Compare commits
3055 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4ea80cf5e | ||
|
|
feacb58cd1 | ||
|
|
1de30c0c38 | ||
|
|
4c30054a2d | ||
|
|
0b9e06c28d | ||
|
|
37e4a99ba6 | ||
|
|
7078eb7482 | ||
|
|
c2ec97d641 | ||
|
|
2a2a5ffb66 | ||
|
|
b84ef57d58 | ||
|
|
14b066d3cd | ||
|
|
2b5e167b07 | ||
|
|
c9547cbdb8 | ||
|
|
89a76148b4 | ||
|
|
81fd472bb3 | ||
|
|
4ba9c63eb4 | ||
|
|
9e20c5a3e3 | ||
|
|
20e0774df2 | ||
|
|
603244aa6a | ||
|
|
1cc30934c7 | ||
|
|
053f26cd02 | ||
|
|
cc82a088a9 | ||
|
|
e30e384cec | ||
|
|
33691a6507 | ||
|
|
83917f98f5 | ||
|
|
1fe5a61e52 | ||
|
|
dab9bcb9db | ||
|
|
b2ca6206cc | ||
|
|
918c2f8587 | ||
|
|
8f851164d6 | ||
|
|
d215d1998f | ||
|
|
75e3256497 | ||
|
|
58f5a17a83 | ||
|
|
e7c3d797be | ||
|
|
34abd5b8f5 | ||
|
|
8b138d14bb | ||
|
|
e23abd69b5 | ||
|
|
9c16ad456d | ||
|
|
4b851afc6a | ||
|
|
f333148afa | ||
|
|
8d0160a3e7 | ||
|
|
4a02e988c1 | ||
|
|
134472cd4b | ||
|
|
b40a10da7b | ||
|
|
25f5b33d17 | ||
|
|
f57c39bba2 | ||
|
|
99b234eca8 | ||
|
|
9c3c8cc9d1 | ||
|
|
b08e3a5128 | ||
|
|
e48cdc85f7 | ||
|
|
a5da68a7f9 | ||
|
|
7d594ab0d3 | ||
|
|
9ed3d668ee | ||
|
|
0da0a5e027 | ||
|
|
28eb0b65f4 | ||
|
|
1d29572ecd | ||
|
|
07e8d242d1 | ||
|
|
1586a286d8 | ||
|
|
4859059eba | ||
|
|
f2949c1836 | ||
|
|
cd6acfb91d | ||
|
|
2d5dc9a6aa | ||
|
|
87e7da2aff | ||
|
|
461eb38d88 | ||
|
|
ba0bb62fa3 | ||
|
|
1ca62dd38e | ||
|
|
1b1328c601 | ||
|
|
9633036887 | ||
|
|
e3d76ea9f4 | ||
|
|
d7212e69b5 | ||
|
|
ead58bd6f6 | ||
|
|
fbe13b75df | ||
|
|
6085a8231f | ||
|
|
e15cd190b3 | ||
|
|
3d55423deb | ||
|
|
f62df52c1d | ||
|
|
7829f94ac4 | ||
|
|
e9d42b9cdd | ||
|
|
1f05a8d92a | ||
|
|
69ae2b2997 | ||
|
|
b86e47de02 | ||
|
|
ea7647f43c | ||
|
|
ae7df52780 | ||
|
|
bc5737b9b0 | ||
|
|
d0745d1914 | ||
|
|
2b4c926a70 | ||
|
|
d922c1c80f | ||
|
|
67500a7689 | ||
|
|
1c8aa7440c | ||
|
|
d128dbec4c | ||
|
|
676cb8810b | ||
|
|
189e3d5599 | ||
|
|
009d0b39f9 | ||
|
|
81a8aa7c3d | ||
|
|
6c6761d14b | ||
|
|
7d2e3df929 | ||
|
|
f334c696cb | ||
|
|
db974d72d5 | ||
|
|
c15e342bb8 | ||
|
|
dc1449c7b6 | ||
|
|
0b305caf58 | ||
|
|
8f1f3645b2 | ||
|
|
0079162efe | ||
|
|
7afec06d4c | ||
|
|
29f85a8fd2 | ||
|
|
6e0dc24eca | ||
|
|
cee1180aa7 | ||
|
|
6db2b55e63 | ||
|
|
a3c038781f | ||
|
|
59c9e5397e | ||
|
|
a4c253b9a9 | ||
|
|
f12b4faf34 | ||
|
|
ff49759f42 | ||
|
|
01d0c738bc | ||
|
|
d57554a48c | ||
|
|
b16b57f38b | ||
|
|
12177446a2 | ||
|
|
61b15db958 | ||
|
|
349e8f5139 | ||
|
|
f30482808b | ||
|
|
79cdecdff6 | ||
|
|
336dee53cd | ||
|
|
77022bbd7f | ||
|
|
df96df776d | ||
|
|
67bc803859 | ||
|
|
8ef56c6d91 | ||
|
|
d377d1e1cf | ||
|
|
4209e4d90d | ||
|
|
83c85d02ee | ||
|
|
866b72d029 | ||
|
|
4bc0f44789 | ||
|
|
99c55cb22f | ||
|
|
74c73c695f | ||
|
|
b972891337 | ||
|
|
57515d54db | ||
|
|
0ff8dcc8e9 | ||
|
|
38efa6a2ba | ||
|
|
6306625184 | ||
|
|
1803ab303f | ||
|
|
e72dd7c845 | ||
|
|
87288caeb9 | ||
|
|
79b519e462 | ||
|
|
5f8ea2aecc | ||
|
|
94bc52a0c3 | ||
|
|
fed51bdcd9 | ||
|
|
5fc9689645 | ||
|
|
7c6a783fc8 | ||
|
|
764d479d7f | ||
|
|
ec15f29e40 | ||
|
|
2c12bee79b | ||
|
|
1120866b75 | ||
|
|
b362c069e5 | ||
|
|
4b6b18c182 | ||
|
|
80efc8c60c | ||
|
|
99168157fc | ||
|
|
23c3263562 | ||
|
|
1179a78fe1 | ||
|
|
82677ddd85 | ||
|
|
31f29e9086 | ||
|
|
3b3e606573 | ||
|
|
18b713cec3 | ||
|
|
2a6d385cea | ||
|
|
4cc1926899 | ||
|
|
15b2c2b739 | ||
|
|
197bf56271 | ||
|
|
4110f4b8ce | ||
|
|
becbaca858 | ||
|
|
add50257f6 | ||
|
|
f061ee5f88 | ||
|
|
480b81b3dd | ||
|
|
61d4a795ae | ||
|
|
cd89883dbb | ||
|
|
d5a729a2ba | ||
|
|
b41533c278 | ||
|
|
04758587b4 | ||
|
|
b6b0969879 | ||
|
|
18ef97fae6 | ||
|
|
333f052f86 | ||
|
|
7dd40eccf3 | ||
|
|
db728840a0 | ||
|
|
8906436824 | ||
|
|
e8dedb04a5 | ||
|
|
d4b581c007 | ||
|
|
a900beb3fd | ||
|
|
19a0f77c53 | ||
|
|
6dbd97ba14 | ||
|
|
d2fbea8e39 | ||
|
|
86a49c6223 | ||
|
|
e97f9b47d7 | ||
|
|
ee3ed5f660 | ||
|
|
3446f3d1e0 | ||
|
|
69d03a7a42 | ||
|
|
bab95cbefa | ||
|
|
5ef23fa49a | ||
|
|
f4ff63485a | ||
|
|
c20fbe8635 | ||
|
|
662cf65ff2 | ||
|
|
7ded517b20 | ||
|
|
4be31b0dad | ||
|
|
dc439ba5be | ||
|
|
5ba8a05450 | ||
|
|
7ef19b318a | ||
|
|
2ac76ad852 | ||
|
|
f4598f81c9 | ||
|
|
c432dbb5bc | ||
|
|
d0f0bb799e | ||
|
|
a98dbfdf4f | ||
|
|
a71909acd3 | ||
|
|
ea5953a397 | ||
|
|
4ad9ccabe0 | ||
|
|
17640d44fa | ||
|
|
812d471573 | ||
|
|
fa981d5a83 | ||
|
|
202f2c6cb0 | ||
|
|
55359bfa24 | ||
|
|
95fcfce9cd | ||
|
|
3120a2c43f | ||
|
|
7ba3a59dea | ||
|
|
eb5f8fcfa1 | ||
|
|
5014227028 | ||
|
|
7a76de2e4c | ||
|
|
de5692c1af | ||
|
|
555e4f0e65 | ||
|
|
723c670100 | ||
|
|
2f951dc272 | ||
|
|
0daabdc21c | ||
|
|
38a187e9fc | ||
|
|
5a613231e0 | ||
|
|
28a35e7260 | ||
|
|
461a5a780d | ||
|
|
207260821b | ||
|
|
466527884f | ||
|
|
9d03eb2643 | ||
|
|
c801202642 | ||
|
|
95952fae75 | ||
|
|
f62629b513 | ||
|
|
f04087815c | ||
|
|
255b1c63d0 | ||
|
|
9b5b8ddc22 | ||
|
|
d0a66f1701 | ||
|
|
c176ac600b | ||
|
|
cf0ab16533 | ||
|
|
03d0e2157e | ||
|
|
cdd5137ebe | ||
|
|
0a924b2c29 | ||
|
|
43acecfc6e | ||
|
|
5e7e739589 | ||
|
|
0b968b6a98 | ||
|
|
f14dfb6c17 | ||
|
|
cb5ccd8166 | ||
|
|
bfbcbb686d | ||
|
|
744300744c | ||
|
|
9bac099339 | ||
|
|
135c9fb64d | ||
|
|
4ed6fbbd74 | ||
|
|
4d3e9dc49b | ||
|
|
319360f8d0 | ||
|
|
3ef990b0bf | ||
|
|
b8ae46b6df | ||
|
|
113aba0897 | ||
|
|
a51672f3ee | ||
|
|
f08b3eb006 | ||
|
|
66f65093fc | ||
|
|
d78944e03b | ||
|
|
2fe31b876f | ||
|
|
9949ea364a | ||
|
|
77b7f7bfad | ||
|
|
8d4b458a22 | ||
|
|
2df8e77733 | ||
|
|
c21011a17a | ||
|
|
a11a691788 | ||
|
|
81659d4bf2 | ||
|
|
aab20fd23e | ||
|
|
5fad4dd034 | ||
|
|
7bc19e8185 | ||
|
|
45d0928ff9 | ||
|
|
9b768273f4 | ||
|
|
ef24b17a70 | ||
|
|
dfbe5aaa16 | ||
|
|
f499c9ada9 | ||
|
|
c1a73aa62a | ||
|
|
601e787500 | ||
|
|
d24bfabdc1 | ||
|
|
2c559d63f5 | ||
|
|
b5a1554631 | ||
|
|
510e1c7296 | ||
|
|
c6d8af5dc3 | ||
|
|
adf884c2c4 | ||
|
|
c7b321315c | ||
|
|
9f2eefcbb3 | ||
|
|
fc2e39f41b | ||
|
|
eae86d15ef | ||
|
|
361d80da17 | ||
|
|
2597402496 | ||
|
|
c8bc6f9ffe | ||
|
|
b0ef9238ff | ||
|
|
b71e503a01 | ||
|
|
e9f96593c3 | ||
|
|
36aa641cb9 | ||
|
|
ddb46646fa | ||
|
|
96dc79cfe6 | ||
|
|
e0e9f14a5e | ||
|
|
b24e1142f8 | ||
|
|
0543b16de9 | ||
|
|
8d46c09f95 | ||
|
|
5724ca73b4 | ||
|
|
3e09bef613 | ||
|
|
627b1fe33f | ||
|
|
1aa270485c | ||
|
|
ae09c19b69 | ||
|
|
c5cf8eef1a | ||
|
|
e76d4b3474 | ||
|
|
88a44ee065 | ||
|
|
51e02da277 | ||
|
|
e9c3e42aa6 | ||
|
|
93a0063941 | ||
|
|
26a3cf79c5 | ||
|
|
26999afc22 | ||
|
|
81729e4b2a | ||
|
|
4bae5ee2fb | ||
|
|
a786e6c8f5 | ||
|
|
3803f36aa5 | ||
|
|
55bc26bd09 | ||
|
|
d84037a0dd | ||
|
|
1ce5fcafd9 | ||
|
|
281233f48b | ||
|
|
68d73e088d | ||
|
|
b433191b35 | ||
|
|
d75ad44315 | ||
|
|
c3d3c3a6e9 | ||
|
|
b9b8ccb8ae | ||
|
|
5a56a7c8af | ||
|
|
d4efb63f3d | ||
|
|
2ec349e919 | ||
|
|
772770273a | ||
|
|
fa5cbfc304 | ||
|
|
5276321ade | ||
|
|
6303602323 | ||
|
|
486fb0d10a | ||
|
|
74b8a08251 | ||
|
|
2a244bb8d4 | ||
|
|
84e73943f7 | ||
|
|
ace09ca5a7 | ||
|
|
a9ae34b149 | ||
|
|
cff778fe6a | ||
|
|
be69f9f8a3 | ||
|
|
5ca2078461 | ||
|
|
4461e7225f | ||
|
|
49d5d10d77 | ||
|
|
84374f03e9 | ||
|
|
f8a44014f7 | ||
|
|
6befb64691 | ||
|
|
1ff2c21c61 | ||
|
|
c79d4a24c4 | ||
|
|
3d7a5676d8 | ||
|
|
aa362477e8 | ||
|
|
13b524e8a5 | ||
|
|
d6eb6d3e3e | ||
|
|
91b8f1a457 | ||
|
|
c8cdcfc99f | ||
|
|
fe20e738cd | ||
|
|
e23856bf10 | ||
|
|
a7de7fb286 | ||
|
|
a931d2a91f | ||
|
|
c94c66b71e | ||
|
|
cb89c30591 | ||
|
|
1012c0f654 | ||
|
|
9b5fb9ae8f | ||
|
|
c4055271a8 | ||
|
|
cd1df37ed3 | ||
|
|
3d8d4fd921 | ||
|
|
17b0c3e48d | ||
|
|
f364257db9 | ||
|
|
6b0d9f8551 | ||
|
|
f0fb420a8d | ||
|
|
8aa2695263 | ||
|
|
b9af8ee6be | ||
|
|
7077289840 | ||
|
|
bdd35fb02a | ||
|
|
47660c5679 | ||
|
|
28573f9676 | ||
|
|
375b7f6dd7 | ||
|
|
99ec2d5ce7 | ||
|
|
f2afd654f8 | ||
|
|
d42919285b | ||
|
|
33a1f135e0 | ||
|
|
214b836d13 | ||
|
|
408a07e8b9 | ||
|
|
b247731062 | ||
|
|
dcaa484929 | ||
|
|
35886633e5 | ||
|
|
d04afc26e7 | ||
|
|
bb5f1b703e | ||
|
|
dfe2d27709 | ||
|
|
1dec4f0070 | ||
|
|
89b6513217 | ||
|
|
16a8caa8db | ||
|
|
1594d190eb | ||
|
|
3333f70a64 | ||
|
|
5bd803e6b4 | ||
|
|
b5f5b096d4 | ||
|
|
dce05140bf | ||
|
|
29d5ac94b2 | ||
|
|
2b80c6c1ad | ||
|
|
94a62b040b | ||
|
|
2bb9c50db9 | ||
|
|
6533ba4581 | ||
|
|
081909572e | ||
|
|
aa84cb0079 | ||
|
|
a66c3700b3 | ||
|
|
70476bd168 | ||
|
|
a7929e142f | ||
|
|
fd0d65b8ce | ||
|
|
ef2a94c2c8 | ||
|
|
b43daf2f08 | ||
|
|
280f628746 | ||
|
|
713774c03f | ||
|
|
0889c1531e | ||
|
|
dbd5810a08 | ||
|
|
c8722e9945 | ||
|
|
87780a2fc8 | ||
|
|
ab03256db0 | ||
|
|
e26640c80e | ||
|
|
e6806453e1 | ||
|
|
d0fb2583a5 | ||
|
|
c4f8f318af | ||
|
|
a6286bb67e | ||
|
|
90aea9708c | ||
|
|
cb076123b3 | ||
|
|
70a9a66ae9 | ||
|
|
8521a47cfa | ||
|
|
106cc5238e | ||
|
|
2040eb22a2 | ||
|
|
b6075a9765 | ||
|
|
daacbcb89d | ||
|
|
6d622bbd14 | ||
|
|
f355da4874 | ||
|
|
4b36de5200 | ||
|
|
88d37e99aa | ||
|
|
1608fc3fdc | ||
|
|
057fd18139 | ||
|
|
b6371a0bdf | ||
|
|
03fe72e0b1 | ||
|
|
3bf4bddc10 | ||
|
|
92dcf19511 | ||
|
|
b238443a9d | ||
|
|
021a39a964 | ||
|
|
72c494e9dc | ||
|
|
42cefd56eb | ||
|
|
944f163882 | ||
|
|
11a8a73723 | ||
|
|
e34cf8f6a6 | ||
|
|
7f8143f06f | ||
|
|
472e513a9f | ||
|
|
1cbacab3a2 | ||
|
|
49bbb8588d | ||
|
|
23e0fe5791 | ||
|
|
6877dfb772 | ||
|
|
f65b33f3fc | ||
|
|
3daddf2fe6 | ||
|
|
efccf2729b | ||
|
|
3a1cd8f67f | ||
|
|
53c90429d3 | ||
|
|
7b5384a7d5 | ||
|
|
2b362d8eaf | ||
|
|
ce0024a43c | ||
|
|
888696975d | ||
|
|
da5852d330 | ||
|
|
81fa8544dd | ||
|
|
e407286c39 | ||
|
|
908f7b8985 | ||
|
|
98edbcaeb2 | ||
|
|
482b7e8017 | ||
|
|
acf295a259 | ||
|
|
a0667da4de | ||
|
|
f95ad86d5b | ||
|
|
72f03c75c8 | ||
|
|
14cb8f0014 | ||
|
|
0d57870311 | ||
|
|
fb6fca152f | ||
|
|
11a33455ce | ||
|
|
124076ed72 | ||
|
|
294f591152 | ||
|
|
f9414dc815 | ||
|
|
99c1e0e262 | ||
|
|
f6c344873d | ||
|
|
f8f768337e | ||
|
|
c64694e40f | ||
|
|
116791f29f | ||
|
|
69fd7e0b7d | ||
|
|
ac539d1f90 | ||
|
|
9774a17f7e | ||
|
|
1f7b0c076c | ||
|
|
51c6c37ea6 | ||
|
|
790de8cfa6 | ||
|
|
f49f2ecb6c | ||
|
|
9647fb358b | ||
|
|
e9e28ae26a | ||
|
|
60032c186d | ||
|
|
e7011ca0a5 | ||
|
|
0382113567 | ||
|
|
18fe633979 | ||
|
|
2d8b4d9c2a | ||
|
|
d4d6050862 | ||
|
|
6bed5265e2 | ||
|
|
a1b4fdf624 | ||
|
|
b9ea1573ea | ||
|
|
7a56545e9e | ||
|
|
2bf9b66af7 | ||
|
|
215a6faae9 | ||
|
|
61f37e0260 | ||
|
|
b2c434a1fd | ||
|
|
0d2bcbf25b | ||
|
|
a3d1838a8c | ||
|
|
692fb1a68c | ||
|
|
c71d915a4b | ||
|
|
a0b5dec8b9 | ||
|
|
e2f71b10ec | ||
|
|
743e4fce0b | ||
|
|
d97c608323 | ||
|
|
89baa3cabf | ||
|
|
d83712b093 | ||
|
|
806309fc33 | ||
|
|
70f6343a2c | ||
|
|
03dca869c8 | ||
|
|
84a10d4eb1 | ||
|
|
554a77fbca | ||
|
|
e12f5e41ff | ||
|
|
79ad003bc6 | ||
|
|
fc417022c9 | ||
|
|
f427d9f1c4 | ||
|
|
409f185f7e | ||
|
|
6b080455ff | ||
|
|
da726ecd15 | ||
|
|
a8f61878ca | ||
|
|
73e929f0cf | ||
|
|
60420c3e32 | ||
|
|
a02e933375 | ||
|
|
73df6519f0 | ||
|
|
ac3a34ff58 | ||
|
|
8d85b521c8 | ||
|
|
6d89010a1f | ||
|
|
8c85fdd7b5 | ||
|
|
cc535b0d0a | ||
|
|
d275b56dc1 | ||
|
|
ad1fc9b9c7 | ||
|
|
1ea6fb9300 | ||
|
|
9d96ab8f6a | ||
|
|
4f518d2315 | ||
|
|
7377476f97 | ||
|
|
a55bd4458c | ||
|
|
22cb7f7d8f | ||
|
|
7b46595503 | ||
|
|
aa30f6ef98 | ||
|
|
5107cd28c4 | ||
|
|
b537d73a55 | ||
|
|
9a5c49bd08 | ||
|
|
19cf204dc4 | ||
|
|
a75baba1f6 | ||
|
|
a2dd45fd69 | ||
|
|
b90cdb8686 | ||
|
|
16e79c6546 | ||
|
|
f3fbff291f | ||
|
|
f994088d38 | ||
|
|
091a49ff78 | ||
|
|
357313b555 | ||
|
|
3b64d8b0a5 | ||
|
|
6fa95d9f4f | ||
|
|
15ff5ede7e | ||
|
|
d89c826e18 | ||
|
|
5e485fb87e | ||
|
|
6b7e8bef1d | ||
|
|
5cb2312806 | ||
|
|
aa7543ad0c | ||
|
|
b6df80dcef | ||
|
|
c0ad75cc4d | ||
|
|
612002ec33 | ||
|
|
bb96b96e24 | ||
|
|
49fc63d422 | ||
|
|
350315fa56 | ||
|
|
fa859a3b5d | ||
|
|
b2f5110871 | ||
|
|
18d0cae6b0 | ||
|
|
f09b03338e | ||
|
|
6e011ae70e | ||
|
|
854fbe53be | ||
|
|
1ef252fbc2 | ||
|
|
aaebe01892 | ||
|
|
83efffb7f9 | ||
|
|
b89aa4488c | ||
|
|
2029148e7c | ||
|
|
8b33414c55 | ||
|
|
0e177a7a4c | ||
|
|
11fc6a61d5 | ||
|
|
ca5ab6edf5 | ||
|
|
bbefca71e5 | ||
|
|
001adcee62 | ||
|
|
4870cdd76f | ||
|
|
3dc8e87a27 | ||
|
|
1cd069df5e | ||
|
|
4dd1a960c1 | ||
|
|
2c8dc3e6a7 | ||
|
|
49f8b3b7f6 | ||
|
|
dd9dc34308 | ||
|
|
a8b41945d0 | ||
|
|
fa776c34de | ||
|
|
a3a4bbbb83 | ||
|
|
52e1276c8d | ||
|
|
241be5eaee | ||
|
|
a32903218e | ||
|
|
6620fc8570 | ||
|
|
388a4d93e4 | ||
|
|
85898d3531 | ||
|
|
1f2e1691f9 | ||
|
|
2693f5f496 | ||
|
|
854f7d7f2e | ||
|
|
1cac67d4c5 | ||
|
|
72970720d2 | ||
|
|
b5c75caea0 | ||
|
|
f421fd771f | ||
|
|
748f3a3a4f | ||
|
|
59ccf6181e | ||
|
|
c7f5e6b5b0 | ||
|
|
10f99673c5 | ||
|
|
aff5e8f44d | ||
|
|
7db5a48e35 | ||
|
|
fe73e76fe9 | ||
|
|
faa22feebf | ||
|
|
9773c02e7d | ||
|
|
628902bb70 | ||
|
|
c2e981b35a | ||
|
|
2f40eeb49f | ||
|
|
cfb2501576 | ||
|
|
4057906b2c | ||
|
|
93fe97b94d | ||
|
|
aa2df465a0 | ||
|
|
350438b2c4 | ||
|
|
075499b695 | ||
|
|
b361adbe30 | ||
|
|
c448322367 | ||
|
|
b6d4b58f86 | ||
|
|
bbb00ff36f | ||
|
|
07dc823528 | ||
|
|
b9ae97e5ec | ||
|
|
dfafbdd882 | ||
|
|
35d0227862 | ||
|
|
c8842cc71f | ||
|
|
620974217a | ||
|
|
392d47852d | ||
|
|
f714cd66f7 | ||
|
|
425e196dfc | ||
|
|
1ffe617287 | ||
|
|
ea93d197ab | ||
|
|
37c569a976 | ||
|
|
7a189bd5e5 | ||
|
|
d3876eb7b0 | ||
|
|
64cb848a37 | ||
|
|
162e51a0af | ||
|
|
59b9991a2c | ||
|
|
97128673ff | ||
|
|
fdac444aed | ||
|
|
c656903772 | ||
|
|
61b5ab8a49 | ||
|
|
550df1be89 | ||
|
|
99c14533a5 | ||
|
|
b759fdb6e3 | ||
|
|
374e1f65c6 | ||
|
|
3d6526de3e | ||
|
|
8f43c7d3d8 | ||
|
|
e5b7ad5be2 | ||
|
|
8227ce1158 | ||
|
|
35b80178ed | ||
|
|
80b0dba9fe | ||
|
|
a5497dc215 | ||
|
|
964fb5d251 | ||
|
|
e24ee05337 | ||
|
|
c6858d505f | ||
|
|
0ea1e47176 | ||
|
|
5355b91f37 | ||
|
|
86e7eb1087 | ||
|
|
043d89c03b | ||
|
|
1cbad1057d | ||
|
|
d906771b18 | ||
|
|
76ef9c0388 | ||
|
|
262d96f8d7 | ||
|
|
41b7466325 | ||
|
|
76f2c5f9fc | ||
|
|
e5a1fc9e2d | ||
|
|
11f9e260ed | ||
|
|
e209bdec65 | ||
|
|
6432851a78 | ||
|
|
31fb22a7c3 | ||
|
|
bc47e30ad3 | ||
|
|
58cf7c720f | ||
|
|
48bf73de80 | ||
|
|
76a3f4e86c | ||
|
|
3a760282f1 | ||
|
|
71affc0239 | ||
|
|
3b95d23d23 | ||
|
|
8cd5345f8c | ||
|
|
fda393b5e1 | ||
|
|
264f9f84ed | ||
|
|
1d73760901 | ||
|
|
03a13df47b | ||
|
|
5160f22d91 | ||
|
|
3bbc2bf986 | ||
|
|
90f68da42f | ||
|
|
f37438b7a7 | ||
|
|
826d124a5f | ||
|
|
c162fd178b | ||
|
|
9b92e48a6e | ||
|
|
5b5c15b7f3 | ||
|
|
6e9cd4c11b | ||
|
|
8c03c73b28 | ||
|
|
2c10ceba5b | ||
|
|
2a3110cd3d | ||
|
|
924ea435b1 | ||
|
|
0e4a389910 | ||
|
|
720dc14ecf | ||
|
|
51f5f0b82d | ||
|
|
f380a6f8cf | ||
|
|
437a033739 | ||
|
|
2b77e4d292 | ||
|
|
0e104ee936 | ||
|
|
a820bf7bd0 | ||
|
|
09fdec8fbd | ||
|
|
80f6d733b9 | ||
|
|
838345ba46 | ||
|
|
c2378d33b4 | ||
|
|
95575bc040 | ||
|
|
2926871eab | ||
|
|
5b05ea285c | ||
|
|
48a2e6881f | ||
|
|
edbeaa2f77 | ||
|
|
48a85a620d | ||
|
|
cc8db71ecf | ||
|
|
e4573f74a4 | ||
|
|
8cff72cf59 | ||
|
|
73a9de7708 | ||
|
|
104318ab8c | ||
|
|
8ec4659949 | ||
|
|
ffa8ff8427 | ||
|
|
4ef1339ba2 | ||
|
|
3702efdcb3 | ||
|
|
bbdfbe1ab7 | ||
|
|
cc1fc5c269 | ||
|
|
bc32fa64bf | ||
|
|
cfc7de9c77 | ||
|
|
945ab30373 | ||
|
|
494125227f | ||
|
|
a4919b06f9 | ||
|
|
790ba406bf | ||
|
|
e0367056bd | ||
|
|
4bf0dc192c | ||
|
|
4575a0ddce | ||
|
|
837cbff092 | ||
|
|
4108047644 | ||
|
|
347cf4f67d | ||
|
|
7f9344a556 | ||
|
|
8907b692c1 | ||
|
|
6c0d5cb601 | ||
|
|
5c69a146f6 | ||
|
|
de75ae5b9e | ||
|
|
9c9e2c6a62 | ||
|
|
917c18a423 | ||
|
|
aac81c2fba | ||
|
|
9e82839fb7 | ||
|
|
ae2f74777b | ||
|
|
4c5d67606f | ||
|
|
0d2a0f91c7 | ||
|
|
b65fa3e2c7 | ||
|
|
e87d2e1218 | ||
|
|
00ae320b51 | ||
|
|
3d46d24038 | ||
|
|
8b04484ff7 | ||
|
|
7f9f3f683b | ||
|
|
fb2ce06621 | ||
|
|
89f5e87601 | ||
|
|
e124755363 | ||
|
|
d0ccbe2786 | ||
|
|
25dec602b8 | ||
|
|
bbf7007250 | ||
|
|
2b4f8ff00d | ||
|
|
b467b58ee7 | ||
|
|
facefeddae | ||
|
|
141bdb1307 | ||
|
|
b53da61e7c | ||
|
|
ede93323af | ||
|
|
8ccf79175a | ||
|
|
9fa330a0a0 | ||
|
|
3693857960 | ||
|
|
c5f97e8bb0 | ||
|
|
2cb7b4d1ea | ||
|
|
6247cece94 | ||
|
|
417f5c3610 | ||
|
|
3e6f3bd807 | ||
|
|
6346c7fe9b | ||
|
|
11c5a3f050 | ||
|
|
10645b1b94 | ||
|
|
e106dcd76a | ||
|
|
cb30a57a59 | ||
|
|
98da4c0011 | ||
|
|
fc0c316ef2 | ||
|
|
eaf363635e | ||
|
|
b91aa0668f | ||
|
|
53c2f5885a | ||
|
|
5717f77e00 | ||
|
|
3f8dfdd938 | ||
|
|
9e1fbedc4d | ||
|
|
f9eb588d4c | ||
|
|
181ee43107 | ||
|
|
cc30bc1897 | ||
|
|
1232b30e29 | ||
|
|
03aae46880 | ||
|
|
25ce947df5 | ||
|
|
b8f486d8e4 | ||
|
|
6305ff7410 | ||
|
|
b2941894cd | ||
|
|
83056519ec | ||
|
|
3cdfbbac56 | ||
|
|
f61e85c2d6 | ||
|
|
217ebf8c33 | ||
|
|
b32114f2f2 | ||
|
|
6209cdbe0e | ||
|
|
afde81ef3e | ||
|
|
fbbd71e7f2 | ||
|
|
54cf168b4d | ||
|
|
c25b14976c | ||
|
|
39c68075fb | ||
|
|
ce15958a9a | ||
|
|
8d06defbcb | ||
|
|
0d807a37d6 | ||
|
|
9a0a2d84da | ||
|
|
29e2be47d0 | ||
|
|
b2e1f66dbb | ||
|
|
bfe9ee457d | ||
|
|
a034b70449 | ||
|
|
4226654772 | ||
|
|
4ea8ab08a3 | ||
|
|
702fc120af | ||
|
|
9453084481 | ||
|
|
c6dbbc4135 | ||
|
|
ddc53bcb6f | ||
|
|
e50509ac45 | ||
|
|
2ddba469b2 | ||
|
|
4e1b2ccbaa | ||
|
|
e0b8a2400a | ||
|
|
151ba569a7 | ||
|
|
2cb755fe44 | ||
|
|
eeef49fd19 | ||
|
|
6b2626120c | ||
|
|
e77ab26516 | ||
|
|
dbaf6c6ce2 | ||
|
|
5e295f9f1e | ||
|
|
8d3b655517 | ||
|
|
64cefd52c8 | ||
|
|
edb92ed0a5 | ||
|
|
a8513cc0fa | ||
|
|
20d4ce6632 | ||
|
|
d8c3ce30ca | ||
|
|
d894de0784 | ||
|
|
572bd19df6 | ||
|
|
4fd399eae9 | ||
|
|
f7f55710d1 | ||
|
|
18815b97ce | ||
|
|
c4fce32a6a | ||
|
|
9ed5f43ea1 | ||
|
|
232bce0a2d | ||
|
|
27f975f3c5 | ||
|
|
5b834b4396 | ||
|
|
52b46e2b3e | ||
|
|
044fb72da9 | ||
|
|
0cf911bcdd | ||
|
|
829512dd13 | ||
|
|
fa886c71b8 | ||
|
|
21191bdc50 | ||
|
|
1bf2fe16a2 | ||
|
|
c35543af92 | ||
|
|
9bb71bd066 | ||
|
|
f24e4f291d | ||
|
|
32ab9a9d32 | ||
|
|
8b520dec48 | ||
|
|
70c539ac4d | ||
|
|
610651066a | ||
|
|
aaa750dbbc | ||
|
|
a518ee83cc | ||
|
|
de84b5113c | ||
|
|
2ea7847d4f | ||
|
|
0650fca1cf | ||
|
|
1b5bd0d379 | ||
|
|
5b6f796606 | ||
|
|
9d6a755486 | ||
|
|
9470654394 | ||
|
|
28feadd6c5 | ||
|
|
af3ed04b7f | ||
|
|
2da99673cd | ||
|
|
476adcb029 | ||
|
|
b2c8f87276 | ||
|
|
bd4e132709 | ||
|
|
fa8fcf8761 | ||
|
|
8e92b53d9f | ||
|
|
6f90bd3db0 | ||
|
|
a261d8b754 | ||
|
|
9643b7ed1b | ||
|
|
ec191d51bc | ||
|
|
a5452e4b15 | ||
|
|
8522802f85 | ||
|
|
6f2e3afe07 | ||
|
|
70dfb41d95 | ||
|
|
34f04828c5 | ||
|
|
a78799973d | ||
|
|
1797148951 | ||
|
|
67caa89591 | ||
|
|
e3a88e9f5b | ||
|
|
e9910c9b95 | ||
|
|
45e058bdc1 | ||
|
|
9af5404921 | ||
|
|
5c4ca1b699 | ||
|
|
b6827736db | ||
|
|
aada3f3979 | ||
|
|
dc07078fd4 | ||
|
|
ae8278bdb3 | ||
|
|
286de8cdcb | ||
|
|
ca11d5af94 | ||
|
|
fb04f78112 | ||
|
|
75fa2dfd67 | ||
|
|
137267e604 | ||
|
|
642487f4c5 | ||
|
|
783ad9ecda | ||
|
|
0213a368b9 | ||
|
|
f1e7594b79 | ||
|
|
02fd52e366 | ||
|
|
2d5e0a51bd | ||
|
|
1cd82dcd4c | ||
|
|
5ba30d0236 | ||
|
|
c0ea5c31eb | ||
|
|
adee5fa25f | ||
|
|
f9af84fd85 | ||
|
|
41cb381a2e | ||
|
|
50ca07bfb8 | ||
|
|
07732310c1 | ||
|
|
854661e2d4 | ||
|
|
8cac83ed98 | ||
|
|
5ee8e9da80 | ||
|
|
f5c81f5882 | ||
|
|
a415b70adf | ||
|
|
800a7e26e9 | ||
|
|
1bc9dc30f6 | ||
|
|
7d538ee1b8 | ||
|
|
ac5f4cca19 | ||
|
|
54a5d5b9aa | ||
|
|
5c4ec5afc0 | ||
|
|
5bd6001f95 | ||
|
|
0fb8914b67 | ||
|
|
1f6ac49686 | ||
|
|
42887fb1d9 | ||
|
|
f14a7808cb | ||
|
|
a781a46f13 | ||
|
|
6941a12314 | ||
|
|
f0e70a97bc | ||
|
|
c59e3ef4ae | ||
|
|
2bfdc7c1ac | ||
|
|
d831e7d765 | ||
|
|
fe8ef5b922 | ||
|
|
2c150eee33 | ||
|
|
a4d6bafe1a | ||
|
|
78017b8adb | ||
|
|
ea822f66ca | ||
|
|
a55adf12db | ||
|
|
84c016490c | ||
|
|
bb7056d614 | ||
|
|
462b490d05 | ||
|
|
084050bb2f | ||
|
|
8d2ea7e736 | ||
|
|
fe8d5b0d3e | ||
|
|
de724319aa | ||
|
|
ac91b417c3 | ||
|
|
229863d7ff | ||
|
|
8dcb3f2f85 | ||
|
|
15c8f84960 | ||
|
|
f37dd03e4b | ||
|
|
82c97f7e1c | ||
|
|
91078f7a7e | ||
|
|
d2775956e0 | ||
|
|
00b52fa3af | ||
|
|
1ac0ed3c18 | ||
|
|
6ec8246b46 | ||
|
|
f5978a524d | ||
|
|
72030ee8fc | ||
|
|
d6a4dd6965 | ||
|
|
8aa5dc85af | ||
|
|
5c7f99c0ee | ||
|
|
847cb91759 | ||
|
|
9e92d08261 | ||
|
|
bf8e03aa0c | ||
|
|
fcd05f3bb4 | ||
|
|
a14dfc171d | ||
|
|
b8b445eb24 | ||
|
|
fbf4a53a1b | ||
|
|
0c7e810bd3 | ||
|
|
0502779a29 | ||
|
|
576d9ca894 | ||
|
|
d8771509cd | ||
|
|
b139749198 | ||
|
|
bdcb5c502c | ||
|
|
dc72df1dbd | ||
|
|
8be834d0c8 | ||
|
|
c995454f69 | ||
|
|
854e0ebe3f | ||
|
|
f01d2631dd | ||
|
|
60f8cdf3b4 | ||
|
|
8e5bf14623 | ||
|
|
b063ebd6d7 | ||
|
|
eb7d7a2d1b | ||
|
|
f9ee088592 | ||
|
|
1f32d4b4dd | ||
|
|
d3b4c2f394 | ||
|
|
41c00eda74 | ||
|
|
155af33b0c | ||
|
|
b289146aeb | ||
|
|
d2e32a4fd0 | ||
|
|
6631c95166 | ||
|
|
7adabcc203 | ||
|
|
de35a935a6 | ||
|
|
d3d668d930 | ||
|
|
1f60c6dd21 | ||
|
|
1431700642 | ||
|
|
12a1de56fd | ||
|
|
4267208f28 | ||
|
|
25d6ec157f | ||
|
|
b2fc7df06d | ||
|
|
c875371db9 | ||
|
|
dd7818b960 | ||
|
|
0dd6446f3e | ||
|
|
579dc4959b | ||
|
|
27c3170c80 | ||
|
|
7b275008b5 | ||
|
|
2cfea229fd | ||
|
|
e349193745 | ||
|
|
45d68c4da8 | ||
|
|
36d443fa36 | ||
|
|
8549663ed0 | ||
|
|
73b2feae59 | ||
|
|
0871b416a7 | ||
|
|
767bfba670 | ||
|
|
019cbeb617 | ||
|
|
a7d8a8fd1f | ||
|
|
f7e073c857 | ||
|
|
2fdb3668e2 | ||
|
|
f1aee1d9a4 | ||
|
|
057f75ca5f | ||
|
|
314654f319 | ||
|
|
961959d361 | ||
|
|
d603ea50e2 | ||
|
|
3b7bc6beba | ||
|
|
e437168e87 | ||
|
|
cf7d735c56 | ||
|
|
b2a41cc4d5 | ||
|
|
5bc3cb6353 | ||
|
|
e6024ac85b | ||
|
|
4f6fac2336 | ||
|
|
12feb68bf0 | ||
|
|
d5d325bf4e | ||
|
|
47ae1443d1 | ||
|
|
63b51d2fca | ||
|
|
3547be3401 | ||
|
|
a038028c3b | ||
|
|
40cc12e568 | ||
|
|
4a1a915add | ||
|
|
3096b67b76 | ||
|
|
3acceca32f | ||
|
|
e8e05159d8 | ||
|
|
ae0c7390f2 | ||
|
|
11f2acd702 | ||
|
|
1759e257c4 | ||
|
|
3e86c59607 | ||
|
|
dfe5b6b1f2 | ||
|
|
b0026eafb5 | ||
|
|
67519fb203 | ||
|
|
7f4a9d6016 | ||
|
|
317f6e77d4 | ||
|
|
5fcfd32f6c | ||
|
|
0fd056dff9 | ||
|
|
10cf8f1d0e | ||
|
|
67d95cda76 | ||
|
|
3ac66f9dd4 | ||
|
|
43e426ab9f | ||
|
|
a5224258c3 | ||
|
|
ab3a2911c3 | ||
|
|
1cdcab6047 | ||
|
|
2ad8ed5550 | ||
|
|
9226baa63c | ||
|
|
b790d085bb | ||
|
|
933d5c9139 | ||
|
|
2c5fd7effa | ||
|
|
f5a5bebae6 | ||
|
|
f2316ec84e | ||
|
|
84165e5342 | ||
|
|
f65dab114e | ||
|
|
4ad7504be6 | ||
|
|
e9318d7f11 | ||
|
|
01d7d41c17 | ||
|
|
f1fb5f2530 | ||
|
|
ea28c10a39 | ||
|
|
6c84681f35 | ||
|
|
edb3aea880 | ||
|
|
f898925bc0 | ||
|
|
f3be7aa763 | ||
|
|
71c52a87ec | ||
|
|
8c786f38ab | ||
|
|
6bc5826c86 | ||
|
|
90e36c4552 | ||
|
|
f83bd2e3b7 | ||
|
|
367eb1b1e1 | ||
|
|
91e21d69db | ||
|
|
5bcfea161f | ||
|
|
a9e0ee81ce | ||
|
|
c37c513067 | ||
|
|
c0972b3e14 | ||
|
|
1b91ae1ab3 | ||
|
|
4a462597fd | ||
|
|
505c71855e | ||
|
|
2ba0d716d1 | ||
|
|
35ab03c392 | ||
|
|
ddb7551b92 | ||
|
|
fdcc5d68a2 | ||
|
|
ac7c32ad4c | ||
|
|
e93898d2ec | ||
|
|
22fe27da9c | ||
|
|
e31164140c | ||
|
|
7d53eeb7f5 | ||
|
|
d3731ff339 | ||
|
|
02ba2fe59b | ||
|
|
55091cfe8d | ||
|
|
f6e14a5420 | ||
|
|
b38371400c | ||
|
|
0458fee326 | ||
|
|
15256ebbdf | ||
|
|
773435fb7f | ||
|
|
1a674a30ac | ||
|
|
491617e41c | ||
|
|
24fc480f7b | ||
|
|
677f11ba1a | ||
|
|
aa7e307205 | ||
|
|
6ac914904e | ||
|
|
68dd1fbedb | ||
|
|
6869380500 | ||
|
|
3a0febe760 | ||
|
|
46d195557b | ||
|
|
548418ecfe | ||
|
|
28c0d63f89 | ||
|
|
b3eb6ccde3 | ||
|
|
0e09df797b | ||
|
|
7fae0751b9 | ||
|
|
e6cdd1ed7a | ||
|
|
9d8c079d37 | ||
|
|
9bb58b1649 | ||
|
|
d732adf34b | ||
|
|
8718e7efd2 | ||
|
|
b21d29098b | ||
|
|
d010330b58 | ||
|
|
4562024e72 | ||
|
|
34043d5c97 | ||
|
|
a468b6ff39 | ||
|
|
534aa7423e | ||
|
|
be416fd335 | ||
|
|
43962c4a5a | ||
|
|
1b33b2c48c | ||
|
|
efa4c09306 | ||
|
|
181b9cdee6 | ||
|
|
a1c3cd272b | ||
|
|
c67b4a4e51 | ||
|
|
72c97ba224 | ||
|
|
ca96e40397 | ||
|
|
758daee0c9 | ||
|
|
37b6a2568d | ||
|
|
4ee2fd8b14 | ||
|
|
7706be3e2f | ||
|
|
16c2316183 | ||
|
|
ce22100b02 | ||
|
|
d2cc38c8ec | ||
|
|
c0a31ccb55 | ||
|
|
8ddc9e3138 | ||
|
|
7a24c23bdd | ||
|
|
32f4b72d68 | ||
|
|
282df5c2e6 | ||
|
|
6713ba3798 | ||
|
|
355edda058 | ||
|
|
b1141f8cbb | ||
|
|
eaad527e32 | ||
|
|
810922de5e | ||
|
|
da3414e3bc | ||
|
|
99a0c78fe4 | ||
|
|
444d3eeb7c | ||
|
|
a3c00c5f75 | ||
|
|
dfb465ef77 | ||
|
|
b20107ad2a | ||
|
|
6977556984 | ||
|
|
676f25962d | ||
|
|
02fe971f0b | ||
|
|
0b310f849a | ||
|
|
c9c00d2b9f | ||
|
|
910087e37a | ||
|
|
9d99794242 | ||
|
|
3218d7c64d | ||
|
|
3364e5c876 | ||
|
|
a6355e1945 | ||
|
|
a3a8e67ce2 | ||
|
|
ac388e1daf | ||
|
|
625a55ddeb | ||
|
|
6c1b07a7f1 | ||
|
|
b511b0c39a | ||
|
|
5b43de944d | ||
|
|
e255f4158f | ||
|
|
e0740f89d9 | ||
|
|
a4605238aa | ||
|
|
a4e680ee01 | ||
|
|
edf7d80678 | ||
|
|
92e6e99bb0 | ||
|
|
73ed60059f | ||
|
|
78d8e0b5aa | ||
|
|
832eca2d9c | ||
|
|
f69bdd1ac4 | ||
|
|
01f10baa18 | ||
|
|
23178b24c6 | ||
|
|
295aafddf0 | ||
|
|
398b978a5f | ||
|
|
f59999f35f | ||
|
|
e078bf2d2f | ||
|
|
bab1da1ea5 | ||
|
|
593c9f133d | ||
|
|
8071eb2d93 | ||
|
|
f44ff12a5f | ||
|
|
70953333d2 | ||
|
|
e453be1c04 | ||
|
|
6ac2f8d9c3 | ||
|
|
06ca87e041 | ||
|
|
15d1521564 | ||
|
|
4e1396e7a7 | ||
|
|
ab0f8fc081 | ||
|
|
0f29652b96 | ||
|
|
53de61330f | ||
|
|
2c52190966 | ||
|
|
df66a0ff38 | ||
|
|
33ced1c16e | ||
|
|
0b3d3ceb48 | ||
|
|
d385edf348 | ||
|
|
54cd9c7afa | ||
|
|
1ccb24018f | ||
|
|
6bd8e81eae | ||
|
|
edcffd3417 | ||
|
|
1e599731b8 | ||
|
|
f7c85d8aa2 | ||
|
|
75e6c8fad6 | ||
|
|
f16170e0b5 | ||
|
|
74c1e71fe5 | ||
|
|
471dd08016 | ||
|
|
f8e15acf89 | ||
|
|
703621d84e | ||
|
|
0893bf4aa0 | ||
|
|
e44e9f4cf0 | ||
|
|
6cdbebf0d3 | ||
|
|
7b85106792 | ||
|
|
cf2a90845b | ||
|
|
647209cf6d | ||
|
|
5c0d53b52c | ||
|
|
56c2b8798c | ||
|
|
d4262e9fdc | ||
|
|
1902e8206d | ||
|
|
5918952afb | ||
|
|
55cd323159 | ||
|
|
249734f52a | ||
|
|
8530a62421 | ||
|
|
65f1260839 | ||
|
|
fc8a679367 | ||
|
|
cafacf4748 | ||
|
|
5c6ceb2307 | ||
|
|
e05fef18a0 | ||
|
|
9c8aab6e29 | ||
|
|
38267a26c1 | ||
|
|
9e99dae864 | ||
|
|
f9747fd1eb | ||
|
|
bf47368f25 | ||
|
|
7b82950495 | ||
|
|
5dd5a20fc1 | ||
|
|
906e3f8cea | ||
|
|
44ee3c92b7 | ||
|
|
ae55912176 | ||
|
|
703b47d916 | ||
|
|
a1816896ca | ||
|
|
e522b4c7f3 | ||
|
|
daa4f7dfb1 | ||
|
|
39e6463d19 | ||
|
|
f30bc948c3 | ||
|
|
2b0422b2cb | ||
|
|
70149846df | ||
|
|
a8f88d7c4d | ||
|
|
73ddf48d12 | ||
|
|
a9a65fe1f1 | ||
|
|
70eb5c1053 | ||
|
|
defcf7d220 | ||
|
|
1f78253b38 | ||
|
|
40fcdb0fc0 | ||
|
|
9a3a78c96c | ||
|
|
7701b41af4 | ||
|
|
9304d02d78 | ||
|
|
932b9c0966 | ||
|
|
edb33e1f2c | ||
|
|
fc83306d72 | ||
|
|
5bdfe23435 | ||
|
|
503b17acd6 | ||
|
|
ef8c088127 | ||
|
|
151f15fa15 | ||
|
|
35db862d12 | ||
|
|
7948e04ca7 | ||
|
|
b6b9c2a843 | ||
|
|
95109ef9b0 | ||
|
|
7fd49be682 | ||
|
|
f16662bcc0 | ||
|
|
4962597f58 | ||
|
|
19597bb40b | ||
|
|
80bc526401 | ||
|
|
67f1b968bb | ||
|
|
ae0ed07447 | ||
|
|
f5f415e851 | ||
|
|
8a20c1812f | ||
|
|
98d4d99c1b | ||
|
|
a38ef2b6f5 | ||
|
|
5723717576 | ||
|
|
b8f097ff94 | ||
|
|
dcab038020 | ||
|
|
234c192429 | ||
|
|
15af5396f8 | ||
|
|
3fc6da34e8 | ||
|
|
b1dce01b49 | ||
|
|
885dc48a50 | ||
|
|
30962c4c7b | ||
|
|
b993cfd294 | ||
|
|
c8c5862b47 | ||
|
|
0dfd8b9f53 | ||
|
|
0d3450ceed | ||
|
|
073ece0527 | ||
|
|
8020bbd806 | ||
|
|
1ebd4dbda6 | ||
|
|
beebbf54ad | ||
|
|
f8e5a65f95 | ||
|
|
379066c782 | ||
|
|
e96ada8c2e | ||
|
|
0a7d903dd6 | ||
|
|
0afc671763 | ||
|
|
dd183cbca0 | ||
|
|
cc17373166 | ||
|
|
19df2e0baa | ||
|
|
045b4db246 | ||
|
|
59ccf845b5 | ||
|
|
814a48c55f | ||
|
|
4c6cc4abd6 | ||
|
|
34f47fcfd7 | ||
|
|
87e64da0d9 | ||
|
|
730de02874 | ||
|
|
e0fef1da42 | ||
|
|
3bfa7b1cdd | ||
|
|
fcb59091d2 | ||
|
|
9146e2a318 | ||
|
|
aefe69c4b5 | ||
|
|
d1ee3d5688 | ||
|
|
f92cdf36f5 | ||
|
|
8668ff8939 | ||
|
|
50d37ad752 | ||
|
|
c6afe4fd4e | ||
|
|
03be4a22d4 | ||
|
|
85f18f5991 | ||
|
|
0d237a8f55 | ||
|
|
7522ac1eaf | ||
|
|
4704c2a178 | ||
|
|
da818ff577 | ||
|
|
2660f673db | ||
|
|
fec1a1c0ee | ||
|
|
537d0203e1 | ||
|
|
7e00fbfe2d | ||
|
|
b54cfd76dd | ||
|
|
74783eee0e | ||
|
|
3994d5bf75 | ||
|
|
08f7685ca3 | ||
|
|
d08d4962a5 | ||
|
|
42c9166df2 | ||
|
|
4d70a0c5bd | ||
|
|
1202be4686 | ||
|
|
14f93a91e3 | ||
|
|
49de124fc0 | ||
|
|
cc939de641 | ||
|
|
fd6c77c73e | ||
|
|
5c213d31cf | ||
|
|
d8ab1c3a67 | ||
|
|
5157789774 | ||
|
|
69d92ba0a8 | ||
|
|
4686e38a5e | ||
|
|
cab3f60e06 | ||
|
|
f59907d9d7 | ||
|
|
305441ea28 | ||
|
|
807094c829 | ||
|
|
cae1b3f47a | ||
|
|
4c3a8e1fd7 | ||
|
|
0d5c1b99df | ||
|
|
656faacc76 | ||
|
|
b8919f8c11 | ||
|
|
b0c042e9dc | ||
|
|
455116c86f | ||
|
|
4202452e70 | ||
|
|
7df7fd635b | ||
|
|
b4fa2d7ce6 | ||
|
|
8ac3089e0b | ||
|
|
e2f1f3029f | ||
|
|
dd5c438597 | ||
|
|
60982cc276 | ||
|
|
d23ea29bef | ||
|
|
5246ea3537 | ||
|
|
5ad217bd18 | ||
|
|
5d1c6d35f7 | ||
|
|
1d49af144c | ||
|
|
9bdbd49de0 | ||
|
|
e0821d264e | ||
|
|
5cf94ae35b | ||
|
|
c5fbb73fea | ||
|
|
c30b8942e7 | ||
|
|
e21c1bbc59 | ||
|
|
87178985f9 | ||
|
|
0a23332766 | ||
|
|
9a752ac3a2 | ||
|
|
aaed5a47d7 | ||
|
|
6e19a7e862 | ||
|
|
5cd9fe860f | ||
|
|
498e77c46e | ||
|
|
da69644771 | ||
|
|
7c0f4ad255 | ||
|
|
76ec0b6d74 | ||
|
|
c3e604ba49 | ||
|
|
15848d399c | ||
|
|
0c791ec52c | ||
|
|
6938b6e9ac | ||
|
|
a9fe3e1b12 | ||
|
|
c23234d1d8 | ||
|
|
3855beccce | ||
|
|
41932c9127 | ||
|
|
91840904b6 | ||
|
|
9ba4ac9956 | ||
|
|
753092db30 | ||
|
|
f0b07f1155 | ||
|
|
3429060a7b | ||
|
|
8a6016376c | ||
|
|
51d0658bdb | ||
|
|
1cac2f6170 | ||
|
|
88e209d65b | ||
|
|
67103e7113 | ||
|
|
496ada3647 | ||
|
|
405302e2f0 | ||
|
|
0530a58530 | ||
|
|
8ccae822fe | ||
|
|
e45af9b611 | ||
|
|
e8a9bd83d3 | ||
|
|
8d32c853d5 | ||
|
|
9137fb2b31 | ||
|
|
d2eeb19f06 | ||
|
|
43cc91aca2 | ||
|
|
045187fe2d | ||
|
|
834e908edd | ||
|
|
98ba60a51c | ||
|
|
9bcca0a791 | ||
|
|
1a588b34fa | ||
|
|
b3398a09ba | ||
|
|
8fed7034bf | ||
|
|
cfe933c368 | ||
|
|
79968af8ed | ||
|
|
bd58e02a18 | ||
|
|
d5e82110c3 | ||
|
|
da6be5c490 | ||
|
|
c5b7264f1a | ||
|
|
f8015c156e | ||
|
|
23012fbb5c | ||
|
|
f3c0e8a835 | ||
|
|
808428e947 | ||
|
|
60d3eba712 | ||
|
|
817b0f8167 | ||
|
|
116673630a | ||
|
|
82c8fa2640 | ||
|
|
14b51c0c74 | ||
|
|
3c99ccc67b | ||
|
|
c69bc77a7a | ||
|
|
7ff07804d0 | ||
|
|
2f4766af9d | ||
|
|
c2e5f19226 | ||
|
|
ac1bd650ce | ||
|
|
c845b63578 | ||
|
|
4c278a8da5 | ||
|
|
7b48bc1ef6 | ||
|
|
2179f199b7 | ||
|
|
60a3ea0cea | ||
|
|
acaf7cd934 | ||
|
|
38a2fdff39 | ||
|
|
14907849cc | ||
|
|
45ba89c89a | ||
|
|
9d235fa838 | ||
|
|
5ea481409f | ||
|
|
603c2fdc68 | ||
|
|
e384995b63 | ||
|
|
92444c05aa | ||
|
|
5831bb49f1 | ||
|
|
ba14d1e846 | ||
|
|
c8e34ac522 | ||
|
|
d41c20f06c | ||
|
|
30b09856a5 | ||
|
|
3307c0c183 | ||
|
|
fb1af04b55 | ||
|
|
fda439cb38 | ||
|
|
eb8044e3d4 | ||
|
|
842177a0aa | ||
|
|
6913fe1f08 | ||
|
|
aaf2c7f58a | ||
|
|
8c9ed4907b | ||
|
|
d7c1a8f7ae | ||
|
|
f3855b6548 | ||
|
|
82096b67a5 | ||
|
|
a560c9c1ee | ||
|
|
2a089eab08 | ||
|
|
ab4607bf0e | ||
|
|
c9e839f1fd | ||
|
|
33c75076da | ||
|
|
8d9fe13490 | ||
|
|
1752579f9d | ||
|
|
a525104dac | ||
|
|
375fd7a6aa | ||
|
|
cd79191d7a | ||
|
|
904994ae24 | ||
|
|
0a1870d862 | ||
|
|
d1ab79a9e7 | ||
|
|
b37769b935 | ||
|
|
ac7001b96e | ||
|
|
8c0b88d69a | ||
|
|
4381809959 | ||
|
|
54d3cd86b9 | ||
|
|
1720feeeee | ||
|
|
f7b40d5f92 | ||
|
|
31df40a841 | ||
|
|
cdda8649fc | ||
|
|
c44863a9bb | ||
|
|
1e4df539b7 | ||
|
|
823599fd78 | ||
|
|
94852460c1 | ||
|
|
900a789b69 | ||
|
|
013c181aaa | ||
|
|
3b38440385 | ||
|
|
074977c58e | ||
|
|
3625eb01e2 | ||
|
|
bbc5217c81 | ||
|
|
a5515ad08b | ||
|
|
12e4441227 | ||
|
|
fdc4ddf316 | ||
|
|
eb2ebead28 | ||
|
|
a8ed7eb914 | ||
|
|
fd509a9099 | ||
|
|
7bf4b23ee5 | ||
|
|
937dd2be5e | ||
|
|
5f9789f99f | ||
|
|
d6d70163d5 | ||
|
|
f4c830e671 | ||
|
|
950bdb5b76 | ||
|
|
3068ed75ee | ||
|
|
42945e1b42 | ||
|
|
faef230d85 | ||
|
|
a7f0dfdff7 | ||
|
|
da28516a98 | ||
|
|
44e27bf9ab | ||
|
|
72fdc707ee | ||
|
|
4d8b6c5ea7 | ||
|
|
fafa299ae1 | ||
|
|
f779957145 | ||
|
|
ce6a26976c | ||
|
|
b53a6da24a | ||
|
|
438fdaa1b1 | ||
|
|
eb10d0d8d0 | ||
|
|
e1a7056ef8 | ||
|
|
20fa49f8e4 | ||
|
|
4ff90029b1 | ||
|
|
20b75b4065 | ||
|
|
832a25601d | ||
|
|
19682ec21b | ||
|
|
b71e2957d3 | ||
|
|
e7fb444bb3 | ||
|
|
fd2705a49d | ||
|
|
935c9a50ab | ||
|
|
08c2e989fa | ||
|
|
942e595444 | ||
|
|
f2225ff6b6 | ||
|
|
12e073e8cf | ||
|
|
d3b77c3be1 | ||
|
|
2607ad2e24 | ||
|
|
67f0801453 | ||
|
|
eebd36ccc8 | ||
|
|
55d401c098 | ||
|
|
0c1c5ae9e5 | ||
|
|
d7b5d1f947 | ||
|
|
80f253e67c | ||
|
|
39cad02e0d | ||
|
|
0c79dcdf1b | ||
|
|
cb1bc6cfdf | ||
|
|
a7094de40f | ||
|
|
b5c9f034ca | ||
|
|
d875ed5cf5 | ||
|
|
53e4b347de | ||
|
|
fafdf88442 | ||
|
|
0911de205f | ||
|
|
26fc03ee19 | ||
|
|
f406de3089 | ||
|
|
b62f7a7497 | ||
|
|
59b428f24b | ||
|
|
54e8395789 | ||
|
|
2fabfbe8f6 | ||
|
|
28ac9e153e | ||
|
|
dadbf1de90 | ||
|
|
2e16dd983f | ||
|
|
847f57855c | ||
|
|
2d412c019c | ||
|
|
47fc9561ab | ||
|
|
25fa999259 | ||
|
|
f40145412b | ||
|
|
cec15dbfc0 | ||
|
|
69d0790484 | ||
|
|
537a904a49 | ||
|
|
939643c307 | ||
|
|
2ce208854f | ||
|
|
6883b91f8a | ||
|
|
dccdef99c1 | ||
|
|
76ab99bca6 | ||
|
|
fed0c7a330 | ||
|
|
f179d92c9c | ||
|
|
907c6dec47 | ||
|
|
3ea9192f79 | ||
|
|
6a5cd698a4 | ||
|
|
179dd0e4d8 | ||
|
|
4c5763b125 | ||
|
|
37ed1f750e | ||
|
|
9528e26487 | ||
|
|
8143ef1057 | ||
|
|
2056015fa2 | ||
|
|
1d98c76c90 | ||
|
|
bddc65e072 | ||
|
|
1b7a06aaf1 | ||
|
|
fbf12dc764 | ||
|
|
e390a56f05 | ||
|
|
063c272aea | ||
|
|
c00fd0480c | ||
|
|
ca732f9b8b | ||
|
|
d3a0fe64e7 | ||
|
|
90256ba68a | ||
|
|
8b30762f03 | ||
|
|
77436877ef | ||
|
|
840e1c5c5b | ||
|
|
ee179a0bd8 | ||
|
|
2a3ab0ecb2 | ||
|
|
841c7730e7 | ||
|
|
bf8f8d32a9 | ||
|
|
8ba56f8b66 | ||
|
|
dc5e7ab98d | ||
|
|
ca7effe0c0 | ||
|
|
7e543a64e4 | ||
|
|
98ea5a7b70 | ||
|
|
7883839871 | ||
|
|
f8d74bbb6d | ||
|
|
387c399078 | ||
|
|
c184f1e42e | ||
|
|
5c7d19ce13 | ||
|
|
3d4b3edc3a | ||
|
|
a7ffc8a172 | ||
|
|
618d2b993a | ||
|
|
2458b6b388 | ||
|
|
be933b8b78 | ||
|
|
38dcb7bd3e | ||
|
|
a001126704 | ||
|
|
fe513b1a07 | ||
|
|
0825d0511a | ||
|
|
c1ec42a812 | ||
|
|
ae747aa426 | ||
|
|
70cf212178 | ||
|
|
5992658164 | ||
|
|
6e79927bc0 | ||
|
|
8dffd6181d | ||
|
|
c4ee21bdb0 | ||
|
|
1d1197e18a | ||
|
|
cc1ff369a7 | ||
|
|
c89030beee | ||
|
|
4fa65099f9 | ||
|
|
2a90a0a278 | ||
|
|
36ab052dda | ||
|
|
fddbe6a574 | ||
|
|
a887be432b | ||
|
|
cf86645bb5 | ||
|
|
705311f01f | ||
|
|
81429bfa85 | ||
|
|
1016d41d7a | ||
|
|
0ff760fe4a | ||
|
|
f48b1d066e | ||
|
|
90c82ab1e7 | ||
|
|
1a0d1f7d79 | ||
|
|
132132307f | ||
|
|
2a6e6a671e | ||
|
|
c073f2a15b | ||
|
|
cf1e1aac77 | ||
|
|
19893601f2 | ||
|
|
034d35b8a7 | ||
|
|
7ef9e7eb51 | ||
|
|
28e23dfdab | ||
|
|
2c80c4a7d5 | ||
|
|
5c1147bfa4 | ||
|
|
ee79744735 | ||
|
|
410d4a47ed | ||
|
|
ead6d9c7d3 | ||
|
|
4c74908789 | ||
|
|
547d8ae113 | ||
|
|
4fcaae8053 | ||
|
|
c935744f4c | ||
|
|
a01e1bad0f | ||
|
|
3cabbc1328 | ||
|
|
7192439b2c | ||
|
|
ff6cbf6628 | ||
|
|
53e9925880 | ||
|
|
9dfe6242b9 | ||
|
|
ea419509f1 | ||
|
|
a1a683ec56 | ||
|
|
dbe3b6a427 | ||
|
|
e8bd4d05b5 | ||
|
|
1fb0ed9545 | ||
|
|
ea464bdc7d | ||
|
|
d1c2d0b907 | ||
|
|
175b2914b6 | ||
|
|
a2c86daef6 | ||
|
|
b40248a1d5 | ||
|
|
ae3a34287a | ||
|
|
b971f2ab22 | ||
|
|
cbc73f5c9a | ||
|
|
373ef5b7e1 | ||
|
|
89388940ed | ||
|
|
b2c94adabf | ||
|
|
3904f50c1b | ||
|
|
d81fa897ad | ||
|
|
a0792aa469 | ||
|
|
5be03c7ab5 | ||
|
|
fc4da4408c | ||
|
|
83ab701d02 | ||
|
|
59aaabecc7 | ||
|
|
3f07bb5c3a | ||
|
|
94dd1eb0c2 | ||
|
|
07ab079715 | ||
|
|
d559df3ee3 | ||
|
|
69cd766f88 | ||
|
|
276db17f0c | ||
|
|
cfce39c1de | ||
|
|
ef5631bff4 | ||
|
|
62017b3ff5 | ||
|
|
3aafbd2ccb | ||
|
|
100bea981d | ||
|
|
931311f11f | ||
|
|
5e456f378b | ||
|
|
bf315258c5 | ||
|
|
9780db6fa0 | ||
|
|
6d0a24cc95 | ||
|
|
1a3d6e86a8 | ||
|
|
4f5efef922 | ||
|
|
ff269d414e | ||
|
|
c3e746aa74 | ||
|
|
511047874e | ||
|
|
47e40fc762 | ||
|
|
27c113d8ae | ||
|
|
c082f2a1b1 | ||
|
|
12f7a3fca0 | ||
|
|
88d66dee6e | ||
|
|
3460e6d513 | ||
|
|
1831caea08 | ||
|
|
b88885582d | ||
|
|
66650d6dd9 | ||
|
|
0b65f07960 | ||
|
|
b14e6a7860 | ||
|
|
68a8c964ea | ||
|
|
f03ac0133f | ||
|
|
6c1045c545 | ||
|
|
0cdfd5e62b | ||
|
|
a839638478 | ||
|
|
1063dbea02 | ||
|
|
c173db69a9 | ||
|
|
bbbab1b2e5 | ||
|
|
c9b6b5b8e1 | ||
|
|
2386124089 | ||
|
|
9e907f10b1 | ||
|
|
2ec6e47086 | ||
|
|
504e18d9a7 | ||
|
|
b021ff4e21 | ||
|
|
32c50a9793 | ||
|
|
44ae48baf5 | ||
|
|
cc3dc1636b | ||
|
|
545ac689b1 | ||
|
|
e7799fef1c | ||
|
|
d857ca46e0 | ||
|
|
0e3cc97ee6 | ||
|
|
66107cf7a4 | ||
|
|
1e8df5c9d0 | ||
|
|
4f608bdc5f | ||
|
|
3da1bae826 | ||
|
|
48559d3358 | ||
|
|
5d8871a044 | ||
|
|
a684fadf43 | ||
|
|
8c858c6b1e | ||
|
|
7e0803c4b4 | ||
|
|
697b42c70f | ||
|
|
cb52dfdd0f | ||
|
|
db203a5ad8 | ||
|
|
3f4df35a3e | ||
|
|
4661576c8a | ||
|
|
b03bb5a3d7 | ||
|
|
f7d4f9d94e | ||
|
|
c10593e4ac | ||
|
|
47580c6976 | ||
|
|
0fa281083e | ||
|
|
0aca6c2588 | ||
|
|
e181abe797 | ||
|
|
7818219763 | ||
|
|
25d20266b8 | ||
|
|
330505faaf | ||
|
|
f7dd10bc08 | ||
|
|
20cc82e210 | ||
|
|
585885e6a2 | ||
|
|
149af003d4 | ||
|
|
50a5b9861a | ||
|
|
17ce6f7291 | ||
|
|
7047ee9391 | ||
|
|
5e1c32b606 | ||
|
|
38032f0b77 | ||
|
|
6364ea8e57 | ||
|
|
c796e724aa | ||
|
|
63053f46a8 | ||
|
|
8bf8c278f0 | ||
|
|
aa0c186c8c | ||
|
|
5539f74bea | ||
|
|
11a6cf8236 | ||
|
|
ce63dbde1b | ||
|
|
989d843fcb | ||
|
|
32d07e7959 | ||
|
|
50b585c1dd | ||
|
|
e03beba9bc | ||
|
|
e4ceedcac6 | ||
|
|
80edfffc3f | ||
|
|
7a734ebf29 | ||
|
|
197e159b48 | ||
|
|
696632e551 | ||
|
|
b1752de36f | ||
|
|
5967907f86 | ||
|
|
ed288317c4 | ||
|
|
3754021ae8 | ||
|
|
7214ce2ede | ||
|
|
d1dcbd97b7 | ||
|
|
30c0690e90 | ||
|
|
4b79881472 | ||
|
|
b42be9899e | ||
|
|
54c2e670e1 | ||
|
|
e35dbba57d | ||
|
|
e632f07708 | ||
|
|
7f0201b552 | ||
|
|
70de7ffe69 | ||
|
|
7a421205e9 | ||
|
|
3dcc9ad844 | ||
|
|
5548ed1b57 | ||
|
|
32bc082a9f | ||
|
|
4eed77e123 | ||
|
|
8564105ee3 | ||
|
|
4a537dde1a | ||
|
|
2f4d89f32a | ||
|
|
10d74d3b34 | ||
|
|
e1ba78ff61 | ||
|
|
31ee456962 | ||
|
|
717607807a | ||
|
|
56e4af58d3 | ||
|
|
622aecfd6d | ||
|
|
be9adb64bb | ||
|
|
bb257f2bf2 | ||
|
|
76f365f7e8 | ||
|
|
499336e752 | ||
|
|
e53ec3e43c | ||
|
|
8b5fe714e1 | ||
|
|
27c5721e2b | ||
|
|
f3534288f1 | ||
|
|
87a5829f9e | ||
|
|
11e9f0eaf2 | ||
|
|
6f653a603b | ||
|
|
a7bba61b6a | ||
|
|
15ac81c1cd | ||
|
|
6b839c8cdc | ||
|
|
15c25329b6 | ||
|
|
aca85b63ae | ||
|
|
26637c0f1c | ||
|
|
56da5493b3 | ||
|
|
abcc9b374c | ||
|
|
53fc6af1fb | ||
|
|
93db7ec71e | ||
|
|
f15909c814 | ||
|
|
7adae569f5 | ||
|
|
a7bf22cafe | ||
|
|
fc9da4756c | ||
|
|
5c7db14253 | ||
|
|
b42a51cc56 | ||
|
|
9eee7b2582 | ||
|
|
bf8a5e6a11 | ||
|
|
a7e507a137 | ||
|
|
04de621e37 | ||
|
|
dc7f5e3dbc | ||
|
|
c3f45471c7 | ||
|
|
c47d5565c2 | ||
|
|
fd4f3147f9 | ||
|
|
22e23e1e65 | ||
|
|
a470b2cd4e | ||
|
|
8e8b635769 | ||
|
|
83b056738f | ||
|
|
af13c580b3 | ||
|
|
e35197c968 | ||
|
|
58992030dc | ||
|
|
677dfde22e | ||
|
|
e1433cbf2a | ||
|
|
93e48fabdf | ||
|
|
fb424d28b9 | ||
|
|
8b9017224f | ||
|
|
3b50a732b5 | ||
|
|
5852fe54a7 | ||
|
|
2fe84293b3 | ||
|
|
66d1de0821 | ||
|
|
148c0d9213 | ||
|
|
871a6f23e2 | ||
|
|
b043e6bf52 | ||
|
|
4bbae73be1 | ||
|
|
daddbadc06 | ||
|
|
4029b94ff2 | ||
|
|
b74d1cb54a | ||
|
|
6a689e2ae4 | ||
|
|
cf5059b006 | ||
|
|
337c5412b7 | ||
|
|
01b1f7529e | ||
|
|
820aeee659 | ||
|
|
4db5855b74 | ||
|
|
579f5d7c8a | ||
|
|
313256adff | ||
|
|
f2a2e86db7 | ||
|
|
75206dd8ac | ||
|
|
8435063c3f | ||
|
|
8700e1ef65 | ||
|
|
bba48f455e | ||
|
|
6ac0cd421a | ||
|
|
1a471a7c20 | ||
|
|
e851abb5a5 | ||
|
|
85eb88a4a6 | ||
|
|
fd61a0bfbf | ||
|
|
2513ade3c4 | ||
|
|
5b2ad5f87f | ||
|
|
b4b731eaa4 | ||
|
|
2b4a354a8c | ||
|
|
a1d9c5d86c | ||
|
|
744cc51140 | ||
|
|
c73e24c3a2 | ||
|
|
e3bec5039b | ||
|
|
85d9c91e5e | ||
|
|
ca236da385 | ||
|
|
c904a92c22 | ||
|
|
0952b6d68f | ||
|
|
d09f932834 | ||
|
|
ac4c5c6e28 | ||
|
|
0e3bcbe10d | ||
|
|
3b64176c0d | ||
|
|
782ecbd750 | ||
|
|
6b2e98b9be | ||
|
|
4cf1739604 | ||
|
|
369474a0bc | ||
|
|
24975d670e | ||
|
|
61ac1c4ae3 | ||
|
|
8b881ab0b4 | ||
|
|
b291b04d62 | ||
|
|
5a5ce4e665 | ||
|
|
2317c17b4b | ||
|
|
fb02bdb445 | ||
|
|
53d85ac7a2 | ||
|
|
f25534ff0f | ||
|
|
463369f283 | ||
|
|
9377701ad1 | ||
|
|
a98fce2160 | ||
|
|
ccda1b4523 | ||
|
|
ac6f80c274 | ||
|
|
5fd86b781b | ||
|
|
0d28292cfb | ||
|
|
8bf9d38711 | ||
|
|
4caf052199 | ||
|
|
82ea2cd86d | ||
|
|
89c0d5763c | ||
|
|
813409a8fb | ||
|
|
03b7445cb9 | ||
|
|
9f35801f64 | ||
|
|
526f5efb78 | ||
|
|
b3071603d0 | ||
|
|
6f358dd8ea | ||
|
|
a6a715b8c2 | ||
|
|
1ebbfe5d92 | ||
|
|
9e27921867 | ||
|
|
f1057bb4a3 | ||
|
|
48434453e3 | ||
|
|
6e8597e3f7 | ||
|
|
bb98fe824e | ||
|
|
70b57b078d | ||
|
|
8410e541b6 | ||
|
|
4bad752f30 | ||
|
|
68d677f028 | ||
|
|
bee3150193 | ||
|
|
4025ef2070 | ||
|
|
e64cc325d7 | ||
|
|
5c9d323fe9 | ||
|
|
5d55e558fe | ||
|
|
687f126f4f | ||
|
|
2bad06a234 | ||
|
|
61fbb76eeb | ||
|
|
38f8048309 | ||
|
|
540a0761ef | ||
|
|
051563522a | ||
|
|
d86045c64e | ||
|
|
1a2e2f4d51 | ||
|
|
f2fbe6dfee | ||
|
|
5dcecb55c2 | ||
|
|
3bd41013c0 | ||
|
|
aa35099a4d | ||
|
|
6a45d83082 | ||
|
|
25397b94b3 | ||
|
|
d1df48ebb1 | ||
|
|
4a7aa032c2 | ||
|
|
846986987d | ||
|
|
b2d380afcc | ||
|
|
6135e83653 | ||
|
|
f090bbc1c7 | ||
|
|
a10d0e45c9 | ||
|
|
6d5671dd0e | ||
|
|
8a251fe39e | ||
|
|
24d93ea87d | ||
|
|
93aa4f086e | ||
|
|
a357f5a1b8 | ||
|
|
39c0af46b0 | ||
|
|
4e4048be4e | ||
|
|
b5e2c628cd | ||
|
|
6b8b69d324 | ||
|
|
36993703f6 | ||
|
|
713f1239c6 | ||
|
|
cb3dffc7fc | ||
|
|
c0065765d4 | ||
|
|
37621f8548 | ||
|
|
8e18a5fb4c | ||
|
|
a0d96d5a74 | ||
|
|
0c8620e944 | ||
|
|
7fbc883ec0 | ||
|
|
6561a40f2c | ||
|
|
0427d08ede | ||
|
|
a7aec70bc1 | ||
|
|
ad6918d71e | ||
|
|
c7d36ac06e | ||
|
|
9428cf0d06 | ||
|
|
ec17e58eed | ||
|
|
2723f2150b | ||
|
|
9ced45c714 | ||
|
|
42e7233aaa | ||
|
|
4e54e4c22a | ||
|
|
565859b2aa | ||
|
|
fe9ef2e85d | ||
|
|
0a5fedf089 | ||
|
|
45a9235738 | ||
|
|
fd43c75811 | ||
|
|
4271f42685 | ||
|
|
016bfcddad | ||
|
|
26d18031f2 | ||
|
|
4307ff5bf0 | ||
|
|
648d6b2662 | ||
|
|
6f4a3701e7 | ||
|
|
2486aee24d | ||
|
|
19c9d7d59d | ||
|
|
abd640d36b | ||
|
|
a085e9ed54 | ||
|
|
f790ef5a2b | ||
|
|
d6ec588c11 | ||
|
|
ed031c6dc1 | ||
|
|
0a871d57cc | ||
|
|
f1653d4643 | ||
|
|
58bc040953 | ||
|
|
c040206d3a | ||
|
|
e0af49f638 | ||
|
|
7d1f218523 | ||
|
|
c779701d26 | ||
|
|
dc7b425dc5 | ||
|
|
9be00cd546 | ||
|
|
2caf8d6a4e | ||
|
|
27c4069187 | ||
|
|
4b2c0b0771 | ||
|
|
7e1216a3d3 | ||
|
|
a02e3d2ebd | ||
|
|
84297ff473 | ||
|
|
1ffad1ebaf | ||
|
|
2db99e7807 | ||
|
|
d7fdfd6d71 | ||
|
|
241053e1a8 | ||
|
|
6da8396c76 | ||
|
|
79e0a1b94c | ||
|
|
4d94700375 | ||
|
|
1672217dd9 | ||
|
|
313c90ff85 | ||
|
|
227da8dce4 | ||
|
|
84111996b4 | ||
|
|
b23699f0c1 | ||
|
|
0c0610c6c5 | ||
|
|
fb39aa32bb | ||
|
|
ca25c6075b | ||
|
|
a9f474b24d | ||
|
|
1354da01e6 | ||
|
|
6151a1ca7f | ||
|
|
bbe1350f7d | ||
|
|
d9c104613c | ||
|
|
4770b32287 | ||
|
|
89cfe1ef57 | ||
|
|
72d29030d9 | ||
|
|
5cf98922fb | ||
|
|
6a2f2b4efe | ||
|
|
69cb8c5a0a | ||
|
|
1ba9513a4e | ||
|
|
1095e47e6f | ||
|
|
0ebda97b03 | ||
|
|
2d5ef36a7f | ||
|
|
39cbfb84ae | ||
|
|
73a56830b0 | ||
|
|
d924f73ceb | ||
|
|
c44926c2cd | ||
|
|
11a852d49c | ||
|
|
2b30f5591c | ||
|
|
d3661fa9d3 | ||
|
|
a1c66e3808 | ||
|
|
f3fc393617 | ||
|
|
3f6909866f | ||
|
|
3adcfd6b4a | ||
|
|
d42be69735 | ||
|
|
9ed3328496 | ||
|
|
3e5bd096cf | ||
|
|
d5e4d8637c | ||
|
|
c5883ebe8f | ||
|
|
e6d8115e52 | ||
|
|
a9d70fe27e | ||
|
|
3fb314a1cb | ||
|
|
e898639168 | ||
|
|
ef9a17a28a | ||
|
|
16141a7104 | ||
|
|
e496f4f3e2 | ||
|
|
5d42439bf4 | ||
|
|
b60681e9bd | ||
|
|
25684bf4f6 | ||
|
|
8d57ef2be4 | ||
|
|
6143f792f3 | ||
|
|
f0c5b603ee | ||
|
|
b61b45177a | ||
|
|
afd19a7307 | ||
|
|
155a348802 | ||
|
|
733de44d03 | ||
|
|
228532b03e | ||
|
|
54bd10a1db | ||
|
|
674f158877 | ||
|
|
a07d7ffdec | ||
|
|
aadc85cda0 | ||
|
|
43f6d79554 | ||
|
|
fd1aea420e | ||
|
|
dbdad6fce8 | ||
|
|
f48231e309 | ||
|
|
d24189e8aa | ||
|
|
5baa08eb0c | ||
|
|
95eb310a7f | ||
|
|
d112d6308c | ||
|
|
00da650524 | ||
|
|
bb3aae46c5 | ||
|
|
1ca8eeeb50 | ||
|
|
5d4eef50e4 | ||
|
|
2b2123f14d | ||
|
|
8b91b815ba | ||
|
|
5824c8ffd0 | ||
|
|
8788867572 | ||
|
|
f2193ff45c | ||
|
|
1091142614 | ||
|
|
ef22387440 | ||
|
|
61ff04119e | ||
|
|
bb7252042e | ||
|
|
c95e267cdd | ||
|
|
059547e37c | ||
|
|
6dc0e4f5c3 | ||
|
|
8fc9685a1b | ||
|
|
7744568eb8 | ||
|
|
30b6d1cd1d | ||
|
|
fe9585500d | ||
|
|
1ddba4a76f | ||
|
|
53b83909ed | ||
|
|
af75060001 | ||
|
|
315210fe29 | ||
|
|
284c646638 | ||
|
|
39df3d7bad | ||
|
|
8f75f7332d | ||
|
|
c3edf44cb4 | ||
|
|
f933716bf5 | ||
|
|
b37c0fbb95 | ||
|
|
3d057781de | ||
|
|
043180a0fa | ||
|
|
f345212468 | ||
|
|
a6c367ba24 | ||
|
|
1a7eb9f6d8 | ||
|
|
a22fffc8b5 | ||
|
|
7e036cc65f | ||
|
|
7a083e7ce4 | ||
|
|
c6aef98361 | ||
|
|
639b7d9374 | ||
|
|
23f7c1522e | ||
|
|
2e4bc5e218 | ||
|
|
a556237963 | ||
|
|
e8488eb406 | ||
|
|
5363842c4d | ||
|
|
4c5d783699 | ||
|
|
64d067d5a1 | ||
|
|
1845a65085 | ||
|
|
86bad5cb3e | ||
|
|
ad4c88b535 | ||
|
|
55dde26aae | ||
|
|
a93c85ebc9 | ||
|
|
cd45046724 | ||
|
|
804be6d5e4 | ||
|
|
344782099f | ||
|
|
4ffff84540 | ||
|
|
dffa3b7986 | ||
|
|
0f7bc9be52 | ||
|
|
05fc8ed5db | ||
|
|
74a8779c49 | ||
|
|
40631a753f | ||
|
|
5cf266c5be | ||
|
|
0f3eb42332 | ||
|
|
1fa8395847 | ||
|
|
1b6e283ac1 | ||
|
|
7b9504c5b4 | ||
|
|
2b52e21ccf | ||
|
|
c49050ea69 | ||
|
|
53037c96cf | ||
|
|
000e5fa105 | ||
|
|
3ccad9ada9 | ||
|
|
73bd3e513c | ||
|
|
2c2a24c31b | ||
|
|
28a1c254d9 | ||
|
|
203ad6b565 | ||
|
|
0969bb9824 | ||
|
|
c6ae7729d1 | ||
|
|
af719dd8c2 | ||
|
|
f87e257233 | ||
|
|
83d7535d84 | ||
|
|
811cc9c028 | ||
|
|
f14fbfe087 | ||
|
|
446099b1f9 | ||
|
|
bad927e283 | ||
|
|
ccbb3dca9f | ||
|
|
d47b947acf | ||
|
|
6332db8e86 | ||
|
|
d829d43f2f | ||
|
|
8944698df1 | ||
|
|
ccf5f2f60e | ||
|
|
d381f579d3 | ||
|
|
995c0a7afc | ||
|
|
ebba516603 | ||
|
|
9289d80e32 | ||
|
|
d366e10cb9 | ||
|
|
7c30c2f945 | ||
|
|
4ae9821185 | ||
|
|
2283c90da1 | ||
|
|
a32d2c6f4d | ||
|
|
208edfcebd | ||
|
|
6ec869505e | ||
|
|
4135040007 | ||
|
|
67c3883cb4 | ||
|
|
30b3be8194 | ||
|
|
594a2e759a | ||
|
|
46e6a048d4 | ||
|
|
426fe6e3c1 | ||
|
|
4bfaf1728d | ||
|
|
83aaa9e8f0 | ||
|
|
6adf26f4d9 | ||
|
|
ac9ffa3f0f | ||
|
|
7a94216b3a | ||
|
|
fd361ef5cb | ||
|
|
314e20ea18 | ||
|
|
48bf21a537 | ||
|
|
f6de9918b5 | ||
|
|
c37ecab029 | ||
|
|
a50d7e2c60 | ||
|
|
38ff515d68 | ||
|
|
ff2cb31f0f | ||
|
|
85fc467845 | ||
|
|
1289a6e14f | ||
|
|
a88d523559 | ||
|
|
48e2a79d8f | ||
|
|
56c671149e | ||
|
|
d37621044c | ||
|
|
f3087773e3 | ||
|
|
94681fd47d | ||
|
|
c2678efc06 | ||
|
|
e682a77858 | ||
|
|
89e3ce06fa | ||
|
|
d1afc9c10a | ||
|
|
f3ac263238 | ||
|
|
2d3c1b7702 | ||
|
|
e028eadf60 | ||
|
|
1cd94b4f7a | ||
|
|
fd70f456e9 | ||
|
|
f03b23497a | ||
|
|
1842afa7c6 | ||
|
|
41901be95f | ||
|
|
93261c63b5 | ||
|
|
95dfe5361d | ||
|
|
e5b27af055 | ||
|
|
b2c48af53f | ||
|
|
b0f0a34672 | ||
|
|
9c477710b9 | ||
|
|
3c01673741 | ||
|
|
28743efb60 | ||
|
|
eb201d3474 | ||
|
|
b54d34127e | ||
|
|
fcfc9572f1 | ||
|
|
c0f0084e56 | ||
|
|
7e3162d287 | ||
|
|
c231184c28 | ||
|
|
08294f5f39 | ||
|
|
048afdc232 | ||
|
|
8779de448d | ||
|
|
3770f07720 | ||
|
|
f53180a960 | ||
|
|
6b6c1b98be | ||
|
|
65405da8d1 | ||
|
|
3df54eac21 | ||
|
|
68c1cd83a7 | ||
|
|
be3696ff8c | ||
|
|
9666deca6d | ||
|
|
87d25336e7 | ||
|
|
11f4b3d869 | ||
|
|
2ed7f152b7 | ||
|
|
6e21f19bd5 | ||
|
|
8e205207b0 | ||
|
|
892ff38a3f | ||
|
|
3428b95672 | ||
|
|
64cb966683 | ||
|
|
8bcff36745 | ||
|
|
d985a66eff | ||
|
|
16f855f173 | ||
|
|
31500076d1 | ||
|
|
d955f0e3d8 | ||
|
|
4615418000 | ||
|
|
9ad0799b48 | ||
|
|
60b1dcf5ee | ||
|
|
d0c9e17090 | ||
|
|
e829c2031c | ||
|
|
85ea71d9aa | ||
|
|
e14dd36a0a | ||
|
|
cf210c5a5a | ||
|
|
ce571bad81 | ||
|
|
55b0fb69ac | ||
|
|
e04f3e317e | ||
|
|
8f2b6cf44e | ||
|
|
ee0ac7cbed | ||
|
|
87fd1a5f38 | ||
|
|
c0ef2eb559 | ||
|
|
b7cc592fb1 | ||
|
|
1d2c3a748b | ||
|
|
405529e8f6 | ||
|
|
e17959ed65 | ||
|
|
b599f95564 | ||
|
|
16c8721d6c | ||
|
|
6c115804e8 | ||
|
|
43c69d4288 | ||
|
|
b8dcfcf900 | ||
|
|
f77aeded6f | ||
|
|
faf6ea83fa | ||
|
|
cb7e54acaf | ||
|
|
87f9837939 | ||
|
|
380447dd41 | ||
|
|
a8667836b3 | ||
|
|
31d0d6c7c9 | ||
|
|
77cd519be2 | ||
|
|
361902d59d | ||
|
|
5accc2a923 | ||
|
|
53eb1649d5 | ||
|
|
4cbda25000 | ||
|
|
5a10a8dd46 | ||
|
|
ea4c140ad0 | ||
|
|
a67b4a5059 | ||
|
|
95bdbc590c | ||
|
|
d249c77b18 | ||
|
|
e07914e9b3 | ||
|
|
d831624d43 | ||
|
|
827791574d | ||
|
|
b458a254a9 | ||
|
|
1bbdabc42f | ||
|
|
91fd93c724 | ||
|
|
186a336232 | ||
|
|
27c697c1d2 | ||
|
|
974fd19b40 | ||
|
|
d384442fb3 | ||
|
|
46dbd016f4 | ||
|
|
0cf0c7a27c | ||
|
|
5489237f11 | ||
|
|
aa16370fc5 | ||
|
|
b75554ddcb | ||
|
|
a31281df40 | ||
|
|
51d9e7fcb1 | ||
|
|
e2b15c9b4f | ||
|
|
6bbb968128 | ||
|
|
91ba2a9282 | ||
|
|
21d7dd873e | ||
|
|
3f0f189a3a | ||
|
|
dc49dd0a94 | ||
|
|
a7c6e36ec3 | ||
|
|
c8976daf96 | ||
|
|
7aca2a1b36 | ||
|
|
63f9e26b2e | ||
|
|
547783e0e0 | ||
|
|
86109127b8 | ||
|
|
6df195aa94 | ||
|
|
cbdea7965d | ||
|
|
0a74546a98 | ||
|
|
fde6e5f1fb | ||
|
|
06ea69ae4a | ||
|
|
4728885437 | ||
|
|
a7e26055b2 | ||
|
|
45e6ef09a8 | ||
|
|
d9f07c4de4 | ||
|
|
98cc0b9dfc | ||
|
|
f84076d80c | ||
|
|
5f85810345 | ||
|
|
52ad526b87 | ||
|
|
8446773037 | ||
|
|
be10718dfc | ||
|
|
8939f0dad7 | ||
|
|
3c1419a22f | ||
|
|
211c52ccc1 | ||
|
|
99b73f91b8 | ||
|
|
9da96b9e92 | ||
|
|
7f87af5a08 | ||
|
|
e2659c87f4 | ||
|
|
a8cb0a0e9c | ||
|
|
34583c834d | ||
|
|
1d61d4dad4 | ||
|
|
434bfdde67 | ||
|
|
d5a8731850 | ||
|
|
d3738f2f31 | ||
|
|
570a8ee97d | ||
|
|
9168af4850 | ||
|
|
d8a9ef8187 | ||
|
|
475239bd02 | ||
|
|
ea3042e1d7 | ||
|
|
39d631b056 | ||
|
|
6e06e05f12 | ||
|
|
4d8f8f19d4 | ||
|
|
384e341452 | ||
|
|
aa46285b8f | ||
|
|
fae00992c8 | ||
|
|
47477808e4 | ||
|
|
be16f93ba0 | ||
|
|
a153f0d87d | ||
|
|
179dd6339f | ||
|
|
4c662a30ef | ||
|
|
28372af5a9 | ||
|
|
1f93cce2c5 | ||
|
|
62cc534153 | ||
|
|
4df1ec867c | ||
|
|
ff195ad272 | ||
|
|
00ca21243b | ||
|
|
4d9c73ab1f | ||
|
|
ddf98937d6 | ||
|
|
5acd7c3e99 | ||
|
|
0f35017955 | ||
|
|
2235524f97 | ||
|
|
17a8b38484 | ||
|
|
7651b5a11d | ||
|
|
775a066a9a | ||
|
|
5cdbfc0af7 | ||
|
|
4a8e9fef99 | ||
|
|
05f68d0b1a | ||
|
|
d82a685d7f | ||
|
|
105bcf23be | ||
|
|
a26ceeb76d | ||
|
|
9f94545283 | ||
|
|
daac71ac9a | ||
|
|
2db34c4d7e | ||
|
|
5212f6d0b7 | ||
|
|
3ec502d862 | ||
|
|
1d5bca7962 | ||
|
|
4b9b4c1427 | ||
|
|
dfc4667910 | ||
|
|
5be2eb1c9a | ||
|
|
5e1e6657d1 | ||
|
|
2a2019b363 | ||
|
|
a8de386af6 | ||
|
|
63354b00eb | ||
|
|
822460e5ee | ||
|
|
dbf6eeb144 | ||
|
|
47295ec417 | ||
|
|
0e60b46db0 | ||
|
|
8d7175875a | ||
|
|
024d057e03 | ||
|
|
ec20fb453b | ||
|
|
06768833cc | ||
|
|
51d1efead6 | ||
|
|
04ff495066 | ||
|
|
df408505e0 | ||
|
|
7674e23580 | ||
|
|
689cf3171d | ||
|
|
ac23dda8db | ||
|
|
da7934555c | ||
|
|
0b9b0e7f13 | ||
|
|
a430b66a8d | ||
|
|
11e4542746 | ||
|
|
7238b89437 | ||
|
|
e2dcc3c0ea | ||
|
|
0e944f7d8a | ||
|
|
b391f4bc12 | ||
|
|
65f066d391 | ||
|
|
cbe81a8f0a | ||
|
|
9957739dc4 | ||
|
|
d0eb84ec51 | ||
|
|
df0e211d01 | ||
|
|
a3eef29b26 | ||
|
|
3614812680 | ||
|
|
8cdae41051 | ||
|
|
b59833e8f0 | ||
|
|
a4586b8bf1 | ||
|
|
3fbdfbe7a4 | ||
|
|
73a5fb1648 | ||
|
|
71fc7c4ab6 | ||
|
|
d57b39da6e | ||
|
|
4bf13f3c70 | ||
|
|
4297665c93 | ||
|
|
7131ae2d91 | ||
|
|
103dc9704a | ||
|
|
7efa79637c | ||
|
|
f33666b848 | ||
|
|
2acd6c8b40 | ||
|
|
7329c9d0bb | ||
|
|
4a7cc06d05 | ||
|
|
b2bb29911c | ||
|
|
028a723a31 | ||
|
|
05705be7c3 | ||
|
|
f89c0bb07c | ||
|
|
ca402cb604 | ||
|
|
47b9f15b0b | ||
|
|
2104df5a83 | ||
|
|
5527926508 | ||
|
|
f82f3fa858 | ||
|
|
69d4514716 | ||
|
|
0a49fcb22a | ||
|
|
89d50ed5f1 | ||
|
|
9224d1e017 | ||
|
|
9b2c954f8e | ||
|
|
d718c88353 | ||
|
|
b2e1d4cc61 | ||
|
|
e3b81d0b36 | ||
|
|
cbfe19aebf | ||
|
|
15269713cc | ||
|
|
cbba373d7d | ||
|
|
2a6544b794 | ||
|
|
2eedfad833 | ||
|
|
55b946e784 | ||
|
|
1839e1ac42 | ||
|
|
67bc03bcc1 | ||
|
|
f0f04ce3ff | ||
|
|
16caeb5400 | ||
|
|
9a6995343b | ||
|
|
ec07334d14 | ||
|
|
c859321cfd | ||
|
|
d68db98d62 | ||
|
|
b89f55f9b9 | ||
|
|
58f42f1441 | ||
|
|
3df0e6fda1 | ||
|
|
79093bf61c | ||
|
|
78e2c223f2 | ||
|
|
deea1249c4 | ||
|
|
a513fbf592 | ||
|
|
d6eb675b89 | ||
|
|
10df195630 | ||
|
|
6dfcec6e8b | ||
|
|
8ffd091e53 | ||
|
|
8c7f1de80c | ||
|
|
830db36928 | ||
|
|
ae68cc95bb | ||
|
|
a123a8301f | ||
|
|
0ce1c120f9 | ||
|
|
67728851a3 | ||
|
|
785db03650 | ||
|
|
2fe02a2cc3 | ||
|
|
7a747774fd | ||
|
|
8a88a8a9ef | ||
|
|
42456bac0f | ||
|
|
0cffd76296 | ||
|
|
d8373bc488 | ||
|
|
5953fd71d3 | ||
|
|
de6837adb0 | ||
|
|
23dd575ce1 | ||
|
|
1f8cdbaf62 | ||
|
|
e312c3147a | ||
|
|
128e7fccdb | ||
|
|
3a323551eb | ||
|
|
b9d9797734 | ||
|
|
26d94c0519 | ||
|
|
6befc2b7a2 | ||
|
|
9db671b83a | ||
|
|
c4205c1c11 | ||
|
|
93d47bb0c2 | ||
|
|
218ed1ce13 | ||
|
|
bb12da6777 | ||
|
|
c4452c99ae | ||
|
|
5ef0ad9a3e | ||
|
|
113a3eb5cf | ||
|
|
eec386cbf4 | ||
|
|
b3e8b41e0e | ||
|
|
1db275707b | ||
|
|
64b730a22e | ||
|
|
8522775569 | ||
|
|
e81b77cbcd | ||
|
|
8498b79493 | ||
|
|
7c1160de92 | ||
|
|
c517b6db3b | ||
|
|
30f3a6f450 | ||
|
|
2ed9d68c08 | ||
|
|
d45c2eb5b6 | ||
|
|
fc1c1ea690 | ||
|
|
18e17f2932 | ||
|
|
e70ea6f202 | ||
|
|
c4026c8e78 | ||
|
|
a58b2efaf9 | ||
|
|
e917ae4198 | ||
|
|
3832ac3965 | ||
|
|
bba9de7b76 | ||
|
|
d2de2c7093 | ||
|
|
53aed4c7f8 | ||
|
|
e8bd839281 | ||
|
|
7d07e34d6b | ||
|
|
f6f97e69eb | ||
|
|
0fe5d9d628 | ||
|
|
e665857aa8 | ||
|
|
00f6b878b3 | ||
|
|
7cddf8ae6a | ||
|
|
3383a84fa6 | ||
|
|
8e120bca77 | ||
|
|
66d235a873 | ||
|
|
dca9266697 | ||
|
|
b3131169ad | ||
|
|
e83bcf0fd9 | ||
|
|
9137244fcf | ||
|
|
3a32aab066 | ||
|
|
5fd4e2f008 | ||
|
|
0bc460db56 | ||
|
|
5a34244854 | ||
|
|
9676cabcb8 | ||
|
|
44b02961ac | ||
|
|
66f0b49ca7 | ||
|
|
24ed0fd479 | ||
|
|
8f6656d657 | ||
|
|
19e08942ed | ||
|
|
0865b9bbc5 | ||
|
|
00a5dbf42c | ||
|
|
acae9ee602 | ||
|
|
93e0787911 | ||
|
|
5c354db1b2 | ||
|
|
a5ca8781ff | ||
|
|
ba1636033e | ||
|
|
d8c063f59b | ||
|
|
30b99abfb1 | ||
|
|
8a51582d8a | ||
|
|
72635c8711 | ||
|
|
7bec653b55 | ||
|
|
9d30b6e29a | ||
|
|
77d4a9f711 | ||
|
|
8eec3cddb5 | ||
|
|
d633029d08 | ||
|
|
15a27e234c | ||
|
|
174846f110 | ||
|
|
2aed64d1c1 | ||
|
|
e36f24dc63 | ||
|
|
74f4dacbe4 | ||
|
|
4d7a5f03ab | ||
|
|
40dcbd1229 | ||
|
|
30686477f1 | ||
|
|
7beddf3019 | ||
|
|
8e8737c4df | ||
|
|
454afd5d1b | ||
|
|
5d88e86462 | ||
|
|
02666b7da4 | ||
|
|
5342dae5b3 | ||
|
|
2b0fd17fbf | ||
|
|
f0848e23c7 | ||
|
|
3dc6e274f0 | ||
|
|
2c6d9e699f | ||
|
|
27ecde2f17 | ||
|
|
05a685fb24 | ||
|
|
6b272e8a6f | ||
|
|
7d9f57299c | ||
|
|
263f68554e | ||
|
|
c7a924e83b | ||
|
|
74a71f4d8e | ||
|
|
9b9fb325bd | ||
|
|
b7b738c92b | ||
|
|
b8a539a67a | ||
|
|
23f7a540fb | ||
|
|
3d487be59e | ||
|
|
6ef6caaca4 | ||
|
|
87a222748f | ||
|
|
ef0a9a4a1e | ||
|
|
6c674e86e5 | ||
|
|
55e6e80433 | ||
|
|
86bbad5b3d | ||
|
|
e02d2c8af2 | ||
|
|
6907c6dfe4 | ||
|
|
1a51a355f2 | ||
|
|
92227a3b7f | ||
|
|
ab0d5c8967 | ||
|
|
e13db20c85 | ||
|
|
e4b4a7b0c5 | ||
|
|
1fa23bdf16 | ||
|
|
f8905a0490 | ||
|
|
5fe6757f8a | ||
|
|
f3ac71ed3e | ||
|
|
8aef6ebfbc | ||
|
|
31d593a529 | ||
|
|
d5b47ecdce | ||
|
|
f5020f8dc0 | ||
|
|
def774c9ef | ||
|
|
2dea8309a7 | ||
|
|
d153a734cb | ||
|
|
a220667f1b | ||
|
|
62b648c70f | ||
|
|
9f8bde7078 | ||
|
|
c593b4180a | ||
|
|
3e2177b402 | ||
|
|
d9bf09bb9b | ||
|
|
21c1d3c191 | ||
|
|
7da590ca76 | ||
|
|
97a298375a | ||
|
|
7d35c9a8eb | ||
|
|
d77aaded39 | ||
|
|
fae1b4dec1 | ||
|
|
e4c47de90a | ||
|
|
6a5de6606c | ||
|
|
8132920ed8 | ||
|
|
26e8eb8c11 | ||
|
|
3647f3130f | ||
|
|
f52a330b16 | ||
|
|
a669144d16 | ||
|
|
78e835dd5f | ||
|
|
da8a7041d1 | ||
|
|
3aa103e114 | ||
|
|
6aca198428 | ||
|
|
085ed59334 | ||
|
|
3f3bb4d3b7 | ||
|
|
148e3dc65b | ||
|
|
063b102461 | ||
|
|
558620cdfa | ||
|
|
7b62c9e8a4 | ||
|
|
b44d65d265 | ||
|
|
1197693591 | ||
|
|
81f91f3324 | ||
|
|
f78f6634fa | ||
|
|
28eee609de | ||
|
|
a3e1843e8b | ||
|
|
c9b8607c9f | ||
|
|
fe94d75b1b | ||
|
|
5aadf88ae3 | ||
|
|
4e038142da | ||
|
|
d75e95a23d | ||
|
|
a019227ddc | ||
|
|
d3b10a6711 | ||
|
|
faa14fa91d | ||
|
|
85dced9cd1 | ||
|
|
e45df6fa6d | ||
|
|
8bbf9b50b4 | ||
|
|
12794a499d | ||
|
|
3d31f73453 | ||
|
|
99f30fe09a | ||
|
|
11c64f3035 | ||
|
|
aa65af10b6 | ||
|
|
1afc8d20a0 | ||
|
|
42b4d7ce5f | ||
|
|
c1c53af855 | ||
|
|
740c88c506 | ||
|
|
270d27be73 | ||
|
|
dc98c2c1fe | ||
|
|
e6079ee275 | ||
|
|
26b88a55e0 | ||
|
|
b5721fe6f3 | ||
|
|
ec99cae3d9 | ||
|
|
cceae6770c | ||
|
|
4cfa658fde | ||
|
|
8e58349bfa | ||
|
|
68a08b1f62 | ||
|
|
20a30b303b | ||
|
|
373f294fe3 | ||
|
|
5459a540e7 | ||
|
|
221181092e | ||
|
|
326e01d548 | ||
|
|
c7572f0624 | ||
|
|
b94ce542c3 | ||
|
|
6a303ae50a | ||
|
|
59721a3f1a | ||
|
|
bd5ecf358a | ||
|
|
2617fcdcfd | ||
|
|
dd5e4adc73 | ||
|
|
c46c41db5a | ||
|
|
aafd3c8d35 | ||
|
|
cb6d531300 | ||
|
|
e7b11a7ceb | ||
|
|
54c6c2e6cd | ||
|
|
c7ef32bf3c | ||
|
|
824816cb94 | ||
|
|
a138425298 | ||
|
|
9888aa8c08 | ||
|
|
da0dcf65b3 | ||
|
|
c9d875e3fa | ||
|
|
bd44bb4534 | ||
|
|
fda0a918f0 | ||
|
|
31599c5da9 | ||
|
|
7e1fbb3017 | ||
|
|
08b2f6f998 | ||
|
|
daeaa800d8 | ||
|
|
9c4baf9cad | ||
|
|
a1f01d2def | ||
|
|
dde6e0859b | ||
|
|
7322006455 | ||
|
|
c193a86a4c | ||
|
|
58fcca58fc | ||
|
|
ffc477091f | ||
|
|
46620e2da5 | ||
|
|
c43ba46c97 | ||
|
|
a2fdefb6a6 | ||
|
|
0aea814a23 | ||
|
|
5c605be45c | ||
|
|
1e34f3ef38 | ||
|
|
569cd4dd42 | ||
|
|
203ab05d12 | ||
|
|
471c68474a | ||
|
|
76cc9614df | ||
|
|
e53a35eebf | ||
|
|
96f60caa77 | ||
|
|
e608257c1a | ||
|
|
05f31f40eb | ||
|
|
0b73633a66 | ||
|
|
2f5c4413e1 | ||
|
|
c6e93b9870 | ||
|
|
f64297c256 | ||
|
|
edb9bac503 | ||
|
|
fa64191082 | ||
|
|
4a5c0e7ff0 | ||
|
|
aa54e47029 | ||
|
|
7bcb6dd7cb | ||
|
|
9651db67ce | ||
|
|
3ebb41c5ad | ||
|
|
23d91c7b37 | ||
|
|
b644418b11 | ||
|
|
86c4045073 | ||
|
|
42f493b2c3 | ||
|
|
5a766c583c | ||
|
|
776e65bc5e | ||
|
|
55939f6320 | ||
|
|
a1ea6b21d8 | ||
|
|
c61357ec6d | ||
|
|
d84b4e4f7d | ||
|
|
19bae2af96 | ||
|
|
daff760280 | ||
|
|
e161c26c35 | ||
|
|
b99f634939 | ||
|
|
a93b3dab1b | ||
|
|
5a16a50b3f | ||
|
|
21888829cc | ||
|
|
dffef6f839 | ||
|
|
4ef7195d38 | ||
|
|
627d6f8a28 | ||
|
|
178ebf3ed0 | ||
|
|
979e91a2eb | ||
|
|
4dec688e0b | ||
|
|
1247dbe999 | ||
|
|
f6f6318e02 | ||
|
|
6c7341b9f3 | ||
|
|
71e9caef9c | ||
|
|
dfba9d3650 | ||
|
|
45cfe1a817 | ||
|
|
68066cdd48 | ||
|
|
d1da77d6bc | ||
|
|
6cd97d2cb9 | ||
|
|
dcae882009 | ||
|
|
ee45bc713e | ||
|
|
5936e00acc | ||
|
|
d12e8cbe97 | ||
|
|
60140087a5 | ||
|
|
74f4849144 | ||
|
|
b8c36b034b | ||
|
|
d51183be51 | ||
|
|
fd3bb37c48 | ||
|
|
f990095ddf | ||
|
|
c86b99e69c | ||
|
|
70b15d128a | ||
|
|
42ce3cb405 | ||
|
|
98fb9c89de | ||
|
|
2bc2b632c6 | ||
|
|
2b4c6514c3 | ||
|
|
f3e2f10478 | ||
|
|
b43fa38350 | ||
|
|
0d4165421c | ||
|
|
b02e8a9502 | ||
|
|
b625e40eb0 | ||
|
|
47729e3e43 | ||
|
|
ac0426d97d | ||
|
|
0619274d00 | ||
|
|
24b9e713f2 | ||
|
|
b3736617c4 | ||
|
|
63ee99fde9 | ||
|
|
837d5803c8 | ||
|
|
2d1f24ca0f | ||
|
|
84a1f40115 | ||
|
|
abb40b3ad7 | ||
|
|
dfd54b7b54 | ||
|
|
c82cde5e16 | ||
|
|
5ea4c90292 | ||
|
|
fa3bdb5464 | ||
|
|
12abf494d8 | ||
|
|
f5e8a60a8f | ||
|
|
c53adedbe0 | ||
|
|
3b6831ea93 | ||
|
|
2f19af6a3e | ||
|
|
0f5a4c10ef | ||
|
|
dfcaacee80 | ||
|
|
2ac3c1fe6e | ||
|
|
d8c70c2498 | ||
|
|
16c15548c1 | ||
|
|
d0fbf68d90 | ||
|
|
230599417e | ||
|
|
4c235f0427 | ||
|
|
4045a16e27 | ||
|
|
7f91e85df8 | ||
|
|
dfb3285e18 | ||
|
|
0280059c13 | ||
|
|
5fdc3eca7e | ||
|
|
95cee1676a | ||
|
|
70580cc6ae | ||
|
|
f56eb0d791 | ||
|
|
4534a729c7 | ||
|
|
62a6c243fe | ||
|
|
5feb5ee015 | ||
|
|
7907d05847 | ||
|
|
1dfa95d457 | ||
|
|
b6b52ffdb7 | ||
|
|
97cb73cb73 | ||
|
|
3f3226391a | ||
|
|
91c873c25f | ||
|
|
b38e28e50e | ||
|
|
65fc3eb362 | ||
|
|
3955fbdc64 | ||
|
|
441b72158d | ||
|
|
8e1457d605 | ||
|
|
da4215afbd | ||
|
|
6e2007aeca | ||
|
|
4ba01c6cf1 | ||
|
|
1dd5f63a11 | ||
|
|
467921dbf6 | ||
|
|
99b2140838 | ||
|
|
63b5e28537 | ||
|
|
109eefa7e3 | ||
|
|
380791211f | ||
|
|
bffd7c8d24 | ||
|
|
aaab06f21d | ||
|
|
4c87b62b5e | ||
|
|
e34e479c33 | ||
|
|
665f7c849b | ||
|
|
88b9eed559 | ||
|
|
cb162a8f1e | ||
|
|
db5d3aa9bd | ||
|
|
9db1ad32f9 | ||
|
|
630286665b | ||
|
|
8b08c1d113 | ||
|
|
6fcfa6cac0 | ||
|
|
b1da8bbc4c | ||
|
|
7d56e71f77 | ||
|
|
68e02817a0 | ||
|
|
58bb2d5f93 | ||
|
|
ee263914aa | ||
|
|
a887fc8153 | ||
|
|
12d9e6b618 | ||
|
|
f1b9ce61e1 | ||
|
|
3f2c7542f8 | ||
|
|
132c1a9a8b | ||
|
|
801c0ac47c | ||
|
|
24550236be | ||
|
|
3f46d6d16e | ||
|
|
5d6cf5789a | ||
|
|
fca66222df | ||
|
|
2e3120cd46 | ||
|
|
fa2b03b7fa | ||
|
|
b141b3c95e | ||
|
|
83a2f07ba9 | ||
|
|
ec2dd67d89 | ||
|
|
6da071c88d | ||
|
|
98ba214dfb | ||
|
|
5b86c96adf | ||
|
|
a43f9d78c4 | ||
|
|
bc8b32ebab | ||
|
|
363efd3836 | ||
|
|
c1817505f8 | ||
|
|
27fac748cd | ||
|
|
56739945fa | ||
|
|
8a5e7accaf | ||
|
|
8c8ae57103 | ||
|
|
c3ab43a9fc | ||
|
|
a2d1d83457 | ||
|
|
ce01adc5b7 | ||
|
|
f0598c9fec | ||
|
|
19c0d325ca | ||
|
|
97d0cc2fb4 | ||
|
|
df3a80e17e | ||
|
|
3eacdff1d6 | ||
|
|
cd63d2622c | ||
|
|
2bf91ea453 | ||
|
|
7e8cbc542b | ||
|
|
55e0d734df | ||
|
|
a42c7e4735 | ||
|
|
dd264617d7 | ||
|
|
2167b1fc6b | ||
|
|
9b3f1c3f9c | ||
|
|
e51014a5bc | ||
|
|
58e5f96eda | ||
|
|
74679b4b41 | ||
|
|
2a0f727cba | ||
|
|
9937c01cde | ||
|
|
ebf3e4fea7 | ||
|
|
8e3839203b | ||
|
|
a53bc720cb | ||
|
|
ab62f61256 | ||
|
|
a2b737e6a0 | ||
|
|
893e07ea16 | ||
|
|
78cfb9b7f0 | ||
|
|
fae42bbca3 | ||
|
|
d95b13664e | ||
|
|
f7fe38fa25 | ||
|
|
38ed49d814 | ||
|
|
fb08369aec | ||
|
|
a071cef46a | ||
|
|
7438576bb1 | ||
|
|
571d510423 | ||
|
|
8dd4b58227 | ||
|
|
d9402bc24d | ||
|
|
0513ed16bb |
2
.gitignore
vendored
@@ -4,3 +4,5 @@ installer/src/certs/server.key
|
||||
# vim swap files
|
||||
*.swp
|
||||
|
||||
.cursor
|
||||
|
||||
|
||||
299
CHANGES
@@ -2925,3 +2925,302 @@
|
||||
[8.3.2]
|
||||
* Bring back immich vectors hook in postgres addon
|
||||
|
||||
[9.0.0]
|
||||
* UI redesign
|
||||
* notifications: email notification when server reboot is required
|
||||
* notifications: email notification when cloudron update failed
|
||||
* notifications: email notification for low disk space (90%)
|
||||
* node: update to 22.20.0
|
||||
* docker: update to 28.1.1
|
||||
* s3: automatically abort old multipart uploads
|
||||
* notifications: validate domains configs
|
||||
* ldap: automatically detect pagination support
|
||||
* ubuntu: alert for 20.04 support being deprecated
|
||||
* domains: vanity nameservers
|
||||
* token: access can by restricted by ip range(s)
|
||||
* sendmail: requiresValidCertificate option for using mail server domain
|
||||
* mail: update haraka to 3.1.1
|
||||
* sshfs: implement rm via ssh
|
||||
* multiple docker registries
|
||||
* mail: rename delivered -> sent and received -> saved in event log
|
||||
* graphs: replace collectd with custom collector
|
||||
* graphs: live graphs
|
||||
* graphs: add system disk and network graph
|
||||
* profile: drop gravatar support
|
||||
* login: suppress notification of impersonated users
|
||||
* mongodb: reduce verbosity of logs
|
||||
* redis: disable by default when optional
|
||||
* apps: fix issue where operations on stopped apps errored
|
||||
* eventlog: Fix incorrect eventlog that the update crashed
|
||||
* database: change charset to utf8mb4. this allows emojis everywhere!
|
||||
* mail: add brevo as relay provider
|
||||
* mail: add rbl6 check
|
||||
* eventlog: mail server change log
|
||||
* profile: avatar cannot be changed when profile is locked
|
||||
* app backup: no more part alters app state. runs completely in background
|
||||
* system: disk usage is not collected in background. new disk ui, computes space on demand
|
||||
* backups: multiple backup targets
|
||||
* port bindings: add `enabledByDefault` property in manifest
|
||||
* backups: store integrity information and perform validation
|
||||
* reverse proxy: remove OCSP support. this is being deprecated in favor of CRLs
|
||||
* sqlite: fix issue where dump was also logged when backing up
|
||||
* backups: remove noop backend
|
||||
|
||||
[9.0.1]
|
||||
* redis: update to 8.2.2
|
||||
* Split the ubuntu version and cloudron version
|
||||
* Restructure sidebar menu items
|
||||
* eventlog: fix display of backup (sites) events
|
||||
* app archive: fix download config
|
||||
* graphs: fix performance issue when selecting apps
|
||||
* Support overwrite DNS in app install dialog
|
||||
* encryption: do not allow password and hint to be the same
|
||||
* Add better grouping to mailbox owner select
|
||||
* eventlog: display task log link when available
|
||||
* add ephemeral port warning
|
||||
* rsync: fix integrity computation
|
||||
|
||||
[9.0.2]
|
||||
* backupsite: only owner can add a site
|
||||
* remove max-height from the users view and groups view tables
|
||||
* backups: fix listing when stats is null
|
||||
* graphs: fix detection of rootfs block device
|
||||
* sidebar: ldap/openid/directory should not be visible to non-admins
|
||||
* sidebar: email domains, eventlog, settings is only for admins
|
||||
* reload dashboard on Cloudron version change
|
||||
* Always start with a fresh domains list for the apps filter
|
||||
* sysinfo: fallback to product family if product vendor is empty
|
||||
* archive: display the site name of latest backup
|
||||
* graphs: fix flickering of disk graph item
|
||||
* graphs: fix issue with live graph time calculation
|
||||
|
||||
[9.0.3]
|
||||
* Fix submit state for login form
|
||||
* Avoid flickering of SystemUpdate view when update is busy
|
||||
* backuptask: fix crash when accessing stats of old backups
|
||||
* backup sites: fix listing when status call errors
|
||||
* backups: display mail backup stats
|
||||
* Add missing autocomplete attributes on forms
|
||||
* Refresh backup site status and task in the background
|
||||
* Hide non-owner actions for backup sites
|
||||
* Move app start/stop back to the main toolbar
|
||||
* Fix styling in public page
|
||||
* network: fix ip caching bug
|
||||
* Change default footer to not have the forum link
|
||||
* Fix troubleshooting tool
|
||||
* Give domains list a larger max-height
|
||||
* Make app error compatible with previous releases
|
||||
|
||||
[9.0.4]
|
||||
* filemanager: fix missing translations
|
||||
* display backup duration
|
||||
* add hetznercloud DNS provider
|
||||
|
||||
[9.0.5]
|
||||
* access control/operators: remove deleted users and groups
|
||||
* backupcleaner: fix scoping of cleanup by site id
|
||||
* Use normal buttons for app start/stop
|
||||
* site schedule: Fix hourly display
|
||||
|
||||
[9.0.6]
|
||||
* Autofocus search in appstore view
|
||||
* All settings in sidebar should be same icon
|
||||
* Make backup content list a TableView so we can sort it by size and fileCount
|
||||
* Fix filemanager for custom apps
|
||||
* Sort apps in the grid by label
|
||||
* Filter dropdowns are searchable with more than 10 entries
|
||||
* Show app icons in the grid in grayscale if app is stopped
|
||||
* Support wildcard domain aliases in app location
|
||||
|
||||
[9.0.7]
|
||||
* externalldap: only set group members if they changed
|
||||
* Fix issue where backups remote paths were incorrectly migrated
|
||||
|
||||
[9.0.8]
|
||||
* Add explicit option to disable automatic backups
|
||||
* backups: show same filesystem warning
|
||||
* Fix tgz app backup download
|
||||
* Fix mailbox usage and quota sorting
|
||||
* Give sshfs identity files unique filenames across mounts
|
||||
* Do not share relay provider setting with view and form
|
||||
* cloudflare: ensure defaultProxyStatus in older configs
|
||||
* filter: fix domain search to include redirect/alias/secondary domains
|
||||
* Use full URLs for page preview icons and favicon
|
||||
* email: fix masquerade toggle
|
||||
|
||||
[9.0.9]
|
||||
* minio: fix issue with accepting selfsigned certs
|
||||
* applink: fix button text in edit mode
|
||||
* password reset: show error message if any
|
||||
* sshfs: use a temporary identity file for remote ssh copy
|
||||
* access control: always show the user management section
|
||||
* update: show the last update error, if any
|
||||
|
||||
[9.0.10]
|
||||
* Only enable LdapServer input fields if feature is enabled
|
||||
* Require display name to not be empty when changed from the profile view
|
||||
* access control: fix spacing
|
||||
* storage: pass limits object to backend
|
||||
|
||||
[9.0.11]
|
||||
* mail: fix count indicator when loading
|
||||
* mailinglist: fix search on name
|
||||
* backup site: fix migration with mixed formats
|
||||
|
||||
[9.0.12]
|
||||
* eventlog: always fetch enough event logs to fill the screen
|
||||
* mail: check for outbound ipv6 connectivity
|
||||
* store actual appId not oidc clientId for log in events
|
||||
* Add english labels for eventlog filtering
|
||||
* mail: when deferred, show reason
|
||||
* mail: prefer ipv4 for outbound mail
|
||||
|
||||
[9.0.13]
|
||||
* Fix issue where footer/name can break templates
|
||||
* rsync: bump empty dir limit to 80k
|
||||
* nginx: do not log query params
|
||||
* Fetch mailbox usage in the background to not delay mailbox listing
|
||||
* cloudron-support: add --check-services and add it to troubleshoot
|
||||
* Do not poll services if they are in recoveryMode
|
||||
* restore/import: fix issue where prefix was empty
|
||||
|
||||
[9.0.14]
|
||||
* Also use a temporary SSH identity file for optimized ssh remote rm -rf
|
||||
* app search: title is optional manifest
|
||||
* network: detect default ipv6 interface when no ipv4 interface
|
||||
* mail status: fix rbl display
|
||||
* platform: show any container upgrade errors in the UI
|
||||
* users: make remove 2fa separate dialog
|
||||
* mandatory 2fa: show undismissable dialog and warning
|
||||
* restore: validate ipv6 config
|
||||
* location: use the domain where app is installed as default
|
||||
* s3: remove leading slash in CopySource
|
||||
* gcs: fix copy operation
|
||||
* restore: fix crash when trying to mount fs volumes
|
||||
* restore: teardown pseudo backup site
|
||||
* oidc: add separate jwks key route for cloudflare access
|
||||
|
||||
[9.0.15]
|
||||
* sshfs: Use unique temporary ssh key file for each ssh remote operation
|
||||
|
||||
[9.0.16]
|
||||
* Update mongodb to 7.0.28 (also fixes mongobleed)
|
||||
* docker: do not use auth for appstore images
|
||||
* backup: add synology C2
|
||||
* mail: update haraka to 3.1.2
|
||||
* csp/robots: add common patterns
|
||||
|
||||
[9.0.17]
|
||||
* Update mongodb to 7.0.28 (also fixes mongobleed)
|
||||
* UI: add favorites for list views
|
||||
* UI: add collapsible sidebar
|
||||
* docker: do not use auth for appstore images
|
||||
* backup: add synology C2
|
||||
* mail: update haraka to 3.1.2
|
||||
* csp/robots: add common patterns
|
||||
|
||||
[9.0.18]
|
||||
* ami & cloud images: fix setup
|
||||
|
||||
[9.1.0]
|
||||
* acme: ARI support . https://www.rfc-editor.org/rfc/rfc9773.txt
|
||||
* Update nodejs to 24.13.0
|
||||
* Update docker to 29.1.5
|
||||
* Update mongodb to 8.0.17
|
||||
* Update redis to 8.4.0
|
||||
* Add notification view. settings have moved to this new view.
|
||||
* updater: skip backup site check when user skips backup
|
||||
* community packages
|
||||
* source builds
|
||||
* backups: add integrity check UI
|
||||
* Fix fonts on chrome
|
||||
* applinks: fix acl UI
|
||||
* services: rename sftp to filemanager, graphite to metrics
|
||||
* app passwords: add expiry
|
||||
* DO Spaces: add missing ATL1, BLR1, SYD1 regions
|
||||
* filemanager: the terminal button automatically cds into the cwd
|
||||
* filemanager: add a tree view
|
||||
* passkey support
|
||||
* security: remove cors
|
||||
* support card/cal dav well-known endpoints
|
||||
* add backupCommand, restoreCommand, persistentDirs
|
||||
* Update Haraka to 3.1.3
|
||||
|
||||
[9.1.1]
|
||||
* cli: use web based browser login flow
|
||||
|
||||
[9.1.2]
|
||||
* apps: avoid flickering with filters
|
||||
* apps: move to error state if a volume is unavailable
|
||||
* apps: enable storage view in all error states
|
||||
* postgres: update pgvector to 0.8.2
|
||||
* appstore: add ai category
|
||||
* appstore: better tag/cateogry mapping
|
||||
* i18n: add Czech translations
|
||||
* Support and prefer Dockerfile.cloudron in local builds
|
||||
* integrity: show status in the info dialog
|
||||
* backup: show integrity column for dependsOn backups
|
||||
* integrity: show log link
|
||||
* syncer: fix bug with a file and dir having same prefix
|
||||
|
||||
[9.1.3]
|
||||
* Remove 'Dashboard' from dashboard page title
|
||||
* integrity: skip check of backups with no integrity info
|
||||
* backupintegrity: add percent progress
|
||||
* apps: fix acl display
|
||||
|
||||
[9.1.4]
|
||||
* services: lazy start services / on demand services
|
||||
* restore: fix restore of trusted ips and blocklist
|
||||
* dashboard: wait for dashboard reload when version has changed
|
||||
* graphite: fix aggregation of block/network read/write
|
||||
* Workaround chrome quirks on file drop handling
|
||||
* notifications: add empty text, progress bar and inifinite scroll
|
||||
* rsync: throttle log messages during download
|
||||
* backup logs: make them much terse and concise
|
||||
* oidc: implement Device Authorization Grant
|
||||
* operator: fix viewing of backup progress and logs
|
||||
* notification: automatic app update failure notification
|
||||
* backup sites: identify conflicting site locations
|
||||
* update: add policy to update apps and platform separately
|
||||
* passkey: fix issue where passkeys were lost on restart
|
||||
* passkey: implement passwordless login
|
||||
* oidcserver: fix jwks_rsaonly response
|
||||
|
||||
[9.1.5]
|
||||
* services: lazy start services / on demand services
|
||||
* restore: fix restore of trusted ips and blocklist
|
||||
* dashboard: wait for dashboard reload when version has changed
|
||||
* graphite: fix aggregation of block/network read/write
|
||||
* Workaround chrome quirks on file drop handling
|
||||
* notifications: add empty text, progress bar and inifinite scroll
|
||||
* rsync: throttle log messages during download
|
||||
* backup logs: make them much terse and concise
|
||||
* oidc: implement Device Authorization Grant
|
||||
* operator: fix viewing of backup progress and logs
|
||||
* notification: automatic app update failure notification
|
||||
* backup sites: identify conflicting site locations
|
||||
* update: add policy to update apps and platform separately
|
||||
* passkey: fix issue where passkeys were lost on restart
|
||||
* passkey: implement passwordless login
|
||||
* oidcserver: fix jwks_rsaonly response
|
||||
|
||||
[9.1.6]
|
||||
* apps: fix wrong disabled state for devices config
|
||||
* notifications: send email when manual platform and app update required
|
||||
* source install: support dockerfileName and build options
|
||||
* source install: persist buildConfig so restore, import, clone work correctly
|
||||
* search for matches in app links labels for apps view filter
|
||||
* restore: prune portBindings whose tcpPorts/udpPorts no longer exist
|
||||
* location: fix duplication of port bindings on submit
|
||||
* Update translations
|
||||
* location: show what DNS is being overwritten in location UI
|
||||
* backup site: remove the local disk provider
|
||||
* mail: update haraka to 3.1.4, tika to 3.3.0
|
||||
* solr: dynamically allocate java heap based on container mem
|
||||
|
||||
[9.2.0]
|
||||
* apppasswords: generate easier to type passwords
|
||||
* logs: escape and unescape new lines
|
||||
* backups/volumes: rename 'mountpoint' to 'User-managed Mount Point'
|
||||
* mail: listen on the bridge IP
|
||||
|
||||
96
box.js
@@ -1,17 +1,19 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
import constants from './src/constants.js';
|
||||
import fs from 'node:fs';
|
||||
import ldapServer from './src/ldapserver.js';
|
||||
import net from 'node:net';
|
||||
import authServer from './src/authserver.js';
|
||||
import oidcServer from './src/oidcserver.js';
|
||||
import paths from './src/paths.js';
|
||||
import proxyAuth from './src/proxyauth.js';
|
||||
import safe from '@cloudron/safetydance';
|
||||
import server from './src/server.js';
|
||||
import directoryServer from './src/directoryserver.js';
|
||||
import logger from './src/logger.js';
|
||||
|
||||
const constants = require('./src/constants.js'),
|
||||
fs = require('fs'),
|
||||
ldapServer = require('./src/ldapserver.js'),
|
||||
net = require('net'),
|
||||
oidc = require('./src/oidc.js'),
|
||||
paths = require('./src/paths.js'),
|
||||
proxyAuth = require('./src/proxyauth.js'),
|
||||
safe = require('safetydance'),
|
||||
server = require('./src/server.js'),
|
||||
directoryServer = require('./src/directoryserver.js');
|
||||
const { log } = logger('box');
|
||||
|
||||
let logFd;
|
||||
|
||||
@@ -35,8 +37,11 @@ async function setupNetworking() {
|
||||
// this is also used as the 'uncaughtException' handler which can only have synchronous functions
|
||||
function exitSync(status) {
|
||||
const ts = new Date().toISOString();
|
||||
const msg = status.error.stack.replace(/\n/g, `\n${ts} `); // prefix each line with ts
|
||||
if (status.error) fs.write(logFd, `${ts} ${msg}\n`, function () {});
|
||||
if (status.message) fs.write(logFd, `${ts} ${status.message}\n`, function () {});
|
||||
if (status.error) {
|
||||
const escapedStack = status.error.stack.replace(/\\/g, '\\\\').replace(/\n/g, '\\n');
|
||||
fs.write(logFd, `${ts} ${escapedStack}\n`, function () {});
|
||||
}
|
||||
fs.fsyncSync(logFd);
|
||||
fs.closeSync(logFd);
|
||||
process.exit(status.code);
|
||||
@@ -53,42 +58,45 @@ async function startServers() {
|
||||
if (conf.enabled) await directoryServer.start();
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const [error] = await safe(startServers());
|
||||
if (error) return exitSync({ error: new Error(`Error starting server: ${JSON.stringify(error)}`), code: 1 });
|
||||
const [error] = await safe(startServers());
|
||||
if (error) exitSync({ error, code: 1, message: 'Error starting servers' });
|
||||
|
||||
// require this here so that logging handler is already setup
|
||||
const debug = require('debug')('box:box');
|
||||
process.on('SIGHUP', async function () {
|
||||
log('Received SIGHUP. Re-reading configs.');
|
||||
const conf = await directoryServer.getConfig();
|
||||
if (conf.enabled) await directoryServer.checkCertificate();
|
||||
});
|
||||
|
||||
process.on('SIGHUP', async function () {
|
||||
debug('Received SIGHUP. Re-reading configs.');
|
||||
const conf = await directoryServer.getConfig();
|
||||
if (conf.enabled) await directoryServer.checkCertificate();
|
||||
});
|
||||
process.on('SIGINT', async function () {
|
||||
log('Received SIGINT. Shutting down.');
|
||||
|
||||
process.on('SIGINT', async function () {
|
||||
debug('Received SIGINT. Shutting down.');
|
||||
await proxyAuth.stop();
|
||||
await server.stop();
|
||||
await directoryServer.stop();
|
||||
await ldapServer.stop();
|
||||
await oidcServer.stop();
|
||||
await authServer.stop();
|
||||
|
||||
await proxyAuth.stop();
|
||||
await server.stop();
|
||||
await directoryServer.stop();
|
||||
await ldapServer.stop();
|
||||
await oidc.stop();
|
||||
setTimeout(process.exit.bind(process), 3000);
|
||||
});
|
||||
setTimeout(() => {
|
||||
log('Shutdown complete');
|
||||
process.exit();
|
||||
}, 2000); // need to wait for the task processes to die
|
||||
});
|
||||
|
||||
process.on('SIGTERM', async function () {
|
||||
debug('Received SIGTERM. Shutting down.');
|
||||
process.on('SIGTERM', async function () {
|
||||
log('Received SIGTERM. Shutting down.');
|
||||
|
||||
await proxyAuth.stop();
|
||||
await server.stop();
|
||||
await directoryServer.stop();
|
||||
await ldapServer.stop();
|
||||
await oidc.stop();
|
||||
setTimeout(process.exit.bind(process), 3000);
|
||||
});
|
||||
await proxyAuth.stop();
|
||||
await server.stop();
|
||||
await directoryServer.stop();
|
||||
await ldapServer.stop();
|
||||
await oidcServer.stop();
|
||||
await authServer.stop();
|
||||
|
||||
process.on('uncaughtException', (error) => exitSync({ error, code: 1 }));
|
||||
}
|
||||
setTimeout(() => {
|
||||
log('Shutdown complete');
|
||||
process.exit();
|
||||
}, 2000); // need to wait for the task processes to die
|
||||
});
|
||||
|
||||
main();
|
||||
process.on('uncaughtException', (uncaughtError) => exitSync({ error: uncaughtError, code: 1, message: 'From uncaughtException handler.' }));
|
||||
|
||||
7
dashboard/.gitignore
vendored
@@ -1,13 +1,10 @@
|
||||
dist/
|
||||
node_modules/
|
||||
|
||||
# will get generated on build
|
||||
public/theme.css
|
||||
public/theme.css.map
|
||||
|
||||
# vim swap files
|
||||
*.swp
|
||||
|
||||
dist/
|
||||
|
||||
# these are not done yet
|
||||
public/translation/ja.json
|
||||
public/translation/pl.json
|
||||
|
||||
99
dashboard/TRANSLATIONS.md
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
## Translations
|
||||
|
||||
This documents the convention used for the text in the UI.
|
||||
|
||||
### Tale of Two Cases
|
||||
|
||||
**Title Case**
|
||||
|
||||
All words are capitalized. In title case, articles (a/an/the), conjunctions (and/but/or/...)
|
||||
and prepositions (on/at/...) inside a phrase are not capitalized. Everything else is capitalized
|
||||
- noun, pronoun, verb, adverb.
|
||||
|
||||
Examples:
|
||||
|
||||
* "Sign In to Your Account"
|
||||
* "Terms and Conditions"
|
||||
* "Getting Started with GraphQL"
|
||||
* "Between You and Me"
|
||||
|
||||
**Sentence Case**
|
||||
|
||||
Only first word is capitalized.
|
||||
|
||||
### UI Conventions
|
||||
|
||||
Keeping as much as possible in Sentence Case helps in sharing the same strings.
|
||||
|
||||
| Element | Recommended Style | Example |
|
||||
| -------------- | ---------------------- | -------------------------------- |
|
||||
| Headings | Title Case | Manage Account |
|
||||
| Sub heading | Title Case | Create Admin Account |
|
||||
| Section/Card | Title Case | System Information |
|
||||
| Form Labels | Sentence case | Email address |
|
||||
| Form Groups | Sentence case | Volume mounts, Data directory |
|
||||
| Table headings | Sentence case | Memory limit |
|
||||
| Info sections | Sentence case | Cloudron version |
|
||||
| Buttons | Sentence case | Save changes |
|
||||
| Radio Buttons | Sentence case | Option one / Option two |
|
||||
| Checkbox | Sentence case | Use CIFS encryption |
|
||||
| Menu action | Sentence case | Select all |
|
||||
| Switches | Sentence case | Allow users to edit email |
|
||||
| Descriptions | Sentence case | Enter your password to continue. |
|
||||
| Tooltips | Sentence case | Click to edit. |
|
||||
| Error Messages | Sentence case | Password is too short |
|
||||
| Notifications | Sentence case | Settings saved successfully. |
|
||||
| Legend (graph) | Sentence case | Docker volume, Box data. |
|
||||
| Placeholders | Sentence case | Comma separated IPs or subnets |
|
||||
|
||||
Hints in brackets are small case. Like "(comma separated)".
|
||||
|
||||
### Full Stops
|
||||
|
||||
Sentence fragments like form hints and tooltips (which are always visible) do not need a full stop.
|
||||
All other full sentences do.
|
||||
|
||||
Description has a full stop unless it's a hint/phrase.
|
||||
|
||||
instructional heading in dialogs (like the object being configured) should not have a full stop.
|
||||
|
||||
Switch UI description does not have a fullstop.
|
||||
|
||||
Setting item description does not need a fullstop (usually).
|
||||
|
||||
Checkbox labels do not have a full stop at the end.
|
||||
|
||||
No full stop → short labels, commands, headings, or action text (“Configure Service {{serviceName}}”).
|
||||
|
||||
Full stop → descriptive text or sentences explaining a setting (“The IPv4 address used for DNS A records.”).
|
||||
|
||||
### Dialog Buttons
|
||||
|
||||
'Add' for addition
|
||||
'Cancel' to cancel
|
||||
'Save' for edit/update
|
||||
'Remove' for non-destructive/less destructive things (app password remove)
|
||||
'Delete' for destructive (user delete)
|
||||
|
||||
'Close' - Only for dialogs with the only button
|
||||
|
||||
### Dialog Text
|
||||
|
||||
When asking for confirmation simply ask 'Remove app password "xxx"' . Don't use "really"
|
||||
or other emotional terms. Quote the password/domain name.
|
||||
|
||||
In general, we put just "Delete User" in Title and provide the username in the context.
|
||||
|
||||
Title = action (what you’re doing)
|
||||
Description = context (to whom it applies)
|
||||
|
||||
### Description Text
|
||||
|
||||
| Context | Verb form | Example |
|
||||
| --------------------------------- | ------------------------ | ---------------------------------------------------------------------- |
|
||||
| **Action / Button / Instruction** | **Imperative** → “Add” | Button: **Add**, Tooltip: “Add a new link” |
|
||||
| **Section / View description** | **Imperative** → “Add” | Description: **Adds shortcuts to external services on the dashboard.** |
|
||||
|
||||
We use plural when possible. "Admins can ..." , "Operators can ..."
|
||||
|
||||
@@ -1,153 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
|
||||
|
||||
<title>Cloudron Setup</title>
|
||||
<meta name="description" content="Cloudron Setup">
|
||||
|
||||
<link id="favicon" href="/api/v1/cloudron/avatar" rel="icon" type="image/png">
|
||||
|
||||
<!-- contains all thing already using import statement -->
|
||||
<script type="module" src="./src/modules.js"></script>
|
||||
|
||||
<!-- Theme CSS -->
|
||||
<link type="text/css" rel="stylesheet" href="./src/theme.scss">
|
||||
|
||||
<!-- jQuery-->
|
||||
<script type="text/javascript" src="/js/jquery.min.js"></script>
|
||||
|
||||
<!-- async -->
|
||||
<script type="text/javascript" src="/js/async-3.2.0.min.js"></script>
|
||||
|
||||
<!-- Angularjs scripts -->
|
||||
<script type="text/javascript" src="/js/angular.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-loader.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-cookies.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-md5.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-ui-notification.js"></script>
|
||||
|
||||
<!-- Angular directives for bootstrap https://angular-ui.github.io/bootstrap/ -->
|
||||
<script type="text/javascript" src="/js/ui-bootstrap-tpls-1.3.3.min.js"></script>
|
||||
|
||||
<!-- Angular translate https://angular-translate.github.io/ -->
|
||||
<script type="text/javascript" src="/js/angular-translate.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-translate-loader-static-files.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-translate-storage-cookie.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-translate-storage-local.min.js"></script>
|
||||
|
||||
<!-- Showdown (markdown converter) -->
|
||||
<script type="text/javascript" src="/js/showdown-1.9.1.min.js"></script>
|
||||
|
||||
<!-- Setup Application -->
|
||||
<script type="text/javascript" src="/js/activation.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/js/client.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/js/utils.js?%VITE_CACHE_ID%"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="setup" ng-app="Application" ng-controller="SetupController">
|
||||
|
||||
<a class="offline-banner animateMe" ng-show="client.offline" ng-cloak href="https://docs.cloudron.io/troubleshooting/" target="_blank"><i class="fa fa-circle-notch fa-spin"></i> Cloudron is offline. Reconnecting...</a>
|
||||
|
||||
<div class="main-container" ng-show="initialized">
|
||||
<div class="row" ng-show="view === 'owner'">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="card" style="max-width: none; padding: 20px;">
|
||||
<form role="form" name="ownerForm" ng-submit="owner.submit()" novalidate>
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<h1>Welcome to Cloudron</h1>
|
||||
<h3>Set up Admin Account</h3>
|
||||
<p class="has-error text-center" ng-show="owner.error.generic">{{ owner.error.generic }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="form-group" ng-class="{ 'has-error': ownerForm.displayName.$dirty && ownerForm.displayName.$invalid }">
|
||||
<label class="control-label" for="inputDisplayName">Full Name</label>
|
||||
<input type="text" class="form-control" ng-model="owner.displayName" id="inputDisplayName" name="displayName" placeholder="Full Name" required autocomplete="off" ng-disabled="owner.busy" autofocus>
|
||||
</div>
|
||||
<div class="form-group" ng-class="{ 'has-error': (ownerForm.email.$dirty && ownerForm.email.$invalid) || (!ownerForm.email.$dirty && owner.error.email) }">
|
||||
<label class="control-label" for="inputEmail">Email <sup><a ng-href="https://docs.cloudron.io/installation/#admin-account" class="help" target="_blank" tabIndex="-1"><i class="fa fa-question-circle"></i></a></sup></label>
|
||||
<input type="email" class="form-control" ng-model="owner.email" id="inputEmail" name="email" placeholder="Email" required autocomplete="off" ng-disabled="owner.busy">
|
||||
<small>A valid email is required for Let's Encrypt certificates. This email is local to your Cloudron. </small>
|
||||
</div>
|
||||
<div class="form-group" ng-class="{ 'has-error': (ownerForm.username.$dirty && ownerForm.username.$invalid) || (!ownerForm.username.$dirty && owner.error.username) }">
|
||||
<label class="control-label" for="inputUsername">Username</label>
|
||||
<input type="text" class="form-control" ng-model="owner.username" id="inputUsername" name="username" placeholder="Username" ng-maxlength="512" ng-minlength="1" required autocomplete="off" ng-disabled="owner.busy">
|
||||
<small>{{ owner.error.username }}</small>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom: 0;" ng-class="{ 'has-error': ownerForm.password.$dirty && ownerForm.password.$invalid }">
|
||||
<label class="control-label" for="inputPassword">Password</label>
|
||||
<input type="password" class="form-control" ng-model="owner.password" id="inputPassword" name="password" placeholder="Password" ng-pattern="/^.{8,}$/" required autocomplete="off" ng-disabled="owner.busy" password-reveal>
|
||||
<small><span ng-show="ownerForm.password.$dirty && ownerForm.password.$invalid">Password must be at least 8 characters</span> </small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<button type="submit" class="btn btn-success" ng-disabled="ownerForm.$invalid || owner.busy"><i class="fa fa-circle-notch fa-spin" ng-show="owner.busy"></i> Create Admin</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-show="view === 'finished'">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="card" style="max-width: none; padding: 20px 40px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<h1>Cloudron is ready to use</h1>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
Before you start:
|
||||
<ul class="fa-ul">
|
||||
<li><i class="fa-li fa fa-users"></i>
|
||||
<b>User management</b>: Cloudron has a central user directory. When installing an app,
|
||||
you can set it up to authenticate against this directory.
|
||||
</li>
|
||||
<br/>
|
||||
<li><i class="fa-li fa fa-envelope-open"></i>
|
||||
<b>Email Configuration</b>: Apps are configured to send email based on the settings in the Email view.
|
||||
This saves you the trouble of having to configure mail settings inside each app.
|
||||
</li>
|
||||
<br/>
|
||||
<li><i class="fa-li fa fa-archive"></i>
|
||||
<b>Backups</b>: Store your backups on storage services completely independent from your server.
|
||||
You can use backups to seamlessly migrate your setup to another server.
|
||||
</li>
|
||||
<br/>
|
||||
<li><i class="fa-li fa fa-birthday-cake"></i>
|
||||
<b>Updates</b>: The Cloudron team tracks upstream releases and publishes app updates after testing.
|
||||
Your apps are kept fresh & secure.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<a class="btn btn-success" ng-href="firstTimeLoginUrl">Proceed to Dashboard</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="text-center">
|
||||
<span class="text-muted">©2022 <a href="https://cloudron.io" target="_blank">Cloudron</a></span>
|
||||
<span class="text-muted"><a href="https://forum.cloudron.io" target="_blank">Forum <i class="fa fa-comments"></i></a></span>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Cloudron Admin Setup</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" style="overflow: hidden; height: 100%;"></div>
|
||||
<script type="module" src="/src/activation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,16 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<script>
|
||||
|
||||
var tmp = window.location.hash.slice(1).split('&');
|
||||
(async function () {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const code = params.get('code');
|
||||
|
||||
tmp.forEach(function (pair) {
|
||||
if (pair.indexOf('access_token=') === 0) localStorage.token = pair.split('=')[1];
|
||||
});
|
||||
if (!code) {
|
||||
console.error('No authorization code in callback URL');
|
||||
window.location.replace('/');
|
||||
return;
|
||||
}
|
||||
|
||||
var redirectTo = '/';
|
||||
if (localStorage.getItem('redirectToHash')) {
|
||||
redirectTo += localStorage.getItem('redirectToHash');
|
||||
localStorage.removeItem('redirectToHash');
|
||||
}
|
||||
window.location.href = redirectTo;
|
||||
const codeVerifier = sessionStorage.getItem('pkce_code_verifier');
|
||||
const clientId = sessionStorage.getItem('pkce_client_id') || 'cid-webadmin';
|
||||
const apiOrigin = sessionStorage.getItem('pkce_api_origin') || '';
|
||||
|
||||
sessionStorage.removeItem('pkce_code_verifier');
|
||||
sessionStorage.removeItem('pkce_client_id');
|
||||
sessionStorage.removeItem('pkce_api_origin');
|
||||
|
||||
try {
|
||||
const response = await fetch(apiOrigin + '/openid/token', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
code: code,
|
||||
client_id: clientId,
|
||||
redirect_uri: window.location.origin + '/authcallback.html',
|
||||
code_verifier: codeVerifier
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok || !data.access_token) {
|
||||
console.error('Token exchange failed', data);
|
||||
window.location.replace('/');
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.token = data.access_token;
|
||||
} catch (e) {
|
||||
console.error('Token exchange error', e);
|
||||
window.location.replace('/');
|
||||
return;
|
||||
}
|
||||
|
||||
let redirectTo = '/';
|
||||
if (localStorage.getItem('redirectToHash')) {
|
||||
redirectTo += localStorage.getItem('redirectToHash');
|
||||
localStorage.removeItem('redirectToHash');
|
||||
}
|
||||
|
||||
window.location.replace(redirectTo);
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
@@ -5,10 +5,7 @@ set -eu
|
||||
echo "=> Create timezones.js"
|
||||
./scripts/createTimezones.cjs ./public/js/timezones.js
|
||||
|
||||
echo "=> Build theme.css for oidc views"
|
||||
./node_modules/.bin/sass --quiet --pkg-importer=node ./src/theme.scss ./public/theme.css
|
||||
|
||||
export VITE_CACHE_ID=$(date +%s)
|
||||
|
||||
echo "=> Build the dashboard apps"
|
||||
./node_modules/.bin/vite build
|
||||
npm run build
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
set -eu
|
||||
|
||||
# Check if the API origin is set, if not prompt the user to enter it
|
||||
if [[ -z "${DASHBOARD_DEVELOPMENT_ORIGIN:-}" ]]; then
|
||||
read -p "Enter the API origin (e.g. http://localhost:3000): " DASHBOARD_DEVELOPMENT_ORIGIN
|
||||
fi
|
||||
|
||||
echo "=> Set API origin"
|
||||
export VITE_API_ORIGIN="${DASHBOARD_DEVELOPMENT_ORIGIN}"
|
||||
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
import globals from 'globals';
|
||||
import js from '@eslint/js';
|
||||
import js from '@eslint/js';
|
||||
import pluginVue from 'eslint-plugin-vue';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
js.configs.recommended,
|
||||
...pluginVue.configs['flat/essential'],
|
||||
{
|
||||
files: ["**/*.js"],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
},
|
||||
ecmaVersion: 13,
|
||||
sourceType: 'module'
|
||||
globals: globals.browser,
|
||||
},
|
||||
rules: {
|
||||
semi: "error",
|
||||
"prefer-const": "error"
|
||||
"semi": "error",
|
||||
"prefer-const": "error",
|
||||
"vue/no-reserved-component-names": "off",
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/no-undef-components": "error",
|
||||
'vue/no-root-v-if': "error",
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -1,17 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/api/v1/cloudron/avatar" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>File Manager</title>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -1,211 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="Application" ng-controller="MainController">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
|
||||
|
||||
<!-- this gets changed once we get the config (because angular has not loaded yet, we see template string for a flash) -->
|
||||
<title>Cloudron Dashboard</title>
|
||||
<meta name="description" content="Cloudron Dashboard">
|
||||
|
||||
<link id="favicon" type="image/png" rel="icon" href="/api/v1/cloudron/avatar">
|
||||
<link rel="apple-touch-icon" href="/api/v1/cloudron/avatar">
|
||||
<link rel="icon" href="/api/v1/cloudron/avatar">
|
||||
|
||||
<!-- contains all thing already using import statement -->
|
||||
<script type="module" src="./src/modules.js"></script>
|
||||
|
||||
<!-- jQuery-->
|
||||
<script type="text/javascript" src="/js/jquery.min.js"></script>
|
||||
|
||||
<!-- CSS -->
|
||||
<link type="text/css" rel="stylesheet" href="/slick.css"/>
|
||||
<link type="text/css" rel="stylesheet" href="/angular-ui-notification.css"/>
|
||||
<link type="text/css" rel="stylesheet" href="./src/theme.scss">
|
||||
|
||||
<!-- async -->
|
||||
<script type="text/javascript" src="/js/async-3.2.0.min.js"></script>
|
||||
|
||||
<!-- Slick carousel -->
|
||||
<script type="text/javascript" src="/js/slick.js"></script>
|
||||
|
||||
<!-- Angularjs scripts -->
|
||||
<script type="text/javascript" src="/js/angular.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-loader.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-route.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-cookies.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-animate.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-base64.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-md5.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-sanitize.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-slick.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-ui-notification.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-fittext.min.js"></script>
|
||||
|
||||
<!-- Angular directives for bootstrap https://angular-ui.github.io/bootstrap/ -->
|
||||
<script type="text/javascript" src="/js/ui-bootstrap-tpls-1.3.3.min.js"></script>
|
||||
|
||||
<!-- Angular translate https://angular-translate.github.io/ -->
|
||||
<script type="text/javascript" src="/js/angular-translate.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-translate-loader-static-files.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-translate-storage-cookie.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-translate-storage-local.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/js/clipboard.min.js"></script>
|
||||
|
||||
<!-- Showdown (markdown converter) -->
|
||||
<script type="text/javascript" src="/js/showdown-1.9.1.min.js"></script>
|
||||
|
||||
<!-- Anugular Multiselect https://github.com/sebastianha/angular-bootstrap-multiselect -->
|
||||
<script type="text/javascript" src="/js/angular-bootstrap-multiselect.js"></script>
|
||||
|
||||
<!-- timezone list -->
|
||||
<script type="text/javascript" src="/js/timezones.js?%VITE_CACHE_ID%"></script>
|
||||
|
||||
<!-- Main Application -->
|
||||
<!-- for now we need this in a static non transformed index.js file -->
|
||||
<script> window.VITE_CACHE_ID = '%VITE_CACHE_ID%' </script>
|
||||
<script type="text/javascript" src="/js/index.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/js/client.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/js/utils.js?%VITE_CACHE_ID%"></script>
|
||||
|
||||
<script type="text/javascript" src="/views/app.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/apps.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/appstore.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/backups.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/branding.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/domains.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/email.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/emails-eventlog.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/emails.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/emails-queue.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/eventlog.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/network.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/notifications.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/profile.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/services.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/settings.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/support.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/system.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/user-directory.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/users.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/views/volumes.js?%VITE_CACHE_ID%"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/ng-template" id="notification.html">
|
||||
<div class="ui-notification">
|
||||
<h3 ng-show="title" ng-bind-html="title"></h3>
|
||||
<div class="message">
|
||||
<a href="{{action}}" ng-show="action" ng-bind-html="message"></a>
|
||||
<span ng-hide="action" ng-bind-html="message"></span>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<a class="offline-banner animateMe" ng-show="client.offline" ng-cloak href="https://docs.cloudron.io/troubleshooting/" target="_blank"><i class="fa fa-circle-notch fa-spin"></i> {{ 'main.offline' | tr }}</a>
|
||||
|
||||
<!-- Modal reboot server -->
|
||||
<div class="modal fade" id="rebootModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'main.rebootDialog.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="text-bold">{{ 'main.rebootDialog.warning' | tr }}</p>
|
||||
<p>{{ 'main.rebootDialog.description' | tr }}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="reboot.submit()" ng-disabled="reboot.busy"><i class="fa fa-circle-notch fa-spin" ng-show="reboot.busy"></i> {{ 'main.rebootDialog.rebootAction' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mainContentContainer" class="animateMe ng-hide layout-root" ng-show="initialized">
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav class="navbar navbar-default navbar-static-top shadow" role="navigation" style="margin-bottom: 0">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand navbar-brand-icon" href="#/"><img ng-src="{{ client.avatar }}" width="40" height="40"/></a>
|
||||
<a class="navbar-brand" href="#/">{{ config.cloudronName || 'Cloudron' }}</a>
|
||||
</div>
|
||||
<!-- /.navbar-header -->
|
||||
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav navbar-right" ng-hide="hideNavBarActions">
|
||||
<li ng-show="user.isAtLeastOwner && (subscription.plan.id === 'free' || subscription.plan.id === 'expired')">
|
||||
<a ng-click="openSubscriptionSetup()" style="cursor: pointer">
|
||||
<span class="badge" ng-class="{'badge-danger': subscription.plan.id !== 'free', 'badge-success': subscription.plan.id === 'free' }">
|
||||
{{ subscription.plan.id === 'free' ? ('settings.appstoreAccount.subscriptionSetupAction' | tr) : ('settings.appstoreAccount.subscriptionReactivateAction' | tr) }}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li ng-show="!user.isAtLeastOwner && subscription.plan.id === 'expired'">
|
||||
<a>
|
||||
<span class="badge badge-danger">Subscription Expired</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a ng-class="{ active: isActive('/apps')}" href="#/apps" ng-click="closeNavbar()"><i class="fa fa-grip fa-fw"></i> {{ 'apps.title' | tr }}</a>
|
||||
</li>
|
||||
<li ng-show="user.isAtLeastAdmin">
|
||||
<a ng-class="{ active: isActive('/appstore')}" href="#/appstore" ng-click="closeNavbar()"><i class="fa fa-cloud-download-alt fa-fw"></i> {{ 'appstore.title' | tr }}</a>
|
||||
</li>
|
||||
<li ng-show="user.isAtLeastUserManager">
|
||||
<a ng-class="{ active: isActive('/users')}" href="#/users" ng-click="closeNavbar()"><i class="fa fa-users fa-fw"></i> {{ 'main.navbar.users' | tr }}</a>
|
||||
</li>
|
||||
<li ng-show="user.isAtLeastAdmin">
|
||||
<a href="#/notifications" ng-click="closeNavbar()">
|
||||
<i class="fas fa-bell" ng-show="notificationCount"></i>
|
||||
<i class="far fa-bell" ng-hide="notificationCount"></i>
|
||||
<span class="badge badge-danger" ng-show="notificationCount">{{ notificationCount === 100 ? '100+' : notificationCount }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><img ng-src="{{user.avatarUrl}}" style="width: 24px; height: 24px;"/> {{user.username}} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="#/profile" ng-click="closeNavbar()"><i class="fa fa-user fa-fw"></i> {{ 'profile.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastMailManager" class="divider"></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/backups" ng-click="closeNavbar()"><i class="fa fa-archive fa-fw"></i> {{ 'backups.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/branding" ng-click="closeNavbar()"><i class="fa fa-passport fa-fw"></i> {{ 'branding.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/domains" ng-click="closeNavbar()"><i class="fa fa-globe fa-fw"></i> {{ 'domains.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastMailManager"><a href="#/email" ng-click="closeNavbar()"><i class="fa fa-envelope fa-fw"></i> {{ 'emails.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/eventlog" ng-click="closeNavbar()"><i class="fa fa-list-alt fa-fw"></i> {{ 'eventlog.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/network" ng-click="closeNavbar()"><i class="fas fa-network-wired fa-fw"></i> {{ 'network.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/services" ng-click="closeNavbar()"><i class="fa fa-cogs fa-fw"></i> {{ 'services.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/settings" ng-click="closeNavbar()"><i class="fa fa-wrench fa-fw"></i> {{ 'settings.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/user-directory" ng-click="closeNavbar()"><i class="fa fa-users-gear fa-fw"></i> {{ 'users.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/volumes" ng-click="closeNavbar()"><i class="fa fa-hdd fa-fw"></i> {{ 'volumes.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin" class="divider"></li>
|
||||
<li ng-show="user.isAtLeastOwner"><a href="#/support" ng-click="closeNavbar()"><i class="fa fa-comment fa-fw"></i> {{ 'support.title' | tr }}</a></li>
|
||||
<li ng-show="user.isAtLeastAdmin"><a href="#/system" ng-click="closeNavbar()"><i class="fa fa-chart-area fa-fw"></i> {{ 'system.title' | tr }}</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="" ng-click="logout($event)"><i class="fa fa-sign-out-alt fa-fw"></i> {{ 'main.logout' | tr }}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div ng-view id="ng-view" class="layout-content"></div>
|
||||
|
||||
<footer class="text-center ng-cloak">
|
||||
<span class="text-muted" ng-bind-html="config.footer | markdown2html"></span>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><%= name %></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" style="overflow: hidden; height: 100%;"></div>
|
||||
<script type="module" src="/src/index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
28
dashboard/injectMetaTags.vite.plugin.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
function injectMetaTags(templates) {
|
||||
let config;
|
||||
let template = fs.readFileSync(path.resolve('./src/meta-tags-header.html'), 'utf8');
|
||||
|
||||
return {
|
||||
name: 'inject-meta-tags',
|
||||
configResolved(resolvedConfig) {
|
||||
config = resolvedConfig;
|
||||
|
||||
// remove all ejs content in dev mode
|
||||
if (!config.isProduction) template = template.replace(/<%[^]*?%>/g, '');
|
||||
},
|
||||
transformIndexHtml: {
|
||||
handler: function transform(html, ctx) {
|
||||
if (templates.indexOf(ctx.filename) === -1) return html;
|
||||
|
||||
html = html.replace(/<head(.*)>/i, `$&\n${template}`);
|
||||
|
||||
return html;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default injectMetaTags;
|
||||
@@ -1,17 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/api/v1/cloudron/avatar" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Logs</title>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
16
dashboard/oidc_device_confirm.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>OpenID Confirm</title>
|
||||
|
||||
<script>
|
||||
window.cloudron = <%- JSON.stringify({ name, clientName, userCode, form }) %>;
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/oidcdeviceconfirm.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
16
dashboard/oidc_device_input.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>OpenID Device Sign-in</title>
|
||||
|
||||
<script>
|
||||
window.cloudron = <%- JSON.stringify({ name, message, form }) %>;
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/oidcdeviceinput.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
16
dashboard/oidc_device_success.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>OpenID Device Success</title>
|
||||
|
||||
<script>
|
||||
window.cloudron = <%- JSON.stringify({ name }) %>;
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/oidcdevicesuccess.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
16
dashboard/oidc_error.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><%= name %> OpenID Error</title>
|
||||
|
||||
<script>
|
||||
window.cloudron = <%- JSON.stringify({ iconUrl, name, errorMessage, footer, language }) %>;
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/oidcerror.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
22
dashboard/oidc_interaction_abort.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><%= name %> OpenID Access Denied</title>
|
||||
|
||||
<script>
|
||||
window.cloudron = <%- JSON.stringify({
|
||||
iconUrl: iconUrl,
|
||||
name: name,
|
||||
submitUrl: submitUrl,
|
||||
footer: footer,
|
||||
language: language
|
||||
}) %>;
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/oidcinteractionabort.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
19
dashboard/oidc_interaction_confirm.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Authorize <%= name %></title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<form id="submitForm" method="post" action="<%- submitUrl %>">
|
||||
<!-- <button type="submit"></button> -->
|
||||
</form>
|
||||
|
||||
<script>
|
||||
|
||||
document.getElementById('submitForm').submit();
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
25
dashboard/oidc_login.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><%= name %> Login</title>
|
||||
|
||||
<script>
|
||||
window.cloudron = <%- JSON.stringify({
|
||||
iconUrl: iconUrl,
|
||||
name: name,
|
||||
note: note,
|
||||
submitUrl: submitUrl,
|
||||
passkeyAuthOptionsUrl: passkeyAuthOptionsUrl,
|
||||
passkeyLoginUrl: passkeyLoginUrl,
|
||||
footer: footer,
|
||||
language: language
|
||||
}) %>;
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/login.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
5319
dashboard/package-lock.json
generated
@@ -3,31 +3,31 @@
|
||||
"scripts": {
|
||||
"update-translations": "curl https://translate.cloudron.io/api/components/cloudron/dashboard/file/ -o lang.zip && unzip -jo lang.zip -d ./public/translation/ && rm lang.zip",
|
||||
"dev": "vite --strictPort --port 4000",
|
||||
"build": "vite build"
|
||||
"build": "rm -rf ./dist/* && vite build --config ./vite.config.mjs && vite build --config ./vite.proxyauth.config.mjs"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@eslint/js": "^9.16.0",
|
||||
"@fontsource/noto-sans": "^5.1.0",
|
||||
"@fortawesome/fontawesome-free": "^6.7.1",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@xterm/addon-attach": "^0.11.0",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"anser": "^2.3.0",
|
||||
"bootstrap-sass": "^3.4.3",
|
||||
"chart.js": "^4.4.7",
|
||||
"eslint-plugin-vue": "^9.32.0",
|
||||
"filesize": "^10.1.6",
|
||||
"jquery": "^3.7.1",
|
||||
"marked": "^15.0.3",
|
||||
"@simplewebauthn/browser": "^13.3.0",
|
||||
"@cloudron/pankow": "^4.1.10",
|
||||
"@fontsource/inter": "^5.2.8",
|
||||
"@fortawesome/fontawesome-free": "^7.2.0",
|
||||
"@vitejs/plugin-vue": "^6.0.5",
|
||||
"@xterm/addon-attach": "^0.12.0",
|
||||
"@xterm/addon-fit": "^0.11.0",
|
||||
"@xterm/xterm": "^6.0.0",
|
||||
"anser": "^2.3.5",
|
||||
"async": "^3.2.6",
|
||||
"chart.js": "^4.5.1",
|
||||
"chartjs-plugin-annotation": "^3.1.0",
|
||||
"eslint": "^10.2.0",
|
||||
"eslint-plugin-vue": "^10.8.0",
|
||||
"marked": "^18.0.0",
|
||||
"moment": "^2.30.1",
|
||||
"pankow": "^2.4.2",
|
||||
"pankow-viewers": "^1.0.11",
|
||||
"sass": "^1.82.0",
|
||||
"vite": "^6.0.3",
|
||||
"vue": "^3.5.13",
|
||||
"vue-i18n": "^10.0.5",
|
||||
"vue-router": "^4.5.0"
|
||||
"moment-timezone": "^0.6.1",
|
||||
"vite": "^8.0.8",
|
||||
"vite-plugin-singlefile": "^2.3.2",
|
||||
"vue": "^3.5.32",
|
||||
"vue-i18n": "^11.3.2",
|
||||
"vue-router": "^5.0.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,165 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><%= name %> Password Reset</title>
|
||||
|
||||
<!-- this gets changed once we get the status (because angular has not loaded yet, we see template string for a flash) -->
|
||||
<title>Cloudron Password Reset</title>
|
||||
<meta name="description" content="Cloudron Password Reset">
|
||||
<script>
|
||||
window.cloudron = <%- JSON.stringify({
|
||||
name: name,
|
||||
footer: footer,
|
||||
language: language
|
||||
}) %>;
|
||||
</script>
|
||||
|
||||
<link id="favicon" href="/api/v1/cloudron/avatar" rel="icon" type="image/png">
|
||||
</head>
|
||||
|
||||
<!-- contains all thing already using import statement -->
|
||||
<script type="module" src="./src/modules.js"></script>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/passwordreset.js"></script>
|
||||
</body>
|
||||
|
||||
<!-- Theme CSS -->
|
||||
<link type="text/css" rel="stylesheet" href="./src/theme.scss">
|
||||
|
||||
<!-- jQuery-->
|
||||
<script type="text/javascript" src="/js/jquery.min.js"></script>
|
||||
|
||||
<!-- async -->
|
||||
<script type="text/javascript" src="/js/async-3.2.0.min.js"></script>
|
||||
|
||||
<!-- Showdown (markdown converter) -->
|
||||
<script type="text/javascript" src="/js/showdown-1.9.1.min.js"></script>
|
||||
|
||||
<!-- Angularjs scripts -->
|
||||
<script type="text/javascript" src="/js/angular.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-loader.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-cookies.min.js"></script>
|
||||
|
||||
<!-- Angular directives for bootstrap https://angular-ui.github.io/bootstrap/ -->
|
||||
<script type="text/javascript" src="/js/ui-bootstrap-tpls-1.3.3.min.js"></script>
|
||||
|
||||
<!-- Angular translate https://angular-translate.github.io/ -->
|
||||
<script type="text/javascript" src="/js/angular-translate.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-translate-loader-static-files.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-translate-storage-cookie.min.js"></script>
|
||||
<script type="text/javascript" src="/js/angular-translate-storage-local.min.js"></script>
|
||||
|
||||
<!-- Setup Application -->
|
||||
<script type="text/javascript" src="/js/passwordreset.js?%VITE_CACHE_ID%"></script>
|
||||
<script type="text/javascript" src="/js/utils.js?%VITE_CACHE_ID%"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body ng-app="Application" ng-controller="PasswordResetController">
|
||||
|
||||
<div class="layout-root ng-cloak" ng-show="initialized">
|
||||
|
||||
<div class="layout-content" ng-show="mode === 'passwordReset'">
|
||||
<div class="card" style="padding: 20px; margin-top: 100px; max-width: 620px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
<img width="128" height="128" style="margin-top: -84px" src="/api/v1/cloudron/avatar"/>
|
||||
<br/>
|
||||
<h2>{{ 'passwordReset.title' | tr }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<form name="passwordResetForm" ng-submit="onPasswordReset()">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="inputPasswordResetIdentifier">{{ 'passwordReset.usernameOrEmail' | tr }}</label>
|
||||
<input type="text" class="form-control" id="inputPasswordResetIdentifier" name="passwordResetIdentifier" ng-model="passwordResetIdentifier" ng-disabled="busy" autofocus required>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="card-form-bottom-bar">
|
||||
<a href="/" class="hand">{{ 'passwordReset.backToLoginAction' | tr }}</a>
|
||||
<button class="btn btn-primary btn-outline" type="submit" ng-disabled="busy || passwordResetForm.$invalid"><i class="fa fa-circle-notch fa-spin" ng-show="busy"></i> {{ 'passwordReset.resetAction' | tr }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-content" ng-show="mode === 'passwordResetDone'">
|
||||
<div class="card" style="padding: 20px; margin-top: 100px; max-width: 620px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
<img width="128" height="128" style="margin-top: -84px" src="/api/v1/cloudron/avatar"/>
|
||||
<br/>
|
||||
<h2 ng-hide="error">{{ 'passwordReset.emailSent.title' | tr }}</h2>
|
||||
<h4 ng-show="error" class="has-error">{{ error }}</h4>
|
||||
<br/>
|
||||
<a href="/" class="btn btn-primary">{{ 'passwordReset.backToLoginAction' | tr }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-content" ng-show="mode === 'newPassword'">
|
||||
<div class="card" style="padding: 20px; margin-top: 100px; max-width: 620px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
<img width="128" height="128" style="margin-top: -84px" src="/api/v1/cloudron/avatar"/>
|
||||
<br/>
|
||||
<h2>{{ 'passwordReset.newPassword.title' | tr }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h4 class="has-error" ng-show="error">{{ error }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<form name="newPasswordForm" ng-submit="onNewPassword()">
|
||||
<input type="password" style="display: none;"/>
|
||||
<div class="form-group" ng-class="{ 'has-error': newPasswordForm.newPassword.$dirty && newPasswordForm.newPassword.$invalid }">
|
||||
<label class="control-label" for="inputNewPassword">{{ 'passwordReset.newPassword.password' | tr }}</label>
|
||||
<div class="control-label" ng-show="newPasswordForm.newPassword.$dirty && newPasswordForm.newPassword.$invalid">
|
||||
<small ng-show="newPasswordForm.newPassword.$dirty && newPasswordForm.newPassword.$invalid">{{ 'passwordReset.newPassword.errorLength' | tr }}</small>
|
||||
</div>
|
||||
<input type="password" class="form-control" id="inputNewPassword" ng-model="newPassword" name="newPassword" ng-minlength="8" ng-maxlength="256" autofocus required password-reveal>
|
||||
</div>
|
||||
<div class="form-group" ng-class="{ 'has-error': newPasswordForm.newPasswordRepeat.$dirty && (newPassword !== newPasswordRepeat) }">
|
||||
<label class="control-label" for="inputNewPasswordRepeat">{{ 'passwordReset.newPassword.passwordRepeat' | tr }}</label>
|
||||
<div class="control-label" ng-show="newPasswordForm.newPasswordRepeat.$dirty && (newPassword !== newPasswordRepeat)">
|
||||
<small ng-show="newPasswordForm.newPasswordRepeat.$dirty && (newPassword !== newPasswordRepeat)">{{ 'passwordReset.newPassword.errorMismatch' | tr }}</small>
|
||||
</div>
|
||||
<input type="password" class="form-control" id="inputNewPasswordRepeat" ng-model="newPasswordRepeat" name="newPasswordRepeat" required password-reveal>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="inputPasswordResetTotpToken">{{ 'login.2faToken' | tr }}</label>
|
||||
<input type="text" class="form-control" name="passwordResetTotpToken" id="inputPasswordResetTotpToken" ng-model="totpToken" ng-disabled="busy" value="">
|
||||
</div>
|
||||
<div class="card-form-bottom-bar">
|
||||
<a href="/" class="hand">{{ 'passwordReset.backToLoginAction' | tr }}</a>
|
||||
<button class="btn btn-primary btn-outline" type="submit" ng-disabled="busy || newPasswordForm.$invalid || newPassword !== newPasswordRepeat"><i class="fa fa-circle-notch fa-spin" ng-show="busy"></i> {{ 'passwordReset.passwordChanged.submitAction' | tr }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-content" ng-show="mode === 'newPasswordDone'">
|
||||
<div class="card" style="padding: 20px; margin-top: 100px; max-width: 620px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
<img width="128" height="128" style="margin-top: -84px" src="/api/v1/cloudron/avatar"/>
|
||||
<br/>
|
||||
<h2>{{ 'passwordReset.success.title' | tr }}</h2>
|
||||
<br/>
|
||||
<a href="/" class="btn btn-primary">{{ 'passwordReset.success.openDashboardAction' | tr }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="text-center">
|
||||
<span class="text-muted" ng-bind-html="branding.footer | markdown2html"></span>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
22
dashboard/proxyauth.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><%= name %> Login</title>
|
||||
|
||||
<script>
|
||||
window.cloudron = <%- JSON.stringify({
|
||||
name: name,
|
||||
iconUrl: iconUrl,
|
||||
loginUrl: loginUrl,
|
||||
language: language,
|
||||
apiOrigin: apiOrigin
|
||||
}) %>;
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/proxyauth.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
Before Width: | Height: | Size: 4.1 KiB |
@@ -1,85 +0,0 @@
|
||||
/**
|
||||
* angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
|
||||
* @author Alex_Crack
|
||||
* @version v0.3.6
|
||||
* @link https://github.com/alexcrack/angular-ui-notification
|
||||
* @license MIT
|
||||
*/
|
||||
.ui-notification
|
||||
{
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
|
||||
width: 300px;
|
||||
|
||||
-webkit-transition: all ease .5s;
|
||||
-o-transition: all ease .5s;
|
||||
transition: all ease .5s;
|
||||
|
||||
color: #fff;
|
||||
border-radius: 0;
|
||||
background: #337ab7;
|
||||
box-shadow: 5px 5px 10px rgba(0, 0, 0, .3);
|
||||
}
|
||||
.ui-notification.clickable
|
||||
{
|
||||
cursor: pointer;
|
||||
}
|
||||
.ui-notification.clickable:hover
|
||||
{
|
||||
opacity: .7;
|
||||
}
|
||||
.ui-notification.killed
|
||||
{
|
||||
-webkit-transition: opacity ease 1s;
|
||||
-o-transition: opacity ease 1s;
|
||||
transition: opacity ease 1s;
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
.ui-notification > h3
|
||||
{
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
|
||||
display: block;
|
||||
|
||||
margin: 10px 10px 0 10px;
|
||||
padding: 0 0 5px 0;
|
||||
|
||||
text-align: left;
|
||||
|
||||
border-bottom: 1px solid rgba(255, 255, 255, .3);
|
||||
}
|
||||
.ui-notification a
|
||||
{
|
||||
color: #fff;
|
||||
}
|
||||
.ui-notification a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
.ui-notification > .message
|
||||
{
|
||||
margin: 10px 10px 10px 10px;
|
||||
}
|
||||
.ui-notification.warning
|
||||
{
|
||||
color: #fff;
|
||||
background: #f0ad4e;
|
||||
}
|
||||
.ui-notification.error
|
||||
{
|
||||
color: #fff;
|
||||
background: #d9534f;
|
||||
}
|
||||
.ui-notification.success
|
||||
{
|
||||
color: #fff;
|
||||
background: #5cb85c;
|
||||
}
|
||||
.ui-notification.info
|
||||
{
|
||||
color: #fff;
|
||||
background: #5bc0de;
|
||||
}
|
||||
108
dashboard/public/img/app_down.svg
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="546.13336"
|
||||
height="546.13336"
|
||||
viewBox="0 0 512.00001 512.00001"
|
||||
id="svg4519"
|
||||
version="1.1"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="app_down.svg"
|
||||
inkscape:export-filename="/home/nebulon/Cloudron/Assets/logo_115.png"
|
||||
inkscape:export-xdpi="20.214842"
|
||||
inkscape:export-ydpi="20.214842"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"><defs
|
||||
id="defs4521" /><sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.98994949"
|
||||
inkscape:cx="250.01276"
|
||||
inkscape:cy="238.90108"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g4496"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1014"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1" /><metadata
|
||||
id="metadata4524"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-540.36216)"><g
|
||||
id="g4467"
|
||||
transform="matrix(20.50952,0,0,20.859456,-526.58031,-94.042799)"><g
|
||||
inkscape:export-ydpi="67.349998"
|
||||
inkscape:export-xdpi="67.349998"
|
||||
transform="matrix(0.59473169,0,0,0.59473169,31.04719,102.48374)"
|
||||
id="g4382"><g
|
||||
id="g4496"><path
|
||||
sodipodi:type="star"
|
||||
style="opacity:1;fill:#7c7c7c;fill-opacity:1;stroke:none;stroke-width:1.10000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path4162"
|
||||
sodipodi:sides="6"
|
||||
sodipodi:cx="12.46875"
|
||||
sodipodi:cy="-99.893143"
|
||||
sodipodi:r1="19.266006"
|
||||
sodipodi:r2="16.307295"
|
||||
sodipodi:arg1="-0.52224059"
|
||||
sodipodi:arg2="0.0013581913"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0.12490573"
|
||||
inkscape:randomized="0"
|
||||
d="m 29.166669,-109.50348 c 1.200386,2.08567 1.17988,17.183595 -0.02617,19.265993 -1.206046,2.082397 -14.291486,9.613601 -16.697919,9.610333 -2.406432,-0.0033 -15.4713664,-7.56999 -16.671752,-9.655655 -1.2003857,-2.085666 -1.1798799,-17.183591 0.026167,-19.265991 1.2060467,-2.0824 14.2914862,-9.6136 16.6979192,-9.61033 2.406432,0.003 15.471366,7.56999 16.671752,9.65565 z"
|
||||
transform="rotate(-30,10.993604,-99.259973)"
|
||||
inkscape:export-xdpi="67.349998"
|
||||
inkscape:export-ydpi="67.349998" /><rect
|
||||
inkscape:transform-center-x="0.40624986"
|
||||
ry="2.4183984"
|
||||
y="-104.9176"
|
||||
x="2.2207832"
|
||||
height="8.7434387"
|
||||
width="8.7434387"
|
||||
id="rect4168-1-1"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.29999995;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /><g
|
||||
transform="translate(0,0.14463441)"
|
||||
id="g4491"><rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.29999995;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4168-1-1-7"
|
||||
width="8.7434387"
|
||||
height="8.7434387"
|
||||
x="9.0890703"
|
||||
y="-98.734459"
|
||||
ry="2.4183986" /><rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.29999995;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4168-1-1-7-2"
|
||||
width="8.7434387"
|
||||
height="8.7434387"
|
||||
x="9.0890703"
|
||||
y="-111.39002"
|
||||
ry="2.4183986" /></g><ellipse
|
||||
style="fill:#ca3636;stroke-width:1.36965;fill-opacity:1"
|
||||
id="path1"
|
||||
cx="23.01207"
|
||||
cy="-89.902901"
|
||||
rx="9.6073742"
|
||||
ry="9.4462013" /><path
|
||||
d="m 26.439777,-95.584412 c 0.161271,-0.368194 0.04101,-0.798203 -0.289743,-1.034712 -0.330744,-0.236504 -0.781758,-0.215002 -1.090634,0.04838 l -6.997553,6.020141 c -0.273341,0.236508 -0.371745,0.615454 -0.243273,0.948711 0.12847,0.333256 0.45648,0.559013 0.820025,0.559013 h 3.047762 l -2.101999,4.821487 c -0.161272,0.368197 -0.041,0.798206 0.289742,1.034712 0.330744,0.236506 0.781758,0.215005 1.090634,-0.04837 l 6.997553,-6.020141 c 0.273342,-0.236505 0.371745,-0.615454 0.243274,-0.948711 -0.12847,-0.333256 -0.453747,-0.556325 -0.820026,-0.556325 h -3.047762 z"
|
||||
id="path1-7"
|
||||
style="fill:#ffffff;stroke-width:0.027104" /></g></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB |
108
dashboard/public/img/not_found.svg
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="546.13336"
|
||||
height="546.13336"
|
||||
viewBox="0 0 512.00001 512.00001"
|
||||
id="svg4519"
|
||||
version="1.1"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="not_found.svg"
|
||||
inkscape:export-filename="/home/nebulon/Cloudron/Assets/logo_115.png"
|
||||
inkscape:export-xdpi="20.214842"
|
||||
inkscape:export-ydpi="20.214842"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"><defs
|
||||
id="defs4521" /><sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.98994949"
|
||||
inkscape:cx="250.01276"
|
||||
inkscape:cy="239.91123"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g4496"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1014"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1" /><metadata
|
||||
id="metadata4524"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-540.36216)"><g
|
||||
id="g4467"
|
||||
transform="matrix(20.50952,0,0,20.859456,-526.58031,-94.042799)"><g
|
||||
inkscape:export-ydpi="67.349998"
|
||||
inkscape:export-xdpi="67.349998"
|
||||
transform="matrix(0.59473169,0,0,0.59473169,31.04719,102.48374)"
|
||||
id="g4382"><g
|
||||
id="g4496"><path
|
||||
sodipodi:type="star"
|
||||
style="opacity:1;fill:#7c7c7c;fill-opacity:1;stroke:none;stroke-width:1.10000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path4162"
|
||||
sodipodi:sides="6"
|
||||
sodipodi:cx="12.46875"
|
||||
sodipodi:cy="-99.893143"
|
||||
sodipodi:r1="19.266006"
|
||||
sodipodi:r2="16.307295"
|
||||
sodipodi:arg1="-0.52224059"
|
||||
sodipodi:arg2="0.0013581913"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0.12490573"
|
||||
inkscape:randomized="0"
|
||||
d="m 29.166669,-109.50348 c 1.200386,2.08567 1.17988,17.183595 -0.02617,19.265993 -1.206046,2.082397 -14.291486,9.613601 -16.697919,9.610333 -2.406432,-0.0033 -15.4713664,-7.56999 -16.671752,-9.655655 -1.2003857,-2.085666 -1.1798799,-17.183591 0.026167,-19.265991 1.2060467,-2.0824 14.2914862,-9.6136 16.6979192,-9.61033 2.406432,0.003 15.471366,7.56999 16.671752,9.65565 z"
|
||||
transform="rotate(-30,10.993604,-99.259973)"
|
||||
inkscape:export-xdpi="67.349998"
|
||||
inkscape:export-ydpi="67.349998" /><rect
|
||||
inkscape:transform-center-x="0.40624986"
|
||||
ry="2.4183984"
|
||||
y="-104.9176"
|
||||
x="2.2207832"
|
||||
height="8.7434387"
|
||||
width="8.7434387"
|
||||
id="rect4168-1-1"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.29999995;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /><g
|
||||
transform="translate(0,0.14463441)"
|
||||
id="g4491"><rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.29999995;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4168-1-1-7"
|
||||
width="8.7434387"
|
||||
height="8.7434387"
|
||||
x="9.0890703"
|
||||
y="-98.734459"
|
||||
ry="2.4183986" /><rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.29999995;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4168-1-1-7-2"
|
||||
width="8.7434387"
|
||||
height="8.7434387"
|
||||
x="9.0890703"
|
||||
y="-111.39002"
|
||||
ry="2.4183986" /></g><ellipse
|
||||
style="fill:#1a76bf;stroke-width:1.36965;fill-opacity:1"
|
||||
id="path1"
|
||||
cx="23.01207"
|
||||
cy="-89.902901"
|
||||
rx="9.6073742"
|
||||
ry="9.4462013" /><path
|
||||
d="m 22.28174,-94.476029 h -3.651649 c -0.403963,0 -0.730329,0.320891 -0.730329,0.718076 v 1.436157 c 0,0.397187 0.326366,0.718079 0.730329,0.718079 h 8.613327 c 0.09585,0 0.189429,-0.03815 0.257897,-0.105469 l 1.095495,-1.077115 c 0.141502,-0.139127 0.141502,-0.368016 0,-0.507142 l -1.095495,-1.07712 c -0.06847,-0.06732 -0.162041,-0.105466 -0.257897,-0.105466 h -3.501017 c 0,-0.397187 -0.326367,-0.718075 -0.730331,-0.718075 -0.403964,0 -0.73033,0.320888 -0.73033,0.718075 z m 5.842639,5.026544 c 0,-0.397185 -0.326366,-0.718078 -0.730331,-0.718078 h -3.651647 v -0.718076 H 22.28174 v 0.718076 h -3.501017 c -0.09585,0 -0.18943,0.03815 -0.257898,0.105468 l -1.095496,1.077117 c -0.141501,0.139127 -0.141501,0.368014 0,0.507141 l 1.095496,1.077118 c 0.06847,0.06732 0.162042,0.105467 0.257898,0.105467 h 8.613325 c 0.403965,0 0.730331,-0.320892 0.730331,-0.718078 z m -4.381978,5.026544 v -2.154233 H 22.28174 v 2.154233 c 0,0.397187 0.326366,0.718078 0.73033,0.718078 0.403964,0 0.730331,-0.320891 0.730331,-0.718078 z"
|
||||
id="path1-3"
|
||||
style="fill:#ffffff;stroke-width:0.0226306" /></g></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
@@ -1,99 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/* global $, angular, redirectIfNeeded */
|
||||
|
||||
// create main application module
|
||||
var app = angular.module('Application', ['pascalprecht.translate', 'ngCookies', 'angular-md5', 'ui-notification', 'ui.bootstrap']);
|
||||
|
||||
app.controller('SetupController', ['$scope', 'Client', function ($scope, Client) {
|
||||
// Stupid angular location provider either wants html5 location mode or not, do the query parsing on my own
|
||||
const search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.split('='); }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {});
|
||||
|
||||
$scope.client = Client;
|
||||
$scope.view = '';
|
||||
$scope.initialized = false;
|
||||
$scope.setupToken = '';
|
||||
$scope.firstTimeLoginUrl = '';
|
||||
|
||||
$scope.owner = {
|
||||
error: null,
|
||||
busy: false,
|
||||
|
||||
email: '',
|
||||
displayName: '',
|
||||
username: '',
|
||||
password: '',
|
||||
|
||||
submit: function () {
|
||||
$scope.owner.busy = true;
|
||||
$scope.owner.error = null;
|
||||
|
||||
var data = {
|
||||
username: $scope.owner.username,
|
||||
password: $scope.owner.password,
|
||||
email: $scope.owner.email,
|
||||
displayName: $scope.owner.displayName,
|
||||
setupToken: $scope.setupToken
|
||||
};
|
||||
|
||||
Client.createAdmin(data, function (error, autoLoginToken) {
|
||||
if (error && error.statusCode === 400) {
|
||||
$scope.owner.busy = false;
|
||||
|
||||
if (error.message === 'Invalid email') {
|
||||
$scope.owner.error = { email: error.message };
|
||||
$scope.owner.email = '';
|
||||
$scope.ownerForm.email.$setPristine();
|
||||
setTimeout(function () { $('#inputEmail').focus(); }, 200);
|
||||
} else {
|
||||
$scope.owner.error = { username: error.message };
|
||||
$scope.owner.username = '';
|
||||
$scope.ownerForm.username.$setPristine();
|
||||
setTimeout(function () { $('#inputUsername').focus(); }, 200);
|
||||
}
|
||||
return;
|
||||
} else if (error) {
|
||||
$scope.owner.busy = false;
|
||||
console.error('Internal error', error);
|
||||
$scope.owner.error = { generic: error.message };
|
||||
return;
|
||||
}
|
||||
|
||||
// set token to autologin on first oidc flow
|
||||
localStorage.cloudronFirstTimeToken = autoLoginToken;
|
||||
|
||||
$scope.firstTimeLoginUrl = '/openid/auth?client_id=cid-webadmin&scope=openid email profile&response_type=code token&redirect_uri=' + window.location.origin + '/authcallback.html';
|
||||
|
||||
setView('finished');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function setView(view) {
|
||||
if (view === 'finished') {
|
||||
$scope.view = 'finished';
|
||||
} else {
|
||||
$scope.view = 'owner';
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
Client.getProvisionStatus(function (error, status) {
|
||||
if (error) return Client.initError(error, init);
|
||||
|
||||
if (redirectIfNeeded(status, 'activation')) return; // redirected to some other view...
|
||||
|
||||
setView(search.view);
|
||||
|
||||
$scope.setupToken = search.setupToken;
|
||||
$scope.initialized = true;
|
||||
|
||||
// Ensure we have a good autofocus
|
||||
setTimeout(function () {
|
||||
$(document).find("[autofocus]:first").focus();
|
||||
}, 250);
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
}]);
|
||||
57
dashboard/public/js/angular-animate.min.js
vendored
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
AngularJS v1.5.8
|
||||
(c) 2010-2016 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(R,B){'use strict';function Da(a,b,c){if(!a)throw Ma("areq",b||"?",c||"required");return a}function Ea(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;Y(a)&&(a=a.join(" "));Y(b)&&(b=b.join(" "));return a+" "+b}function Na(a){var b={};a&&(a.to||a.from)&&(b.to=a.to,b.from=a.from);return b}function Z(a,b,c){var d="";a=Y(a)?a:a&&G(a)&&a.length?a.split(/\s+/):[];s(a,function(a,l){a&&0<a.length&&(d+=0<l?" ":"",d+=c?b+a:a+b)});return d}function Oa(a){if(a instanceof F)switch(a.length){case 0:return a;
|
||||
case 1:if(1===a[0].nodeType)return a;break;default:return F(ta(a))}if(1===a.nodeType)return F(a)}function ta(a){if(!a[0])return a;for(var b=0;b<a.length;b++){var c=a[b];if(1==c.nodeType)return c}}function Pa(a,b,c){s(b,function(b){a.addClass(b,c)})}function Qa(a,b,c){s(b,function(b){a.removeClass(b,c)})}function V(a){return function(b,c){c.addClass&&(Pa(a,b,c.addClass),c.addClass=null);c.removeClass&&(Qa(a,b,c.removeClass),c.removeClass=null)}}function oa(a){a=a||{};if(!a.$$prepared){var b=a.domOperation||
|
||||
P;a.domOperation=function(){a.$$domOperationFired=!0;b();b=P};a.$$prepared=!0}return a}function ha(a,b){Fa(a,b);Ga(a,b)}function Fa(a,b){b.from&&(a.css(b.from),b.from=null)}function Ga(a,b){b.to&&(a.css(b.to),b.to=null)}function W(a,b,c){var d=b.options||{};c=c.options||{};var e=(d.addClass||"")+" "+(c.addClass||""),l=(d.removeClass||"")+" "+(c.removeClass||"");a=Ra(a.attr("class"),e,l);c.preparationClasses&&(d.preparationClasses=$(c.preparationClasses,d.preparationClasses),delete c.preparationClasses);
|
||||
e=d.domOperation!==P?d.domOperation:null;ua(d,c);e&&(d.domOperation=e);d.addClass=a.addClass?a.addClass:null;d.removeClass=a.removeClass?a.removeClass:null;b.addClass=d.addClass;b.removeClass=d.removeClass;return d}function Ra(a,b,c){function d(a){G(a)&&(a=a.split(" "));var b={};s(a,function(a){a.length&&(b[a]=!0)});return b}var e={};a=d(a);b=d(b);s(b,function(a,b){e[b]=1});c=d(c);s(c,function(a,b){e[b]=1===e[b]?null:-1});var l={addClass:"",removeClass:""};s(e,function(b,c){var d,e;1===b?(d="addClass",
|
||||
e=!a[c]||a[c+"-remove"]):-1===b&&(d="removeClass",e=a[c]||a[c+"-add"]);e&&(l[d].length&&(l[d]+=" "),l[d]+=c)});return l}function y(a){return a instanceof F?a[0]:a}function Sa(a,b,c){var d="";b&&(d=Z(b,"ng-",!0));c.addClass&&(d=$(d,Z(c.addClass,"-add")));c.removeClass&&(d=$(d,Z(c.removeClass,"-remove")));d.length&&(c.preparationClasses=d,a.addClass(d))}function pa(a,b){var c=b?"-"+b+"s":"";la(a,[ma,c]);return[ma,c]}function va(a,b){var c=b?"paused":"",d=aa+"PlayState";la(a,[d,c]);return[d,c]}function la(a,
|
||||
b){a.style[b[0]]=b[1]}function $(a,b){return a?b?a+" "+b:a:b}function Ha(a,b,c){var d=Object.create(null),e=a.getComputedStyle(b)||{};s(c,function(a,b){var c=e[a];if(c){var g=c.charAt(0);if("-"===g||"+"===g||0<=g)c=Ta(c);0===c&&(c=null);d[b]=c}});return d}function Ta(a){var b=0;a=a.split(/\s*,\s*/);s(a,function(a){"s"==a.charAt(a.length-1)&&(a=a.substring(0,a.length-1));a=parseFloat(a)||0;b=b?Math.max(a,b):a});return b}function wa(a){return 0===a||null!=a}function Ia(a,b){var c=S,d=a+"s";b?c+="Duration":
|
||||
d+=" linear all";return[c,d]}function Ja(){var a=Object.create(null);return{flush:function(){a=Object.create(null)},count:function(b){return(b=a[b])?b.total:0},get:function(b){return(b=a[b])&&b.value},put:function(b,c){a[b]?a[b].total++:a[b]={total:1,value:c}}}}function Ka(a,b,c){s(c,function(c){a[c]=xa(a[c])?a[c]:b.style.getPropertyValue(c)})}var S,ya,aa,za;void 0===R.ontransitionend&&void 0!==R.onwebkittransitionend?(S="WebkitTransition",ya="webkitTransitionEnd transitionend"):(S="transition",ya=
|
||||
"transitionend");void 0===R.onanimationend&&void 0!==R.onwebkitanimationend?(aa="WebkitAnimation",za="webkitAnimationEnd animationend"):(aa="animation",za="animationend");var qa=aa+"Delay",Aa=aa+"Duration",ma=S+"Delay",La=S+"Duration",Ma=B.$$minErr("ng"),Ua={transitionDuration:La,transitionDelay:ma,transitionProperty:S+"Property",animationDuration:Aa,animationDelay:qa,animationIterationCount:aa+"IterationCount"},Va={transitionDuration:La,transitionDelay:ma,animationDuration:Aa,animationDelay:qa},
|
||||
Ba,ua,s,Y,xa,ea,Ca,ba,G,J,F,P;B.module("ngAnimate",[],function(){P=B.noop;Ba=B.copy;ua=B.extend;F=B.element;s=B.forEach;Y=B.isArray;G=B.isString;ba=B.isObject;J=B.isUndefined;xa=B.isDefined;Ca=B.isFunction;ea=B.isElement}).directive("ngAnimateSwap",["$animate","$rootScope",function(a,b){return{restrict:"A",transclude:"element",terminal:!0,priority:600,link:function(b,d,e,l,n){var I,g;b.$watchCollection(e.ngAnimateSwap||e["for"],function(e){I&&a.leave(I);g&&(g.$destroy(),g=null);if(e||0===e)g=b.$new(),
|
||||
n(g,function(b){I=b;a.enter(b,null,d)})})}}}]).directive("ngAnimateChildren",["$interpolate",function(a){return{link:function(b,c,d){function e(a){c.data("$$ngAnimateChildren","on"===a||"true"===a)}var l=d.ngAnimateChildren;G(l)&&0===l.length?c.data("$$ngAnimateChildren",!0):(e(a(l)(b)),d.$observe("ngAnimateChildren",e))}}}]).factory("$$rAFScheduler",["$$rAF",function(a){function b(a){d=d.concat(a);c()}function c(){if(d.length){for(var b=d.shift(),n=0;n<b.length;n++)b[n]();e||a(function(){e||c()})}}
|
||||
var d,e;d=b.queue=[];b.waitUntilQuiet=function(b){e&&e();e=a(function(){e=null;b();c()})};return b}]).provider("$$animateQueue",["$animateProvider",function(a){function b(a){if(!a)return null;a=a.split(" ");var b=Object.create(null);s(a,function(a){b[a]=!0});return b}function c(a,c){if(a&&c){var d=b(c);return a.split(" ").some(function(a){return d[a]})}}function d(a,b,c,d){return l[a].some(function(a){return a(b,c,d)})}function e(a,b){var c=0<(a.addClass||"").length,d=0<(a.removeClass||"").length;
|
||||
return b?c&&d:c||d}var l=this.rules={skip:[],cancel:[],join:[]};l.join.push(function(a,b,c){return!b.structural&&e(b)});l.skip.push(function(a,b,c){return!b.structural&&!e(b)});l.skip.push(function(a,b,c){return"leave"==c.event&&b.structural});l.skip.push(function(a,b,c){return c.structural&&2===c.state&&!b.structural});l.cancel.push(function(a,b,c){return c.structural&&b.structural});l.cancel.push(function(a,b,c){return 2===c.state&&b.structural});l.cancel.push(function(a,b,d){if(d.structural)return!1;
|
||||
a=b.addClass;b=b.removeClass;var e=d.addClass;d=d.removeClass;return J(a)&&J(b)||J(e)&&J(d)?!1:c(a,d)||c(b,e)});this.$get=["$$rAF","$rootScope","$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$jqLite","$$forceReflow",function(b,c,g,l,C,Wa,Q,t,H,T){function O(){var a=!1;return function(b){a?b():c.$$postDigest(function(){a=!0;b()})}}function x(a,b,c){var f=y(b),d=y(a),N=[];(a=h[c])&&s(a,function(a){w.call(a.node,f)?N.push(a.callback):"leave"===c&&w.call(a.node,
|
||||
d)&&N.push(a.callback)});return N}function r(a,b,c){var f=ta(b);return a.filter(function(a){return!(a.node===f&&(!c||a.callback===c))})}function p(a,h,v){function r(c,f,d,h){sa(function(){var c=x(T,a,f);c.length?b(function(){s(c,function(b){b(a,d,h)});"close"!==d||a[0].parentNode||ra.off(a)}):"close"!==d||a[0].parentNode||ra.off(a)});c.progress(f,d,h)}function k(b){var c=a,f=m;f.preparationClasses&&(c.removeClass(f.preparationClasses),f.preparationClasses=null);f.activeClasses&&(c.removeClass(f.activeClasses),
|
||||
f.activeClasses=null);E(a,m);ha(a,m);m.domOperation();A.complete(!b)}var m=Ba(v),p,T;if(a=Oa(a))p=y(a),T=a.parent();var m=oa(m),A=new Q,sa=O();Y(m.addClass)&&(m.addClass=m.addClass.join(" "));m.addClass&&!G(m.addClass)&&(m.addClass=null);Y(m.removeClass)&&(m.removeClass=m.removeClass.join(" "));m.removeClass&&!G(m.removeClass)&&(m.removeClass=null);m.from&&!ba(m.from)&&(m.from=null);m.to&&!ba(m.to)&&(m.to=null);if(!p)return k(),A;v=[p.className,m.addClass,m.removeClass].join(" ");if(!Xa(v))return k(),
|
||||
A;var g=0<=["enter","move","leave"].indexOf(h),w=l[0].hidden,t=!f||w||N.get(p);v=!t&&z.get(p)||{};var H=!!v.state;t||H&&1==v.state||(t=!M(a,T,h));if(t)return w&&r(A,h,"start"),k(),w&&r(A,h,"close"),A;g&&K(a);w={structural:g,element:a,event:h,addClass:m.addClass,removeClass:m.removeClass,close:k,options:m,runner:A};if(H){if(d("skip",a,w,v)){if(2===v.state)return k(),A;W(a,v,w);return v.runner}if(d("cancel",a,w,v))if(2===v.state)v.runner.end();else if(v.structural)v.close();else return W(a,v,w),v.runner;
|
||||
else if(d("join",a,w,v))if(2===v.state)W(a,w,{});else return Sa(a,g?h:null,m),h=w.event=v.event,m=W(a,v,w),v.runner}else W(a,w,{});(H=w.structural)||(H="animate"===w.event&&0<Object.keys(w.options.to||{}).length||e(w));if(!H)return k(),ka(a),A;var C=(v.counter||0)+1;w.counter=C;L(a,1,w);c.$$postDigest(function(){var b=z.get(p),c=!b,b=b||{},f=0<(a.parent()||[]).length&&("animate"===b.event||b.structural||e(b));if(c||b.counter!==C||!f){c&&(E(a,m),ha(a,m));if(c||g&&b.event!==h)m.domOperation(),A.end();
|
||||
f||ka(a)}else h=!b.structural&&e(b,!0)?"setClass":b.event,L(a,2),b=Wa(a,h,b.options),A.setHost(b),r(A,h,"start",{}),b.done(function(b){k(!b);(b=z.get(p))&&b.counter===C&&ka(y(a));r(A,h,"close",{})})});return A}function K(a){a=y(a).querySelectorAll("[data-ng-animate]");s(a,function(a){var b=parseInt(a.getAttribute("data-ng-animate")),c=z.get(a);if(c)switch(b){case 2:c.runner.end();case 1:z.remove(a)}})}function ka(a){a=y(a);a.removeAttribute("data-ng-animate");z.remove(a)}function k(a,b){return y(a)===
|
||||
y(b)}function M(a,b,c){c=F(l[0].body);var f=k(a,c)||"HTML"===a[0].nodeName,d=k(a,g),h=!1,r,e=N.get(y(a));(a=F.data(a[0],"$ngAnimatePin"))&&(b=a);for(b=y(b);b;){d||(d=k(b,g));if(1!==b.nodeType)break;a=z.get(b)||{};if(!h){var p=N.get(b);if(!0===p&&!1!==e){e=!0;break}else!1===p&&(e=!1);h=a.structural}if(J(r)||!0===r)a=F.data(b,"$$ngAnimateChildren"),xa(a)&&(r=a);if(h&&!1===r)break;f||(f=k(b,c));if(f&&d)break;if(!d&&(a=F.data(b,"$ngAnimatePin"))){b=y(a);continue}b=b.parentNode}return(!h||r)&&!0!==e&&
|
||||
d&&f}function L(a,b,c){c=c||{};c.state=b;a=y(a);a.setAttribute("data-ng-animate",b);c=(b=z.get(a))?ua(b,c):c;z.put(a,c)}var z=new C,N=new C,f=null,A=c.$watch(function(){return 0===t.totalPendingRequests},function(a){a&&(A(),c.$$postDigest(function(){c.$$postDigest(function(){null===f&&(f=!0)})}))}),h=Object.create(null),sa=a.classNameFilter(),Xa=sa?function(a){return sa.test(a)}:function(){return!0},E=V(H),w=R.Node.prototype.contains||function(a){return this===a||!!(this.compareDocumentPosition(a)&
|
||||
16)},ra={on:function(a,b,c){var f=ta(b);h[a]=h[a]||[];h[a].push({node:f,callback:c});F(b).on("$destroy",function(){z.get(f)||ra.off(a,b,c)})},off:function(a,b,c){if(1!==arguments.length||G(arguments[0])){var f=h[a];f&&(h[a]=1===arguments.length?null:r(f,b,c))}else for(f in b=arguments[0],h)h[f]=r(h[f],b)},pin:function(a,b){Da(ea(a),"element","not an element");Da(ea(b),"parentElement","not an element");a.data("$ngAnimatePin",b)},push:function(a,b,c,f){c=c||{};c.domOperation=f;return p(a,b,c)},enabled:function(a,
|
||||
b){var c=arguments.length;if(0===c)b=!!f;else if(ea(a)){var d=y(a);1===c?b=!N.get(d):N.put(d,!b)}else b=f=!!a;return b}};return ra}]}]).provider("$$animation",["$animateProvider",function(a){var b=this.drivers=[];this.$get=["$$jqLite","$rootScope","$injector","$$AnimateRunner","$$HashMap","$$rAFScheduler",function(a,d,e,l,n,I){function g(a){function b(a){if(a.processed)return a;a.processed=!0;var d=a.domNode,p=d.parentNode;e.put(d,a);for(var K;p;){if(K=e.get(p)){K.processed||(K=b(K));break}p=p.parentNode}(K||
|
||||
c).children.push(a);return a}var c={children:[]},d,e=new n;for(d=0;d<a.length;d++){var g=a[d];e.put(g.domNode,a[d]={domNode:g.domNode,fn:g.fn,children:[]})}for(d=0;d<a.length;d++)b(a[d]);return function(a){var b=[],c=[],d;for(d=0;d<a.children.length;d++)c.push(a.children[d]);a=c.length;var e=0,k=[];for(d=0;d<c.length;d++){var g=c[d];0>=a&&(a=e,e=0,b.push(k),k=[]);k.push(g.fn);g.children.forEach(function(a){e++;c.push(a)});a--}k.length&&b.push(k);return b}(c)}var u=[],C=V(a);return function(n,Q,t){function H(a){a=
|
||||
a.hasAttribute("ng-animate-ref")?[a]:a.querySelectorAll("[ng-animate-ref]");var b=[];s(a,function(a){var c=a.getAttribute("ng-animate-ref");c&&c.length&&b.push(a)});return b}function T(a){var b=[],c={};s(a,function(a,d){var h=y(a.element),e=0<=["enter","move"].indexOf(a.event),h=a.structural?H(h):[];if(h.length){var k=e?"to":"from";s(h,function(a){var b=a.getAttribute("ng-animate-ref");c[b]=c[b]||{};c[b][k]={animationID:d,element:F(a)}})}else b.push(a)});var d={},e={};s(c,function(c,k){var r=c.from,
|
||||
p=c.to;if(r&&p){var z=a[r.animationID],g=a[p.animationID],A=r.animationID.toString();if(!e[A]){var n=e[A]={structural:!0,beforeStart:function(){z.beforeStart();g.beforeStart()},close:function(){z.close();g.close()},classes:O(z.classes,g.classes),from:z,to:g,anchors:[]};n.classes.length?b.push(n):(b.push(z),b.push(g))}e[A].anchors.push({out:r.element,"in":p.element})}else r=r?r.animationID:p.animationID,p=r.toString(),d[p]||(d[p]=!0,b.push(a[r]))});return b}function O(a,b){a=a.split(" ");b=b.split(" ");
|
||||
for(var c=[],d=0;d<a.length;d++){var e=a[d];if("ng-"!==e.substring(0,3))for(var r=0;r<b.length;r++)if(e===b[r]){c.push(e);break}}return c.join(" ")}function x(a){for(var c=b.length-1;0<=c;c--){var d=e.get(b[c])(a);if(d)return d}}function r(a,b){function c(a){(a=a.data("$$animationRunner"))&&a.setHost(b)}a.from&&a.to?(c(a.from.element),c(a.to.element)):c(a.element)}function p(){var a=n.data("$$animationRunner");!a||"leave"===Q&&t.$$domOperationFired||a.end()}function K(b){n.off("$destroy",p);n.removeData("$$animationRunner");
|
||||
C(n,t);ha(n,t);t.domOperation();L&&a.removeClass(n,L);n.removeClass("ng-animate");k.complete(!b)}t=oa(t);var ka=0<=["enter","move","leave"].indexOf(Q),k=new l({end:function(){K()},cancel:function(){K(!0)}});if(!b.length)return K(),k;n.data("$$animationRunner",k);var M=Ea(n.attr("class"),Ea(t.addClass,t.removeClass)),L=t.tempClasses;L&&(M+=" "+L,t.tempClasses=null);var z;ka&&(z="ng-"+Q+"-prepare",a.addClass(n,z));u.push({element:n,classes:M,event:Q,structural:ka,options:t,beforeStart:function(){n.addClass("ng-animate");
|
||||
L&&a.addClass(n,L);z&&(a.removeClass(n,z),z=null)},close:K});n.on("$destroy",p);if(1<u.length)return k;d.$$postDigest(function(){var a=[];s(u,function(b){b.element.data("$$animationRunner")?a.push(b):b.close()});u.length=0;var b=T(a),c=[];s(b,function(a){c.push({domNode:y(a.from?a.from.element:a.element),fn:function(){a.beforeStart();var b,c=a.close;if((a.anchors?a.from.element||a.to.element:a.element).data("$$animationRunner")){var d=x(a);d&&(b=d.start)}b?(b=b(),b.done(function(a){c(!a)}),r(a,b)):
|
||||
c()}})});I(g(c))});return k}}]}]).provider("$animateCss",["$animateProvider",function(a){var b=Ja(),c=Ja();this.$get=["$window","$$jqLite","$$AnimateRunner","$timeout","$$forceReflow","$sniffer","$$rAFScheduler","$$animateQueue",function(a,e,l,n,I,g,u,C){function B(a,b){var c=a.parentNode;return(c.$$ngAnimateParentKey||(c.$$ngAnimateParentKey=++O))+"-"+a.getAttribute("class")+"-"+b}function Q(r,p,g,n){var k;0<b.count(g)&&(k=c.get(g),k||(p=Z(p,"-stagger"),e.addClass(r,p),k=Ha(a,r,n),k.animationDuration=
|
||||
Math.max(k.animationDuration,0),k.transitionDuration=Math.max(k.transitionDuration,0),e.removeClass(r,p),c.put(g,k)));return k||{}}function t(a){x.push(a);u.waitUntilQuiet(function(){b.flush();c.flush();for(var a=I(),d=0;d<x.length;d++)x[d](a);x.length=0})}function H(c,e,g){e=b.get(g);e||(e=Ha(a,c,Ua),"infinite"===e.animationIterationCount&&(e.animationIterationCount=1));b.put(g,e);c=e;g=c.animationDelay;e=c.transitionDelay;c.maxDelay=g&&e?Math.max(g,e):g||e;c.maxDuration=Math.max(c.animationDuration*
|
||||
c.animationIterationCount,c.transitionDuration);return c}var T=V(e),O=0,x=[];return function(a,c){function d(){k()}function u(){k(!0)}function k(b){if(!(w||F&&O)){w=!0;O=!1;f.$$skipPreparationClasses||e.removeClass(a,ga);e.removeClass(a,ea);va(h,!1);pa(h,!1);s(x,function(a){h.style[a[0]]=""});T(a,f);ha(a,f);Object.keys(A).length&&s(A,function(a,b){a?h.style.setProperty(b,a):h.style.removeProperty(b)});if(f.onDone)f.onDone();fa&&fa.length&&a.off(fa.join(" "),z);var c=a.data("$$animateCss");c&&(n.cancel(c[0].timer),
|
||||
a.removeData("$$animateCss"));G&&G.complete(!b)}}function M(a){q.blockTransition&&pa(h,a);q.blockKeyframeAnimation&&va(h,!!a)}function L(){G=new l({end:d,cancel:u});t(P);k();return{$$willAnimate:!1,start:function(){return G},end:d}}function z(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-W,0)>=R&&b>=m&&(F=!0,k())}function N(){function b(){if(!w){M(!1);s(x,function(a){h.style[a[0]]=a[1]});T(a,f);e.addClass(a,ea);if(q.recalculateTimingStyles){na=
|
||||
h.className+" "+ga;ia=B(h,na);D=H(h,na,ia);ca=D.maxDelay;J=Math.max(ca,0);m=D.maxDuration;if(0===m){k();return}q.hasTransitions=0<D.transitionDuration;q.hasAnimations=0<D.animationDuration}q.applyAnimationDelay&&(ca="boolean"!==typeof f.delay&&wa(f.delay)?parseFloat(f.delay):ca,J=Math.max(ca,0),D.animationDelay=ca,da=[qa,ca+"s"],x.push(da),h.style[da[0]]=da[1]);R=1E3*J;V=1E3*m;if(f.easing){var d,g=f.easing;q.hasTransitions&&(d=S+"TimingFunction",x.push([d,g]),h.style[d]=g);q.hasAnimations&&(d=aa+
|
||||
"TimingFunction",x.push([d,g]),h.style[d]=g)}D.transitionDuration&&fa.push(ya);D.animationDuration&&fa.push(za);W=Date.now();var p=R+1.5*V;d=W+p;var g=a.data("$$animateCss")||[],N=!0;if(g.length){var l=g[0];(N=d>l.expectedEndTime)?n.cancel(l.timer):g.push(k)}N&&(p=n(c,p,!1),g[0]={timer:p,expectedEndTime:d},g.push(k),a.data("$$animateCss",g));if(fa.length)a.on(fa.join(" "),z);f.to&&(f.cleanupStyles&&Ka(A,h,Object.keys(f.to)),Ga(a,f))}}function c(){var b=a.data("$$animateCss");if(b){for(var d=1;d<b.length;d++)b[d]();
|
||||
a.removeData("$$animateCss")}}if(!w)if(h.parentNode){var d=function(a){if(F)O&&a&&(O=!1,k());else if(O=!a,D.animationDuration)if(a=va(h,O),O)x.push(a);else{var b=x,c=b.indexOf(a);0<=a&&b.splice(c,1)}},g=0<ba&&(D.transitionDuration&&0===X.transitionDuration||D.animationDuration&&0===X.animationDuration)&&Math.max(X.animationDelay,X.transitionDelay);g?n(b,Math.floor(g*ba*1E3),!1):b();v.resume=function(){d(!0)};v.pause=function(){d(!1)}}else k()}var f=c||{};f.$$prepared||(f=oa(Ba(f)));var A={},h=y(a);
|
||||
if(!h||!h.parentNode||!C.enabled())return L();var x=[],I=a.attr("class"),E=Na(f),w,O,F,G,v,J,R,m,V,W,fa=[];if(0===f.duration||!g.animations&&!g.transitions)return L();var ja=f.event&&Y(f.event)?f.event.join(" "):f.event,$="",U="";ja&&f.structural?$=Z(ja,"ng-",!0):ja&&($=ja);f.addClass&&(U+=Z(f.addClass,"-add"));f.removeClass&&(U.length&&(U+=" "),U+=Z(f.removeClass,"-remove"));f.applyClassesEarly&&U.length&&T(a,f);var ga=[$,U].join(" ").trim(),na=I+" "+ga,ea=Z(ga,"-active"),I=E.to&&0<Object.keys(E.to).length;
|
||||
if(!(0<(f.keyframeStyle||"").length||I||ga))return L();var ia,X;0<f.stagger?(E=parseFloat(f.stagger),X={transitionDelay:E,animationDelay:E,transitionDuration:0,animationDuration:0}):(ia=B(h,na),X=Q(h,ga,ia,Va));f.$$skipPreparationClasses||e.addClass(a,ga);f.transitionStyle&&(E=[S,f.transitionStyle],la(h,E),x.push(E));0<=f.duration&&(E=0<h.style[S].length,E=Ia(f.duration,E),la(h,E),x.push(E));f.keyframeStyle&&(E=[aa,f.keyframeStyle],la(h,E),x.push(E));var ba=X?0<=f.staggerIndex?f.staggerIndex:b.count(ia):
|
||||
0;(ja=0===ba)&&!f.skipBlocking&&pa(h,9999);var D=H(h,na,ia),ca=D.maxDelay;J=Math.max(ca,0);m=D.maxDuration;var q={};q.hasTransitions=0<D.transitionDuration;q.hasAnimations=0<D.animationDuration;q.hasTransitionAll=q.hasTransitions&&"all"==D.transitionProperty;q.applyTransitionDuration=I&&(q.hasTransitions&&!q.hasTransitionAll||q.hasAnimations&&!q.hasTransitions);q.applyAnimationDuration=f.duration&&q.hasAnimations;q.applyTransitionDelay=wa(f.delay)&&(q.applyTransitionDuration||q.hasTransitions);q.applyAnimationDelay=
|
||||
wa(f.delay)&&q.hasAnimations;q.recalculateTimingStyles=0<U.length;if(q.applyTransitionDuration||q.applyAnimationDuration)m=f.duration?parseFloat(f.duration):m,q.applyTransitionDuration&&(q.hasTransitions=!0,D.transitionDuration=m,E=0<h.style[S+"Property"].length,x.push(Ia(m,E))),q.applyAnimationDuration&&(q.hasAnimations=!0,D.animationDuration=m,x.push([Aa,m+"s"]));if(0===m&&!q.recalculateTimingStyles)return L();if(null!=f.delay){var da;"boolean"!==typeof f.delay&&(da=parseFloat(f.delay),J=Math.max(da,
|
||||
0));q.applyTransitionDelay&&x.push([ma,da+"s"]);q.applyAnimationDelay&&x.push([qa,da+"s"])}null==f.duration&&0<D.transitionDuration&&(q.recalculateTimingStyles=q.recalculateTimingStyles||ja);R=1E3*J;V=1E3*m;f.skipBlocking||(q.blockTransition=0<D.transitionDuration,q.blockKeyframeAnimation=0<D.animationDuration&&0<X.animationDelay&&0===X.animationDuration);f.from&&(f.cleanupStyles&&Ka(A,h,Object.keys(f.from)),Fa(a,f));q.blockTransition||q.blockKeyframeAnimation?M(m):f.skipBlocking||pa(h,!1);return{$$willAnimate:!0,
|
||||
end:d,start:function(){if(!w)return v={end:d,cancel:u,resume:null,pause:null},G=new l(v),t(N),G}}}}]}]).provider("$$animateCssDriver",["$$animationProvider",function(a){a.drivers.push("$$animateCssDriver");this.$get=["$animateCss","$rootScope","$$AnimateRunner","$rootElement","$sniffer","$$jqLite","$document",function(a,c,d,e,l,n,I){function g(a){return a.replace(/\bng-\S+\b/g,"")}function u(a,b){G(a)&&(a=a.split(" "));G(b)&&(b=b.split(" "));return a.filter(function(a){return-1===b.indexOf(a)}).join(" ")}
|
||||
function C(c,e,n){function l(a){var b={},c=y(a).getBoundingClientRect();s(["width","height","top","left"],function(a){var d=c[a];switch(a){case "top":d+=t.scrollTop;break;case "left":d+=t.scrollLeft}b[a]=Math.floor(d)+"px"});return b}function p(){var c=g(n.attr("class")||""),d=u(c,k),c=u(k,c),d=a(C,{to:l(n),addClass:"ng-anchor-in "+d,removeClass:"ng-anchor-out "+c,delay:!0});return d.$$willAnimate?d:null}function I(){C.remove();e.removeClass("ng-animate-shim");n.removeClass("ng-animate-shim")}var C=
|
||||
F(y(e).cloneNode(!0)),k=g(C.attr("class")||"");e.addClass("ng-animate-shim");n.addClass("ng-animate-shim");C.addClass("ng-anchor");H.append(C);var M;c=function(){var c=a(C,{addClass:"ng-anchor-out",delay:!0,from:l(e)});return c.$$willAnimate?c:null}();if(!c&&(M=p(),!M))return I();var L=c||M;return{start:function(){function a(){c&&c.end()}var b,c=L.start();c.done(function(){c=null;if(!M&&(M=p()))return c=M.start(),c.done(function(){c=null;I();b.complete()}),c;I();b.complete()});return b=new d({end:a,
|
||||
cancel:a})}}}function B(a,b,c,e){var g=Q(a,P),n=Q(b,P),l=[];s(e,function(a){(a=C(c,a.out,a["in"]))&&l.push(a)});if(g||n||0!==l.length)return{start:function(){function a(){s(b,function(a){a.end()})}var b=[];g&&b.push(g.start());n&&b.push(n.start());s(l,function(a){b.push(a.start())});var c=new d({end:a,cancel:a});d.all(b,function(a){c.complete(a)});return c}}}function Q(c){var d=c.element,e=c.options||{};c.structural&&(e.event=c.event,e.structural=!0,e.applyClassesEarly=!0,"leave"===c.event&&(e.onDone=
|
||||
e.domOperation));e.preparationClasses&&(e.event=$(e.event,e.preparationClasses));c=a(d,e);return c.$$willAnimate?c:null}if(!l.animations&&!l.transitions)return P;var t=I[0].body;c=y(e);var H=F(c.parentNode&&11===c.parentNode.nodeType||t.contains(c)?c:t);V(n);return function(a){return a.from&&a.to?B(a.from,a.to,a.classes,a.anchors):Q(a)}}]}]).provider("$$animateJs",["$animateProvider",function(a){this.$get=["$injector","$$AnimateRunner","$$jqLite",function(b,c,d){function e(c){c=Y(c)?c:c.split(" ");
|
||||
for(var d=[],e={},l=0;l<c.length;l++){var s=c[l],B=a.$$registeredAnimations[s];B&&!e[s]&&(d.push(b.get(B)),e[s]=!0)}return d}var l=V(d);return function(a,b,d,u){function C(){u.domOperation();l(a,u)}function B(a,b,d,e,f){switch(d){case "animate":b=[b,e.from,e.to,f];break;case "setClass":b=[b,F,G,f];break;case "addClass":b=[b,F,f];break;case "removeClass":b=[b,G,f];break;default:b=[b,f]}b.push(e);if(a=a.apply(a,b))if(Ca(a.start)&&(a=a.start()),a instanceof c)a.done(f);else if(Ca(a))return a;return P}
|
||||
function y(a,b,d,e,f){var g=[];s(e,function(e){var k=e[f];k&&g.push(function(){var e,f,g=!1,h=function(a){g||(g=!0,(f||P)(a),e.complete(!a))};e=new c({end:function(){h()},cancel:function(){h(!0)}});f=B(k,a,b,d,function(a){h(!1===a)});return e})});return g}function t(a,b,d,e,f){var g=y(a,b,d,e,f);if(0===g.length){var h,k;"beforeSetClass"===f?(h=y(a,"removeClass",d,e,"beforeRemoveClass"),k=y(a,"addClass",d,e,"beforeAddClass")):"setClass"===f&&(h=y(a,"removeClass",d,e,"removeClass"),k=y(a,"addClass",
|
||||
d,e,"addClass"));h&&(g=g.concat(h));k&&(g=g.concat(k))}if(0!==g.length)return function(a){var b=[];g.length&&s(g,function(a){b.push(a())});b.length?c.all(b,a):a();return function(a){s(b,function(b){a?b.cancel():b.end()})}}}var H=!1;3===arguments.length&&ba(d)&&(u=d,d=null);u=oa(u);d||(d=a.attr("class")||"",u.addClass&&(d+=" "+u.addClass),u.removeClass&&(d+=" "+u.removeClass));var F=u.addClass,G=u.removeClass,x=e(d),r,p;if(x.length){var K,J;"leave"==b?(J="leave",K="afterLeave"):(J="before"+b.charAt(0).toUpperCase()+
|
||||
b.substr(1),K=b);"enter"!==b&&"move"!==b&&(r=t(a,b,u,x,J));p=t(a,b,u,x,K)}if(r||p){var k;return{$$willAnimate:!0,end:function(){k?k.end():(H=!0,C(),ha(a,u),k=new c,k.complete(!0));return k},start:function(){function b(c){H=!0;C();ha(a,u);k.complete(c)}if(k)return k;k=new c;var d,e=[];r&&e.push(function(a){d=r(a)});e.length?e.push(function(a){C();a(!0)}):C();p&&e.push(function(a){d=p(a)});k.setHost({end:function(){H||((d||P)(void 0),b(void 0))},cancel:function(){H||((d||P)(!0),b(!0))}});c.chain(e,
|
||||
b);return k}}}}}]}]).provider("$$animateJsDriver",["$$animationProvider",function(a){a.drivers.push("$$animateJsDriver");this.$get=["$$animateJs","$$AnimateRunner",function(a,c){function d(c){return a(c.element,c.event,c.classes,c.options)}return function(a){if(a.from&&a.to){var b=d(a.from),n=d(a.to);if(b||n)return{start:function(){function a(){return function(){s(d,function(a){a.end()})}}var d=[];b&&d.push(b.start());n&&d.push(n.start());c.all(d,function(a){e.complete(a)});var e=new c({end:a(),cancel:a()});
|
||||
return e}}}else return d(a)}}]}])})(window,window.angular);
|
||||
//# sourceMappingURL=angular-animate.min.js.map
|
||||
1
dashboard/public/js/angular-base64.min.js
vendored
@@ -1 +0,0 @@
|
||||
!function(){"use strict";angular.module("base64",[]).constant("$base64",function(){function a(a,b){var c=f.indexOf(a.charAt(b));if(-1==c)throw"Cannot decode base64";return c}function b(b){b=""+b;var c,d,f,g=b.length;if(0==g)return b;if(0!=g%4)throw"Cannot decode base64";c=0,b.charAt(g-1)==e&&(c=1,b.charAt(g-2)==e&&(c=2),g-=4);var h=[];for(d=0;g>d;d+=4)f=a(b,d)<<18|a(b,d+1)<<12|a(b,d+2)<<6|a(b,d+3),h.push(String.fromCharCode(f>>16,255&f>>8,255&f));switch(c){case 1:f=a(b,d)<<18|a(b,d+1)<<12|a(b,d+2)<<6,h.push(String.fromCharCode(f>>16,255&f>>8));break;case 2:f=a(b,d)<<18|a(b,d+1)<<12,h.push(String.fromCharCode(f>>16))}return h.join("")}function c(a,b){var c=a.charCodeAt(b);if(c>255)throw"INVALID_CHARACTER_ERR: DOM Exception 5";return c}function d(a){if(1!=arguments.length)throw"SyntaxError: Not enough arguments";var b,d,g=[];a=""+a;var h=a.length-a.length%3;if(0==a.length)return a;for(b=0;h>b;b+=3)d=c(a,b)<<16|c(a,b+1)<<8|c(a,b+2),g.push(f.charAt(d>>18)),g.push(f.charAt(63&d>>12)),g.push(f.charAt(63&d>>6)),g.push(f.charAt(63&d));switch(a.length-h){case 1:d=c(a,b)<<16,g.push(f.charAt(d>>18)+f.charAt(63&d>>12)+e+e);break;case 2:d=c(a,b)<<16|c(a,b+1)<<8,g.push(f.charAt(d>>18)+f.charAt(63&d>>12)+f.charAt(63&d>>6)+e)}return g.join("")}var e="=",f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";return{encode:d,decode:b}}())}();
|
||||
361
dashboard/public/js/angular-bootstrap-multiselect.js
vendored
@@ -1,361 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
// -------------------------------
|
||||
// WARNING
|
||||
// -------------------------------
|
||||
// This file is taken from https://github.com/sebastianha/angular-bootstrap-multiselect
|
||||
// There are local modifications like support for translation
|
||||
// -------------------------------
|
||||
|
||||
angular.module("ui.multiselect", ["multiselect.tpl.html"])
|
||||
//from bootstrap-ui typeahead parser
|
||||
.factory("optionParser", ["$parse", function($parse) {
|
||||
// 00000111000000000000022200000000000000003333333333333330000000000044000
|
||||
var TYPEAHEAD_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;
|
||||
|
||||
return {
|
||||
parse: function(input) {
|
||||
|
||||
var match = input.match(TYPEAHEAD_REGEXP);
|
||||
if(!match) {
|
||||
throw new Error("Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_'" + " but got '" + input + "'.");
|
||||
}
|
||||
|
||||
return {
|
||||
itemName : match[3],
|
||||
source : $parse(match[4]),
|
||||
viewMapper : $parse(match[2] || match[1]),
|
||||
modelMapper: $parse(match[1])
|
||||
};
|
||||
}
|
||||
};
|
||||
}])
|
||||
.directive("multiselect", ["$parse", "$document", "$compile", "$interpolate", "$translate", "optionParser", function($parse, $document, $compile, $interpolate, $translate, optionParser) {
|
||||
return {
|
||||
restrict: "E",
|
||||
require : "ngModel",
|
||||
link : function(originalScope, element, attrs, modelCtrl) {
|
||||
|
||||
var exp = attrs.options;
|
||||
var parsedResult = optionParser.parse(exp);
|
||||
var isMultiple = attrs.multiple ? true : false;
|
||||
var compareByKey = attrs.compareBy;
|
||||
var headerKey = attrs.headerKey;
|
||||
var dividerKey = attrs.dividerKey;
|
||||
var scrollAfterRows = attrs.scrollAfterRows;
|
||||
var tabindex = attrs.tabindex;
|
||||
var maxWidth = attrs.maxWidth;
|
||||
var required = false;
|
||||
var scope = originalScope.$new();
|
||||
scope.filterAfterRows = attrs.filterAfterRows;
|
||||
var changeHandler = attrs.change || angular.noop;
|
||||
|
||||
scope.items = [];
|
||||
scope.header = "Select";
|
||||
scope.multiple = isMultiple;
|
||||
scope.disabled = false;
|
||||
|
||||
scope.ulStyle = {};
|
||||
if(scrollAfterRows !== undefined && parseInt(scrollAfterRows).toString() === scrollAfterRows) {
|
||||
scope.ulStyle = {"max-height": (scrollAfterRows*26+14)+"px", "overflow-y": "auto", "overflow-x": "hidden"};
|
||||
}
|
||||
if(tabindex !== undefined && parseInt(tabindex).toString() === tabindex) {
|
||||
scope.tabindex = tabindex;
|
||||
}
|
||||
if(maxWidth !== undefined && parseInt(maxWidth).toString() === maxWidth) {
|
||||
scope.maxWidth = {"max-width": maxWidth + "px"};
|
||||
}
|
||||
|
||||
originalScope.$on("$destroy", function() {
|
||||
scope.$destroy();
|
||||
});
|
||||
|
||||
var popUpEl = angular.element("<multiselect-popup></multiselect-popup>");
|
||||
|
||||
//required validator
|
||||
if(attrs.required || attrs.ngRequired) {
|
||||
required = true;
|
||||
}
|
||||
attrs.$observe("required", function(newVal) {
|
||||
required = newVal;
|
||||
});
|
||||
|
||||
//watch disabled state
|
||||
scope.$watch(function() {
|
||||
return $parse(attrs.ngDisabled)(originalScope);
|
||||
}, function(newVal) {
|
||||
scope.disabled = newVal;
|
||||
});
|
||||
|
||||
//watch single/multiple state for dynamically change single to multiple
|
||||
scope.$watch(function() {
|
||||
return $parse(attrs.multiple)(originalScope);
|
||||
}, function(newVal) {
|
||||
isMultiple = newVal || false;
|
||||
});
|
||||
|
||||
//watch option changes for options that are populated dynamically
|
||||
scope.$watch(function() {
|
||||
return parsedResult.source(originalScope);
|
||||
}, function(newVal) {
|
||||
if(angular.isDefined(newVal)) {
|
||||
parseModel();
|
||||
}
|
||||
}, true);
|
||||
|
||||
//watch model change
|
||||
scope.$watch(function() {
|
||||
return modelCtrl.$modelValue;
|
||||
}, function(newVal, oldVal) {
|
||||
//when directive initialize, newVal usually undefined. Also, if model value already set in the controller
|
||||
//for preselected list then we need to mark checked in our scope item. But we don't want to do this every time
|
||||
//model changes. We need to do this only if it is done outside directive scope, from controller, for example.
|
||||
if(angular.isDefined(newVal)) {
|
||||
markChecked(newVal);
|
||||
scope.$eval(changeHandler);
|
||||
}
|
||||
getHeaderText();
|
||||
modelCtrl.$setValidity("required", scope.valid());
|
||||
});
|
||||
|
||||
function parseModel() {
|
||||
scope.items.length = 0;
|
||||
var model = parsedResult.source(originalScope);
|
||||
if(!angular.isDefined(model) || model === null) {
|
||||
return;
|
||||
}
|
||||
for(var i = 0; i < model.length; i++) {
|
||||
var local = {};
|
||||
local[parsedResult.itemName] = model[i];
|
||||
|
||||
// calculate checked status of the option
|
||||
// https://github.com/sebastianha/angular-bootstrap-multiselect/pull/4/files
|
||||
var id = model[i];
|
||||
var checked = false;
|
||||
var modelValue = modelCtrl.$modelValue;
|
||||
if (modelValue) {
|
||||
if (angular.isArray(modelValue)) {
|
||||
for (var j = 0; j < modelValue.length; j++)
|
||||
if (modelValue[j] == id) {
|
||||
checked = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
checked = modelValue == id;
|
||||
}
|
||||
}
|
||||
|
||||
scope.items.push({
|
||||
label : parsedResult.viewMapper(local),
|
||||
model : model[i],
|
||||
checked: checked,
|
||||
header : model[i][headerKey],
|
||||
divider : model[i][dividerKey]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
parseModel();
|
||||
|
||||
element.append($compile(popUpEl)(scope));
|
||||
|
||||
function getHeaderText() {
|
||||
if(isEmpty(modelCtrl.$modelValue)) {
|
||||
scope.header = attrs.msHeader || $translate.instant('main.multiselect.select');
|
||||
return scope.header;
|
||||
}
|
||||
|
||||
if(isMultiple) {
|
||||
if(attrs.msSelected) {
|
||||
scope.header = $interpolate(attrs.msSelected)(scope);
|
||||
} else {
|
||||
scope.header = $translate.instant('main.multiselect.selected', { n: modelCtrl.$modelValue.length });
|
||||
}
|
||||
} else {
|
||||
var local = {};
|
||||
local[parsedResult.itemName] = modelCtrl.$modelValue;
|
||||
scope.header = parsedResult.viewMapper(local);
|
||||
}
|
||||
}
|
||||
|
||||
function isEmpty(obj) {
|
||||
if(obj === true || obj === false) {
|
||||
return false;
|
||||
}
|
||||
if(!obj) {
|
||||
return true;
|
||||
}
|
||||
if(obj.length && obj.length > 0) {
|
||||
return false;
|
||||
}
|
||||
for(var prop in obj) {
|
||||
if(obj[prop]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(compareByKey !== undefined && obj[compareByKey] !== undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
scope.valid = function validModel() {
|
||||
if(!required) {
|
||||
return true;
|
||||
}
|
||||
var value = modelCtrl.$modelValue;
|
||||
return (angular.isArray(value) && value.length > 0) || (!angular.isArray(value) && value !== null);
|
||||
};
|
||||
|
||||
function selectSingle(item) {
|
||||
if(!item.checked) {
|
||||
scope.uncheckAll();
|
||||
item.checked = !item.checked;
|
||||
}
|
||||
setModelValue(false);
|
||||
}
|
||||
|
||||
function selectMultiple(item) {
|
||||
item.checked = !item.checked;
|
||||
setModelValue(true);
|
||||
}
|
||||
|
||||
function setModelValue(isMultiple) {
|
||||
var value;
|
||||
|
||||
if(isMultiple) {
|
||||
value = [];
|
||||
angular.forEach(scope.items, function(item) {
|
||||
if(item.checked) {
|
||||
value.push(item.model);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
angular.forEach(scope.items, function(item) {
|
||||
if(item.checked) {
|
||||
value = item.model;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
modelCtrl.$setViewValue(value);
|
||||
}
|
||||
|
||||
function markChecked(newVal) {
|
||||
if(!angular.isArray(newVal)) {
|
||||
angular.forEach(scope.items, function(item) {
|
||||
item.checked = false;
|
||||
if(compareByKey === undefined && angular.equals(item.model, newVal)) {
|
||||
item.checked = true;
|
||||
} else if(compareByKey !== undefined && newVal !== null && item.model[compareByKey] !== undefined && angular.equals(item.model[compareByKey], newVal[compareByKey])) {
|
||||
item.checked = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
angular.forEach(scope.items, function(item) {
|
||||
item.checked = false;
|
||||
angular.forEach(newVal, function(i) {
|
||||
if(compareByKey === undefined && angular.equals(item.model, i)) {
|
||||
item.checked = true;
|
||||
} else if(compareByKey !== undefined && item.model[compareByKey] !== undefined && angular.equals(item.model[compareByKey], i[compareByKey])) {
|
||||
item.checked = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
scope.checkAll = function() {
|
||||
if(!isMultiple) {
|
||||
return;
|
||||
}
|
||||
angular.forEach(scope.items, function(item) {
|
||||
item.checked = true;
|
||||
});
|
||||
setModelValue(true);
|
||||
};
|
||||
|
||||
scope.uncheckAll = function() {
|
||||
angular.forEach(scope.items, function(item) {
|
||||
item.checked = false;
|
||||
});
|
||||
setModelValue(true);
|
||||
};
|
||||
|
||||
scope.select = function(event, item) {
|
||||
if(isMultiple === false) {
|
||||
selectSingle(item);
|
||||
scope.toggleSelect();
|
||||
} else {
|
||||
event.stopPropagation();
|
||||
selectMultiple(item);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}])
|
||||
.directive("multiselectPopup", ["$document", function($document) {
|
||||
return {
|
||||
restrict : "E",
|
||||
scope : false,
|
||||
replace : true,
|
||||
templateUrl: "multiselect.tpl.html",
|
||||
link : function(scope, element, attrs) {
|
||||
|
||||
scope.isVisible = false;
|
||||
|
||||
scope.toggleSelect = function() {
|
||||
if(element.hasClass("open")) {
|
||||
scope.filter = "";
|
||||
element.removeClass("open");
|
||||
$document.unbind("click", clickHandler);
|
||||
} else {
|
||||
scope.filter = "";
|
||||
element.addClass("open");
|
||||
$document.bind("click", clickHandler);
|
||||
}
|
||||
};
|
||||
|
||||
// $("ul.dropdown-menu").on("click", "[data-stopPropagation]", function(e) {
|
||||
// e.stopPropagation();
|
||||
// });
|
||||
|
||||
function clickHandler(event) {
|
||||
if(elementMatchesAnyInArray(event.target, element.find(event.target.tagName))) {
|
||||
return;
|
||||
}
|
||||
element.removeClass("open");
|
||||
$document.unbind("click", clickHandler);
|
||||
scope.$apply();
|
||||
}
|
||||
|
||||
var elementMatchesAnyInArray = function(element, elementArray) {
|
||||
for(var i = 0; i < elementArray.length; i++) {
|
||||
if(element === elementArray[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
angular.module("multiselect.tpl.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("multiselect.tpl.html",
|
||||
"<div class=\"btn-group\">\n" +
|
||||
" <button tabindex=\"{{tabindex}}\" title=\"{{header}}\" type=\"button\" class=\"btn btn-default dropdown-toggle\" ng-click=\"toggleSelect()\" ng-disabled=\"disabled\" ng-class=\"{'error': !valid()}\">\n" +
|
||||
" <div ng-style=\"maxWidth\" style=\"padding-right: 13px; overflow: hidden; text-overflow: ellipsis;\">{{header}}</div><span class=\"caret\" style=\"position:absolute;right:10px;top:14px;\"></span>\n" +
|
||||
" </button>\n" +
|
||||
" <ul class=\"dropdown-menu\" style=\"margin-bottom:30px;padding-left:5px;padding-right:5px;\" ng-style=\"ulStyle\">\n" +
|
||||
" <input ng-show=\"items.length > filterAfterRows\" ng-model=\"filter\" style=\"padding: 0px 3px; margin-bottom: 4px;\" placeholder=\"{{ 'main.multiselect.filterPlaceholder' | tr }}\">" +
|
||||
" <li data-stopPropagation=\"true\" ng-repeat=\"i in items | filter:filter\" ng-class=\"{'dropdown-header': i.header, 'divider': i.divider}\">\n" +
|
||||
" <a ng-if=\"!i.header && !i.divider\" ng-click=\"select($event, i)\" style=\"padding:3px 10px;cursor:pointer;\">\n" +
|
||||
" <i class=\"fa\" ng-class=\"{'fa-check': i.checked, 'empty': !i.checked}\"></i> {{i.label}}" +
|
||||
" </a>\n" +
|
||||
" <span ng-if=\"i.header\">{{i.label}}</span>" +
|
||||
" </li>\n" +
|
||||
" </ul>\n" +
|
||||
"</div>");
|
||||
}]);
|
||||
9
dashboard/public/js/angular-cookies.min.js
vendored
@@ -1,9 +0,0 @@
|
||||
/*
|
||||
AngularJS v1.5.8
|
||||
(c) 2010-2016 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(n,c){'use strict';function l(b,a,g){var d=g.baseHref(),k=b[0];return function(b,e,f){var g,h;f=f||{};h=f.expires;g=c.isDefined(f.path)?f.path:d;c.isUndefined(e)&&(h="Thu, 01 Jan 1970 00:00:00 GMT",e="");c.isString(h)&&(h=new Date(h));e=encodeURIComponent(b)+"="+encodeURIComponent(e);e=e+(g?";path="+g:"")+(f.domain?";domain="+f.domain:"");e+=h?";expires="+h.toUTCString():"";e+=f.secure?";secure":"";f=e.length+1;4096<f&&a.warn("Cookie '"+b+"' possibly not set or overflowed because it was too large ("+
|
||||
f+" > 4096 bytes)!");k.cookie=e}}c.module("ngCookies",["ng"]).provider("$cookies",[function(){var b=this.defaults={};this.$get=["$$cookieReader","$$cookieWriter",function(a,g){return{get:function(d){return a()[d]},getObject:function(d){return(d=this.get(d))?c.fromJson(d):d},getAll:function(){return a()},put:function(d,a,m){g(d,a,m?c.extend({},b,m):b)},putObject:function(d,b,a){this.put(d,c.toJson(b),a)},remove:function(a,k){g(a,void 0,k?c.extend({},b,k):b)}}}]}]);c.module("ngCookies").factory("$cookieStore",
|
||||
["$cookies",function(b){return{get:function(a){return b.getObject(a)},put:function(a,c){b.putObject(a,c)},remove:function(a){b.remove(a)}}}]);l.$inject=["$document","$log","$browser"];c.module("ngCookies").provider("$$cookieWriter",function(){this.$get=l})})(window,window.angular);
|
||||
//# sourceMappingURL=angular-cookies.min.js.map
|
||||
1
dashboard/public/js/angular-fittext.min.js
vendored
@@ -1 +0,0 @@
|
||||
!function(t,e,i,n){"use strict";i.module("ngFitText",[]).value("fitTextDefaultConfig",{debounce:!1,delay:250,loadDelay:10,compressor:1,min:0,max:Number.POSITIVE_INFINITY}).directive("fittext",["$timeout","fitTextDefaultConfig","fitTextConfig",function(e,n,o){return{restrict:"A",scope:!0,link:function(f,a,l){function r(){var t=T*h/s.offsetWidth/h;return Math.max(Math.min((c[0].offsetWidth-6)*t*p,parseFloat(y)),parseFloat(m))}function u(){s.offsetHeight*s.offsetWidth!==0&&(d.fontSize=T+"px",d.lineHeight="1",d.display="inline-block",d.fontSize=r()+"px",d.lineHeight=b,d.display=v)}i.extend(n,o.config);var c=a.parent(),s=a[0],d=s.style,x=t.getComputedStyle(a[0],null),h=a.children().length||1,g=l.fittextLoadDelay||n.loadDelay,p=l.fittext||n.compressor,m=("inherit"===l.fittextMin?x["font-size"]:l.fittextMin)||n.min,y=("inherit"===l.fittextMax?x["font-size"]:l.fittextMax)||n.max,b=x["line-height"],v=x.display,T=10;e(function(){u()},g),f.$watch(l.ngBind,function(){u()}),n.debounce?i.element(t).bind("resize",n.debounce(function(){f.$apply(u)},n.delay)):i.element(t).bind("resize",function(){f.$apply(u)})}}}]).provider("fitTextConfig",function(){var t=this;return this.config={},this.$get=function(){var e={};return e.config=t.config,e},this})}(window,document,angular);
|
||||
10
dashboard/public/js/angular-loader.min.js
vendored
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
AngularJS v1.5.8
|
||||
(c) 2010-2016 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(){'use strict';function d(b){return function(){var a=arguments[0],e;e="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.5.8/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){e=e+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,c;c=arguments[a];c="function"==typeof c?c.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof c?"undefined":"string"!=typeof c?JSON.stringify(c):c;e+=d(c)}return Error(e)}}(function(b){function a(c,a,b){return c[a]||(c[a]=b())}var e=d("$injector"),n=d("ng");
|
||||
b=a(b,"angular",Object);b.$$minErr=b.$$minErr||d;return a(b,"module",function(){var c={};return function(b,d,h){if("hasOwnProperty"===b)throw n("badname","module");d&&c.hasOwnProperty(b)&&(c[b]=null);return a(c,b,function(){function c(a,b,d,e){e||(e=f);return function(){e[d||"push"]([a,b,arguments]);return g}}function a(c,e){return function(a,d){d&&"function"===typeof d&&(d.$$moduleName=b);f.push([c,e,arguments]);return g}}if(!d)throw e("nomod",b);var f=[],k=[],l=[],m=c("$injector","invoke","push",
|
||||
k),g={_invokeQueue:f,_configBlocks:k,_runBlocks:l,requires:d,name:b,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:c("$provide","value"),constant:c("$provide","constant","unshift"),decorator:a("$provide","decorator"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),component:a("$compileProvider","component"),config:m,run:function(a){l.push(a);
|
||||
return this}};h&&m(h);return g})}})})(window)})(window);
|
||||
//# sourceMappingURL=angular-loader.min.js.map
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"version":3,
|
||||
"file":"angular-loader.min.js",
|
||||
"lineCount":9,
|
||||
"mappings":"A;;;;;aAMC,SAAQ,EAAG,CA6DZA,QAAAA,EAAAA,CAAAA,CAAAA,CAAAA,CAAAA,MAAAA,SAAAA,EAAAA,CAAAA,IAAAA,EAAAA,SAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,EAAAA,CAAAA,GAAAA,EAAAA,CAAAA,CAAAA,CAAAA,CAAAA,GAAAA,CAAAA,EAAAA,EAAAA,CAAAA,CAAAA,sCAAAA,EAAAA,CAAAA,CAAAA,CAAAA,CAAAA,GAAAA,CAAAA,EAAAA,EAAAA,CAAAA,KAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,SAAAA,OAAAA,CAAAA,CAAAA,EAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,EAAAA,CAAAA,EAAAA,CAAAA,CAAAA,GAAAA,CAAAA,GAAAA,EAAAA,GAAAA,EAAAA,CAAAA,CAAAA,CAAAA,EAAAA,GAAAA,KAAAA,EAAAA,kBAAAA,CAAAA,CAAAA,EAAAA,CAAAA,SAAAA,CAAAA,CAAAA,CAAAA,EAAAA,CAAAA,UAAAA,EAAAA,MAAAA,EAAAA,CAAAA,CAAAA,SAAAA,EAAAA,QAAAA,CAAAA,aAAAA,CAAAA,EAAAA,CAAAA,CAAAA,WAAAA,EAAAA,MAAAA,EAAAA,CAAAA,WAAAA,CAAAA,QAAAA,EAAAA,MAAAA,EAAAA,CAAAA,IAAAA,UAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,EAAAA,EAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,MAAAA,MAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CA2CAC,SAA0B,CAACC,CAAD,CAAS,CAKjCC,QAASA,EAAM,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAqB,CAClC,MAAOF,EAAA,CAAIC,CAAJ,CAAP,GAAqBD,CAAA,CAAIC,CAAJ,CAArB,CAAiCC,CAAA,EAAjC,CADkC,CAHpC,IAAIC,EAAkBP,CAAA,CAAO,WAAP,CAAtB,CACIQ,EAAWR,CAAA,CAAO,IAAP,CAMXS;CAAAA,CAAUN,CAAA,CAAOD,CAAP,CAAe,SAAf,CAA0BQ,MAA1B,CAGdD,EAAAE,SAAA,CAAmBF,CAAAE,SAAnB,EAAuCX,CAEvC,OAAOG,EAAA,CAAOM,CAAP,CAAgB,QAAhB,CAA0B,QAAQ,EAAG,CAE1C,IAAIG,EAAU,EAqDd,OAAOC,SAAe,CAACR,CAAD,CAAOS,CAAP,CAAiBC,CAAjB,CAA2B,CAE7C,GAAa,gBAAb,GAKsBV,CALtB,CACE,KAAMG,EAAA,CAAS,SAAT,CAIoBQ,QAJpB,CAAN,CAKAF,CAAJ,EAAgBF,CAAAK,eAAA,CAAuBZ,CAAvB,CAAhB,GACEO,CAAA,CAAQP,CAAR,CADF,CACkB,IADlB,CAGA,OAAOF,EAAA,CAAOS,CAAP,CAAgBP,CAAhB,CAAsB,QAAQ,EAAG,CAuPtCa,QAASA,EAAW,CAACC,CAAD,CAAWC,CAAX,CAAmBC,CAAnB,CAAiCC,CAAjC,CAAwC,CACrDA,CAAL,GAAYA,CAAZ,CAAoBC,CAApB,CACA,OAAO,SAAQ,EAAG,CAChBD,CAAA,CAAMD,CAAN,EAAsB,MAAtB,CAAA,CAA8B,CAACF,CAAD,CAAWC,CAAX,CAAmBI,SAAnB,CAA9B,CACA,OAAOC,EAFS,CAFwC,CAa5DC,QAASA,EAA2B,CAACP,CAAD,CAAWC,CAAX,CAAmB,CACrD,MAAO,SAAQ,CAACO,CAAD,CAAaC,CAAb,CAA8B,CACvCA,CAAJ,EA7b4C,UA6b5C,GA7b2B,MA6bOA,EAAlC,GAAoDA,CAAAC,aAApD,CAAmFxB,CAAnF,CACAkB,EAAAO,KAAA,CAAiB,CAACX,CAAD,CAAWC,CAAX,CAAmBI,SAAnB,CAAjB,CACA,OAAOC,EAHoC,CADQ,CAnQvD,GAAKX,CAAAA,CAAL,CACE,KAAMP,EAAA,CAAgB,OAAhB,CAEiDF,CAFjD,CAAN,CAMF,IAAIkB,EAAc,EAAlB,CAGIQ,EAAe,EAHnB,CAMIC,EAAY,EANhB,CAQIC,EAASf,CAAA,CAAY,WAAZ,CAAyB,QAAzB,CAAmC,MAAnC;AAA2Ca,CAA3C,CARb,CAWIN,EAAiB,CAEnBS,aAAcX,CAFK,CAGnBY,cAAeJ,CAHI,CAInBK,WAAYJ,CAJO,CAenBlB,SAAUA,CAfS,CAyBnBT,KAAMA,CAzBa,CAsCnBc,SAAUO,CAAA,CAA4B,UAA5B,CAAwC,UAAxC,CAtCS,CAiDnBpB,QAASoB,CAAA,CAA4B,UAA5B,CAAwC,SAAxC,CAjDU,CA4DnBW,QAASX,CAAA,CAA4B,UAA5B,CAAwC,SAAxC,CA5DU,CAuEnBY,MAAOpB,CAAA,CAAY,UAAZ,CAAwB,OAAxB,CAvEY,CAmFnBqB,SAAUrB,CAAA,CAAY,UAAZ,CAAwB,UAAxB,CAAoC,SAApC,CAnFS,CA+FnBsB,UAAWd,CAAA,CAA4B,UAA5B,CAAwC,WAAxC,CA/FQ,CAiInBe,UAAWf,CAAA,CAA4B,kBAA5B,CAAgD,UAAhD,CAjIQ,CAmJnBgB,OAAQhB,CAAA,CAA4B,iBAA5B,CAA+C,UAA/C,CAnJW,CA+JnBiB,WAAYjB,CAAA,CAA4B,qBAA5B,CAAmD,UAAnD,CA/JO,CA4KnBkB,UAAWlB,CAAA,CAA4B,kBAA5B,CAAgD,WAAhD,CA5KQ,CAyLnBmB,UAAWnB,CAAA,CAA4B,kBAA5B,CAAgD,WAAhD,CAzLQ,CAsMnBO,OAAQA,CAtMW,CAkNnBa,IAAKA,QAAQ,CAACC,CAAD,CAAQ,CACnBf,CAAAF,KAAA,CAAeiB,CAAf,CACA;MAAO,KAFY,CAlNF,CAwNjBhC,EAAJ,EACEkB,CAAA,CAAOlB,CAAP,CAGF,OAAOU,EA/O+B,CAAjC,CAXwC,CAvDP,CAArC,CAd0B,CAAnCxB,CAiWA,CAAkBC,MAAlB,CAzcY,CAAX,CAAD,CA0cGA,MA1cH;",
|
||||
"sources":["angular-loader.js"],
|
||||
"names":["minErr","setupModuleLoader","window","ensure","obj","name","factory","$injectorMinErr","ngMinErr","angular","Object","$$minErr","modules","module","requires","configFn","context","hasOwnProperty","invokeLater","provider","method","insertMethod","queue","invokeQueue","arguments","moduleInstance","invokeLaterAndSetModuleName","recipeName","factoryFunction","$$moduleName","push","configBlocks","runBlocks","config","_invokeQueue","_configBlocks","_runBlocks","service","value","constant","decorator","animation","filter","controller","directive","component","run","block"]
|
||||
}
|
||||
7
dashboard/public/js/angular-md5.min.js
vendored
@@ -1,7 +0,0 @@
|
||||
/*
|
||||
angular-md5 - v0.1.7
|
||||
2014-01-20
|
||||
*/
|
||||
|
||||
!function(a,b){b.module("angular-md5",["gdi2290.md5"]),b.module("ngMd5",["gdi2290.md5"]),b.module("gdi2290.md5",["gdi2290.gravatar-filter","gdi2290.md5-service","gdi2290.md5-filter"]),b.module("gdi2290.gravatar-filter",[]).filter("gravatar",["md5",function(a){var b={};return function(c,d){return b[c]||(d=d?a.createHash(d.toString().toLowerCase()):"",b[c]=c?a.createHash(c.toString().toLowerCase()):d),b[c]}}]),b.module("gdi2290.md5-filter",[]).filter("md5",["md5",function(a){return function(b){return b?a.createHash(b.toString().toLowerCase()):b}}]),b.module("gdi2290.md5-service",[]).factory("md5",[function(){var a={createHash:function(a){var b,c,d,e,f,g,h,i,j,k,l=function(a,b){return a<<b|a>>>32-b},m=function(a,b){var c,d,e,f,g;return e=2147483648&a,f=2147483648&b,c=1073741824&a,d=1073741824&b,g=(1073741823&a)+(1073741823&b),c&d?2147483648^g^e^f:c|d?1073741824&g?3221225472^g^e^f:1073741824^g^e^f:g^e^f},n=function(a,b,c){return a&b|~a&c},o=function(a,b,c){return a&c|b&~c},p=function(a,b,c){return a^b^c},q=function(a,b,c){return b^(a|~c)},r=function(a,b,c,d,e,f,g){return a=m(a,m(m(n(b,c,d),e),g)),m(l(a,f),b)},s=function(a,b,c,d,e,f,g){return a=m(a,m(m(o(b,c,d),e),g)),m(l(a,f),b)},t=function(a,b,c,d,e,f,g){return a=m(a,m(m(p(b,c,d),e),g)),m(l(a,f),b)},u=function(a,b,c,d,e,f,g){return a=m(a,m(m(q(b,c,d),e),g)),m(l(a,f),b)},v=function(a){for(var b,c=a.length,d=c+8,e=(d-d%64)/64,f=16*(e+1),g=new Array(f-1),h=0,i=0;c>i;)b=(i-i%4)/4,h=i%4*8,g[b]=g[b]|a.charCodeAt(i)<<h,i++;return b=(i-i%4)/4,h=i%4*8,g[b]=g[b]|128<<h,g[f-2]=c<<3,g[f-1]=c>>>29,g},w=function(a){var b,c,d="",e="";for(c=0;3>=c;c++)b=a>>>8*c&255,e="0"+b.toString(16),d+=e.substr(e.length-2,2);return d},x=[],y=7,z=12,A=17,B=22,C=5,D=9,E=14,F=20,G=4,H=11,I=16,J=23,K=6,L=10,M=15,N=21;for(x=v(a),h=1732584193,i=4023233417,j=2562383102,k=271733878,b=x.length,c=0;b>c;c+=16)d=h,e=i,f=j,g=k,h=r(h,i,j,k,x[c+0],y,3614090360),k=r(k,h,i,j,x[c+1],z,3905402710),j=r(j,k,h,i,x[c+2],A,606105819),i=r(i,j,k,h,x[c+3],B,3250441966),h=r(h,i,j,k,x[c+4],y,4118548399),k=r(k,h,i,j,x[c+5],z,1200080426),j=r(j,k,h,i,x[c+6],A,2821735955),i=r(i,j,k,h,x[c+7],B,4249261313),h=r(h,i,j,k,x[c+8],y,1770035416),k=r(k,h,i,j,x[c+9],z,2336552879),j=r(j,k,h,i,x[c+10],A,4294925233),i=r(i,j,k,h,x[c+11],B,2304563134),h=r(h,i,j,k,x[c+12],y,1804603682),k=r(k,h,i,j,x[c+13],z,4254626195),j=r(j,k,h,i,x[c+14],A,2792965006),i=r(i,j,k,h,x[c+15],B,1236535329),h=s(h,i,j,k,x[c+1],C,4129170786),k=s(k,h,i,j,x[c+6],D,3225465664),j=s(j,k,h,i,x[c+11],E,643717713),i=s(i,j,k,h,x[c+0],F,3921069994),h=s(h,i,j,k,x[c+5],C,3593408605),k=s(k,h,i,j,x[c+10],D,38016083),j=s(j,k,h,i,x[c+15],E,3634488961),i=s(i,j,k,h,x[c+4],F,3889429448),h=s(h,i,j,k,x[c+9],C,568446438),k=s(k,h,i,j,x[c+14],D,3275163606),j=s(j,k,h,i,x[c+3],E,4107603335),i=s(i,j,k,h,x[c+8],F,1163531501),h=s(h,i,j,k,x[c+13],C,2850285829),k=s(k,h,i,j,x[c+2],D,4243563512),j=s(j,k,h,i,x[c+7],E,1735328473),i=s(i,j,k,h,x[c+12],F,2368359562),h=t(h,i,j,k,x[c+5],G,4294588738),k=t(k,h,i,j,x[c+8],H,2272392833),j=t(j,k,h,i,x[c+11],I,1839030562),i=t(i,j,k,h,x[c+14],J,4259657740),h=t(h,i,j,k,x[c+1],G,2763975236),k=t(k,h,i,j,x[c+4],H,1272893353),j=t(j,k,h,i,x[c+7],I,4139469664),i=t(i,j,k,h,x[c+10],J,3200236656),h=t(h,i,j,k,x[c+13],G,681279174),k=t(k,h,i,j,x[c+0],H,3936430074),j=t(j,k,h,i,x[c+3],I,3572445317),i=t(i,j,k,h,x[c+6],J,76029189),h=t(h,i,j,k,x[c+9],G,3654602809),k=t(k,h,i,j,x[c+12],H,3873151461),j=t(j,k,h,i,x[c+15],I,530742520),i=t(i,j,k,h,x[c+2],J,3299628645),h=u(h,i,j,k,x[c+0],K,4096336452),k=u(k,h,i,j,x[c+7],L,1126891415),j=u(j,k,h,i,x[c+14],M,2878612391),i=u(i,j,k,h,x[c+5],N,4237533241),h=u(h,i,j,k,x[c+12],K,1700485571),k=u(k,h,i,j,x[c+3],L,2399980690),j=u(j,k,h,i,x[c+10],M,4293915773),i=u(i,j,k,h,x[c+1],N,2240044497),h=u(h,i,j,k,x[c+8],K,1873313359),k=u(k,h,i,j,x[c+15],L,4264355552),j=u(j,k,h,i,x[c+6],M,2734768916),i=u(i,j,k,h,x[c+13],N,1309151649),h=u(h,i,j,k,x[c+4],K,4149444226),k=u(k,h,i,j,x[c+11],L,3174756917),j=u(j,k,h,i,x[c+2],M,718787259),i=u(i,j,k,h,x[c+9],N,3951481745),h=m(h,d),i=m(i,e),j=m(j,f),k=m(k,g);var O=w(h)+w(i)+w(j)+w(k);return O.toLowerCase()}};return a}])}(this,this.angular,void 0);
|
||||
//# sourceMappingURL=angular-md5.min.js.map
|
||||
16
dashboard/public/js/angular-route.min.js
vendored
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
AngularJS v1.5.8
|
||||
(c) 2010-2016 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(E,d){'use strict';function y(t,l,g){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(b,e,a,c,k){function p(){m&&(g.cancel(m),m=null);h&&(h.$destroy(),h=null);n&&(m=g.leave(n),m.then(function(){m=null}),n=null)}function B(){var a=t.current&&t.current.locals;if(d.isDefined(a&&a.$template)){var a=b.$new(),c=t.current;n=k(a,function(a){g.enter(a,null,n||e).then(function(){!d.isDefined(A)||A&&!b.$eval(A)||l()});p()});h=c.scope=a;h.$emit("$viewContentLoaded");
|
||||
h.$eval(s)}else p()}var h,n,m,A=a.autoscroll,s=a.onload||"";b.$on("$routeChangeSuccess",B);B()}}}function w(d,l,g){return{restrict:"ECA",priority:-400,link:function(b,e){var a=g.current,c=a.locals;e.html(c.$template);var k=d(e.contents());if(a.controller){c.$scope=b;var p=l(a.controller,c);a.controllerAs&&(b[a.controllerAs]=p);e.data("$ngControllerController",p);e.children().data("$ngControllerController",p)}b[a.resolveAs||"$resolve"]=c;k(b)}}}var x,C,s=d.module("ngRoute",["ng"]).provider("$route",
|
||||
function(){function t(b,e){return d.extend(Object.create(b),e)}function l(b,d){var a=d.caseInsensitiveMatch,c={originalPath:b,regexp:b},g=c.keys=[];b=b.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)(\*\?|[\?\*])?/g,function(b,a,d,c){b="?"===c||"*?"===c?"?":null;c="*"===c||"*?"===c?"*":null;g.push({name:d,optional:!!b});a=a||"";return""+(b?"":a)+"(?:"+(b?a:"")+(c&&"(.+?)"||"([^/]+)")+(b||"")+")"+(b||"")}).replace(/([\/$\*])/g,"\\$1");c.regexp=new RegExp("^"+b+"$",a?"i":"");return c}x=d.isArray;C=
|
||||
d.isObject;var g={};this.when=function(b,e){var a;a=void 0;if(x(e)){a=a||[];for(var c=0,k=e.length;c<k;c++)a[c]=e[c]}else if(C(e))for(c in a=a||{},e)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=e[c];a=a||e;d.isUndefined(a.reloadOnSearch)&&(a.reloadOnSearch=!0);d.isUndefined(a.caseInsensitiveMatch)&&(a.caseInsensitiveMatch=this.caseInsensitiveMatch);g[b]=d.extend(a,b&&l(b,a));b&&(c="/"==b[b.length-1]?b.substr(0,b.length-1):b+"/",g[c]=d.extend({redirectTo:b},l(c,a)));return this};this.caseInsensitiveMatch=
|
||||
!1;this.otherwise=function(b){"string"===typeof b&&(b={redirectTo:b});this.when(null,b);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce",function(b,e,a,c,k,p,l){function h(a){var f=v.current;(x=(r=y())&&f&&r.$$route===f.$$route&&d.equals(r.pathParams,f.pathParams)&&!r.reloadOnSearch&&!z)||!f&&!r||b.$broadcast("$routeChangeStart",r,f).defaultPrevented&&a&&a.preventDefault()}function n(){var u=v.current,f=r;if(x)u.params=f.params,d.copy(u.params,
|
||||
a),b.$broadcast("$routeUpdate",u);else if(f||u)z=!1,(v.current=f)&&f.redirectTo&&(d.isString(f.redirectTo)?e.path(w(f.redirectTo,f.params)).search(f.params).replace():e.url(f.redirectTo(f.pathParams,e.path(),e.search())).replace()),c.when(f).then(m).then(function(c){f==v.current&&(f&&(f.locals=c,d.copy(f.params,a)),b.$broadcast("$routeChangeSuccess",f,u))},function(a){f==v.current&&b.$broadcast("$routeChangeError",f,u,a)})}function m(a){if(a){var b=d.extend({},a.resolve);d.forEach(b,function(a,c){b[c]=
|
||||
d.isString(a)?k.get(a):k.invoke(a,null,null,c)});a=s(a);d.isDefined(a)&&(b.$template=a);return c.all(b)}}function s(a){var b,c;d.isDefined(b=a.template)?d.isFunction(b)&&(b=b(a.params)):d.isDefined(c=a.templateUrl)&&(d.isFunction(c)&&(c=c(a.params)),d.isDefined(c)&&(a.loadedTemplateUrl=l.valueOf(c),b=p(c)));return b}function y(){var a,b;d.forEach(g,function(c,g){var q;if(q=!b){var h=e.path();q=c.keys;var l={};if(c.regexp)if(h=c.regexp.exec(h)){for(var k=1,p=h.length;k<p;++k){var m=q[k-1],n=h[k];m&&
|
||||
n&&(l[m.name]=n)}q=l}else q=null;else q=null;q=a=q}q&&(b=t(c,{params:d.extend({},e.search(),a),pathParams:a}),b.$$route=c)});return b||g[null]&&t(g[null],{params:{},pathParams:{}})}function w(a,b){var c=[];d.forEach((a||"").split(":"),function(a,d){if(0===d)c.push(a);else{var e=a.match(/(\w+)(?:[?*])?(.*)/),g=e[1];c.push(b[g]);c.push(e[2]||"");delete b[g]}});return c.join("")}var z=!1,r,x,v={routes:g,reload:function(){z=!0;var a={defaultPrevented:!1,preventDefault:function(){this.defaultPrevented=
|
||||
!0;z=!1}};b.$evalAsync(function(){h(a);a.defaultPrevented||n()})},updateParams:function(a){if(this.current&&this.current.$$route)a=d.extend({},this.current.params,a),e.path(w(this.current.$$route.originalPath,a)),e.search(a);else throw D("norout");}};b.$on("$locationChangeStart",h);b.$on("$locationChangeSuccess",n);return v}]}),D=d.$$minErr("ngRoute");s.provider("$routeParams",function(){this.$get=function(){return{}}});s.directive("ngView",y);s.directive("ngView",w);y.$inject=["$route","$anchorScroll",
|
||||
"$animate"];w.$inject=["$compile","$controller","$route"]})(window,window.angular);
|
||||
//# sourceMappingURL=angular-route.min.js.map
|
||||
16
dashboard/public/js/angular-sanitize.min.js
vendored
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
AngularJS v1.5.8
|
||||
(c) 2010-2016 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(s,g){'use strict';function H(g){var l=[];t(l,A).chars(g);return l.join("")}var B=g.$$minErr("$sanitize"),C,l,D,E,q,A,F,t;g.module("ngSanitize",[]).provider("$sanitize",function(){function k(a,e){var b={},c=a.split(","),h;for(h=0;h<c.length;h++)b[e?q(c[h]):c[h]]=!0;return b}function I(a){for(var e={},b=0,c=a.length;b<c;b++){var h=a[b];e[h.name]=h.value}return e}function G(a){return a.replace(/&/g,"&").replace(J,function(a){var b=a.charCodeAt(0);a=a.charCodeAt(1);return"&#"+(1024*(b-55296)+
|
||||
(a-56320)+65536)+";"}).replace(K,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"<").replace(/>/g,">")}function u(a){if(a.nodeType===s.Node.ELEMENT_NODE)for(var e=a.attributes,b=0,c=e.length;b<c;b++){var h=e[b],d=h.name.toLowerCase();if("xmlns:ns1"===d||0===d.lastIndexOf("ns1:",0))a.removeAttributeNode(h),b--,c--}(e=a.firstChild)&&u(e);(e=a.nextSibling)&&u(e)}var v=!1;this.$get=["$$sanitizeUri",function(a){v&&l(w,x);return function(e){var b=[];F(e,t(b,function(b,h){return!/^unsafe:/.test(a(b,
|
||||
h))}));return b.join("")}}];this.enableSvg=function(a){return E(a)?(v=a,this):v};C=g.bind;l=g.extend;D=g.forEach;E=g.isDefined;q=g.lowercase;A=g.noop;F=function(a,e){null===a||void 0===a?a="":"string"!==typeof a&&(a=""+a);f.innerHTML=a;var b=5;do{if(0===b)throw B("uinput");b--;s.document.documentMode&&u(f);a=f.innerHTML;f.innerHTML=a}while(a!==f.innerHTML);for(b=f.firstChild;b;){switch(b.nodeType){case 1:e.start(b.nodeName.toLowerCase(),I(b.attributes));break;case 3:e.chars(b.textContent)}var c;if(!(c=
|
||||
b.firstChild)&&(1==b.nodeType&&e.end(b.nodeName.toLowerCase()),c=b.nextSibling,!c))for(;null==c;){b=b.parentNode;if(b===f)break;c=b.nextSibling;1==b.nodeType&&e.end(b.nodeName.toLowerCase())}b=c}for(;b=f.firstChild;)f.removeChild(b)};t=function(a,e){var b=!1,c=C(a,a.push);return{start:function(a,d){a=q(a);!b&&z[a]&&(b=a);b||!0!==w[a]||(c("<"),c(a),D(d,function(b,d){var f=q(d),g="img"===a&&"src"===f||"background"===f;!0!==m[f]||!0===n[f]&&!e(b,g)||(c(" "),c(d),c('="'),c(G(b)),c('"'))}),c(">"))},end:function(a){a=
|
||||
q(a);b||!0!==w[a]||!0===y[a]||(c("</"),c(a),c(">"));a==b&&(b=!1)},chars:function(a){b||c(G(a))}}};var J=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,K=/([^\#-~ |!])/g,y=k("area,br,col,hr,img,wbr"),d=k("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),r=k("rp,rt"),p=l({},r,d),d=l({},d,k("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul")),r=l({},r,k("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),
|
||||
x=k("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,stop,svg,switch,text,title,tspan"),z=k("script,style"),w=l({},y,d,r,p),n=k("background,cite,href,longdesc,src,xlink:href"),p=k("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,valign,value,vspace,width"),
|
||||
r=k("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan",
|
||||
!0),m=l({},n,r,p),f;(function(a){if(a.document&&a.document.implementation)a=a.document.implementation.createHTMLDocument("inert");else throw B("noinert");var e=(a.documentElement||a.getDocumentElement()).getElementsByTagName("body");1===e.length?f=e[0]:(e=a.createElement("html"),f=a.createElement("body"),e.appendChild(f),a.appendChild(e))})(s)});g.module("ngSanitize").filter("linky",["$sanitize",function(k){var l=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
|
||||
q=/^mailto:/i,u=g.$$minErr("linky"),v=g.isDefined,s=g.isFunction,t=g.isObject,y=g.isString;return function(d,g,p){function x(a){a&&m.push(H(a))}function z(a,b){var c,d=w(a);m.push("<a ");for(c in d)m.push(c+'="'+d[c]+'" ');!v(g)||"target"in d||m.push('target="',g,'" ');m.push('href="',a.replace(/"/g,"""),'">');x(b);m.push("</a>")}if(null==d||""===d)return d;if(!y(d))throw u("notstring",d);for(var w=s(p)?p:t(p)?function(){return p}:function(){return{}},n=d,m=[],f,a;d=n.match(l);)f=d[0],d[2]||
|
||||
d[4]||(f=(d[3]?"http://":"mailto:")+f),a=d.index,x(n.substr(0,a)),z(f,d[0].replace(q,"")),n=n.substring(a+d[0].length);x(n);return k(m.join(""))}}])})(window,window.angular);
|
||||
//# sourceMappingURL=angular-sanitize.min.js.map
|
||||
156
dashboard/public/js/angular-slick.min.js
vendored
@@ -1,156 +0,0 @@
|
||||
'use strict';
|
||||
angular.module('slick', []).directive('slick', [
|
||||
'$timeout',
|
||||
function ($timeout) {
|
||||
return {
|
||||
restrict: 'AEC',
|
||||
scope: {
|
||||
initOnload: '@',
|
||||
data: '=',
|
||||
currentIndex: '=',
|
||||
accessibility: '@',
|
||||
adaptiveHeight: '@',
|
||||
arrows: '@',
|
||||
asNavFor: '@',
|
||||
appendArrows: '@',
|
||||
appendDots: '@',
|
||||
autoplay: '@',
|
||||
autoplaySpeed: '@',
|
||||
centerMode: '@',
|
||||
centerPadding: '@',
|
||||
cssEase: '@',
|
||||
customPaging: '&',
|
||||
dots: '@',
|
||||
draggable: '@',
|
||||
easing: '@',
|
||||
fade: '@',
|
||||
focusOnSelect: '@',
|
||||
infinite: '@',
|
||||
initialSlide: '@',
|
||||
lazyLoad: '@',
|
||||
onBeforeChange: '&',
|
||||
onAfterChange: '&',
|
||||
onInit: '&',
|
||||
onReInit: '&',
|
||||
onSetPosition: '&',
|
||||
pauseOnHover: '@',
|
||||
pauseOnDotsHover: '@',
|
||||
responsive: '=',
|
||||
rtl: '@',
|
||||
slide: '@',
|
||||
slidesToShow: '@',
|
||||
slidesToScroll: '@',
|
||||
speed: '@',
|
||||
swipe: '@',
|
||||
swipeToSlide: '@',
|
||||
touchMove: '@',
|
||||
touchThreshold: '@',
|
||||
useCSS: '@',
|
||||
variableWidth: '@',
|
||||
vertical: '@',
|
||||
prevArrow: '@',
|
||||
nextArrow: '@'
|
||||
},
|
||||
link: function (scope, element, attrs) {
|
||||
var destroySlick, initializeSlick, isInitialized;
|
||||
destroySlick = function () {
|
||||
return $timeout(function () {
|
||||
var slider;
|
||||
slider = $(element);
|
||||
slider.unslick();
|
||||
slider.find('.slick-list').remove();
|
||||
return slider;
|
||||
});
|
||||
};
|
||||
initializeSlick = function () {
|
||||
return $timeout(function () {
|
||||
var currentIndex, slider;
|
||||
slider = $(element);
|
||||
if (scope.currentIndex != null) {
|
||||
currentIndex = scope.currentIndex;
|
||||
}
|
||||
slider.slick({
|
||||
accessibility: scope.accessibility !== 'false',
|
||||
adaptiveHeight: scope.adaptiveHeight === 'true',
|
||||
arrows: scope.arrows !== 'false',
|
||||
asNavFor: scope.asNavFor ? scope.asNavFor : void 0,
|
||||
appendArrows: scope.appendArrows ? $(scope.appendArrows) : $(element),
|
||||
appendDots: scope.appendDots ? $(scope.appendDots) : $(element),
|
||||
autoplay: scope.autoplay === 'true',
|
||||
autoplaySpeed: scope.autoplaySpeed != null ? parseInt(scope.autoplaySpeed, 10) : 3000,
|
||||
centerMode: scope.centerMode === 'true',
|
||||
centerPadding: scope.centerPadding || '50px',
|
||||
cssEase: scope.cssEase || 'ease',
|
||||
customPaging: attrs.customPaging ? scope.customPaging : void 0,
|
||||
dots: scope.dots === 'true',
|
||||
draggable: scope.draggable !== 'false',
|
||||
easing: scope.easing || 'linear',
|
||||
fade: scope.fade === 'true',
|
||||
focusOnSelect: scope.focusOnSelect === 'true',
|
||||
infinite: scope.infinite !== 'false',
|
||||
initialSlide: scope.initialSlide || 0,
|
||||
lazyLoad: scope.lazyLoad || 'ondemand',
|
||||
onBeforeChange: attrs.onBeforeChange ? scope.onBeforeChange : void 0,
|
||||
onAfterChange: function (sl, index) {
|
||||
if (attrs.onAfterChange) {
|
||||
scope.onAfterChange();
|
||||
}
|
||||
if (currentIndex != null) {
|
||||
return scope.$apply(function () {
|
||||
currentIndex = index;
|
||||
return scope.currentIndex = index;
|
||||
});
|
||||
}
|
||||
},
|
||||
onInit: function (sl) {
|
||||
if (attrs.onInit) {
|
||||
scope.onInit();
|
||||
}
|
||||
if (currentIndex != null) {
|
||||
return sl.slideHandler(currentIndex);
|
||||
}
|
||||
},
|
||||
onReInit: attrs.onReInit ? scope.onReInit : void 0,
|
||||
onSetPosition: attrs.onSetPosition ? scope.onSetPosition : void 0,
|
||||
pauseOnHover: scope.pauseOnHover !== 'false',
|
||||
responsive: scope.responsive || void 0,
|
||||
rtl: scope.rtl === 'true',
|
||||
slide: scope.slide || 'div',
|
||||
slidesToShow: scope.slidesToShow != null ? parseInt(scope.slidesToShow, 10) : 1,
|
||||
slidesToScroll: scope.slidesToScroll != null ? parseInt(scope.slidesToScroll, 10) : 1,
|
||||
speed: scope.speed != null ? parseInt(scope.speed, 10) : 300,
|
||||
swipe: scope.swipe !== 'false',
|
||||
swipeToSlide: scope.swipeToSlide === 'true',
|
||||
touchMove: scope.touchMove !== 'false',
|
||||
touchThreshold: scope.touchThreshold ? parseInt(scope.touchThreshold, 10) : 5,
|
||||
useCSS: scope.useCSS !== 'false',
|
||||
variableWidth: scope.variableWidth === 'true',
|
||||
vertical: scope.vertical === 'true',
|
||||
prevArrow: scope.prevArrow ? $(scope.prevArrow) : void 0,
|
||||
nextArrow: scope.nextArrow ? $(scope.nextArrow) : void 0
|
||||
});
|
||||
return scope.$watch('currentIndex', function (newVal, oldVal) {
|
||||
if (currentIndex != null && newVal != null && newVal !== currentIndex) {
|
||||
return slider.slickGoTo(newVal);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
if (scope.initOnload) {
|
||||
isInitialized = false;
|
||||
return scope.$watch('data', function (newVal, oldVal) {
|
||||
if (newVal != null) {
|
||||
if (isInitialized) {
|
||||
destroySlick();
|
||||
}
|
||||
initializeSlick();
|
||||
return isInitialized = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return initializeSlick();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
||||
@@ -1,6 +0,0 @@
|
||||
/*!
|
||||
* angular-translate - v2.18.3 - 2020-07-08
|
||||
*
|
||||
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
|
||||
*/
|
||||
!function(e,i){"function"==typeof define&&define.amd?define([],function(){return i()}):"object"==typeof module&&module.exports?module.exports=i():i()}(0,function(){function e(n,a){"use strict";return function(r){if(!(r&&(angular.isArray(r.files)||angular.isString(r.prefix)&&angular.isString(r.suffix))))throw new Error("Couldn't load static files, no files and prefix or suffix specified!");r.files||(r.files=[{prefix:r.prefix,suffix:r.suffix}]);for(var e=function(e){if(!e||!angular.isString(e.prefix)||!angular.isString(e.suffix))throw new Error("Couldn't load static file, no prefix or suffix specified!");var i=[e.prefix,r.key,e.suffix].join("");return angular.isObject(r.fileMap)&&r.fileMap[i]&&(i=r.fileMap[i]),a(angular.extend({url:i,method:"GET"},r.$http)).then(function(e){return e.data},function(){return n.reject(r.key)})},i=[],t=r.files.length,f=0;f<t;f++)i.push(e({prefix:r.files[f].prefix,key:r.key,suffix:r.files[f].suffix}));return n.all(i).then(function(e){for(var i=e.length,r={},t=0;t<i;t++)for(var f in e[t])r[f]=e[t][f];return r})}}return e.$inject=["$q","$http"],angular.module("pascalprecht.translate").factory("$translateStaticFilesLoader",e),e.displayName="$translateStaticFilesLoader","pascalprecht.translate"});
|
||||
@@ -1,6 +0,0 @@
|
||||
/*!
|
||||
* angular-translate - v2.18.3 - 2020-07-08
|
||||
*
|
||||
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
|
||||
*/
|
||||
!function(t,e){"function"==typeof define&&define.amd?define([],function(){return e()}):"object"==typeof module&&module.exports?module.exports=e():e()}(0,function(){function t(t){"use strict";var n;if(1===angular.version.major&&4<=angular.version.minor){var o=t.get("$cookies");n={get:function(t){return o.get(t)},put:function(t,e){o.put(t,e)}}}else{var r=t.get("$cookieStore");n={get:function(t){return r.get(t)},put:function(t,e){r.put(t,e)}}}return{get:function(t){return n.get(t)},set:function(t,e){n.put(t,e)},put:function(t,e){n.put(t,e)}}}return t.$inject=["$injector"],angular.module("pascalprecht.translate").factory("$translateCookieStorage",t),t.displayName="$translateCookieStorage","pascalprecht.translate"});
|
||||
@@ -1,6 +0,0 @@
|
||||
/*!
|
||||
* angular-translate - v2.18.3 - 2020-07-08
|
||||
*
|
||||
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
|
||||
*/
|
||||
!function(t,e){"function"==typeof define&&define.amd?define([],function(){return e()}):"object"==typeof module&&module.exports?module.exports=e():e()}(0,function(){function t(a,t){"use strict";var o,e={get:function(t){return o||(o=a.localStorage.getItem(t)),o},set:function(t,e){o=e,a.localStorage.setItem(t,e)},put:function(t,e){o=e,a.localStorage.setItem(t,e)}},r="localStorage"in a;if(r){var n="pascalprecht.translate.storageTest";try{r=null!==a.localStorage&&(a.localStorage.setItem(n,"foo"),a.localStorage.removeItem(n),!0)}catch(t){r=!1}}return r?e:t}return t.$inject=["$window","$translateCookieStorage"],angular.module("pascalprecht.translate").factory("$translateLocalStorage",t),t.displayName="$translateLocalStorageFactory","pascalprecht.translate"});
|
||||
6
dashboard/public/js/angular-translate.min.js
vendored
271
dashboard/public/js/angular-ui-notification.js
vendored
@@ -1,271 +0,0 @@
|
||||
/**
|
||||
* angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
|
||||
* @author Alex_Crack
|
||||
* @version v0.3.6
|
||||
* @link https://github.com/alexcrack/angular-ui-notification
|
||||
* @license MIT
|
||||
*/
|
||||
angular.module('ui-notification', []);
|
||||
|
||||
angular.module('ui-notification').provider('Notification', function () {
|
||||
|
||||
this.options = {
|
||||
delay: 5000,
|
||||
startTop: 10,
|
||||
startRight: 10,
|
||||
verticalSpacing: 10,
|
||||
horizontalSpacing: 10,
|
||||
positionX: 'right',
|
||||
positionY: 'top',
|
||||
replaceMessage: false,
|
||||
templateUrl: 'angular-ui-notification.html',
|
||||
onClose: undefined,
|
||||
onClick: undefined,
|
||||
closeOnClick: true,
|
||||
maxCount: 0, // 0 - Infinite
|
||||
container: 'body',
|
||||
priority: 10
|
||||
};
|
||||
|
||||
this.setOptions = function (options) {
|
||||
if (!angular.isObject(options)) throw new Error("Options should be an object!");
|
||||
this.options = angular.extend({}, this.options, options);
|
||||
};
|
||||
|
||||
this.$get = ["$timeout", "$http", "$compile", "$templateCache", "$rootScope", "$injector", "$sce", "$q", "$window", function ($timeout, $http, $compile, $templateCache, $rootScope, $injector, $sce, $q, $window) {
|
||||
var options = this.options;
|
||||
|
||||
var startTop = options.startTop;
|
||||
var startRight = options.startRight;
|
||||
var verticalSpacing = options.verticalSpacing;
|
||||
var horizontalSpacing = options.horizontalSpacing;
|
||||
var delay = options.delay;
|
||||
|
||||
var messageElements = [];
|
||||
var isResizeBound = false;
|
||||
|
||||
var notify = function (args, t) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
if (typeof args !== 'object' || args === null) {
|
||||
args = {message: args};
|
||||
}
|
||||
|
||||
args.scope = args.scope ? args.scope : $rootScope;
|
||||
args.template = args.templateUrl ? args.templateUrl : options.templateUrl;
|
||||
args.delay = !angular.isUndefined(args.delay) ? args.delay : delay;
|
||||
args.type = t || args.type || options.type || '';
|
||||
args.positionY = args.positionY ? args.positionY : options.positionY;
|
||||
args.positionX = args.positionX ? args.positionX : options.positionX;
|
||||
args.replaceMessage = args.replaceMessage ? args.replaceMessage : options.replaceMessage;
|
||||
args.onClose = args.onClose ? args.onClose : options.onClose;
|
||||
args.onClick = args.onClick ? args.onClick : options.onClick;
|
||||
args.closeOnClick = (args.closeOnClick !== null && args.closeOnClick !== undefined) ? args.closeOnClick : options.closeOnClick;
|
||||
args.container = args.container ? args.container : options.container;
|
||||
args.priority = args.priority ? args.priority : options.priority;
|
||||
|
||||
var template = $templateCache.get(args.template);
|
||||
|
||||
if (template) {
|
||||
processNotificationTemplate(template);
|
||||
} else {
|
||||
// load it via $http only if it isn't default template and template isn't exist in template cache
|
||||
// cache:true means cache it for later access.
|
||||
$http.get(args.template, {cache: true})
|
||||
.then(function (response) {
|
||||
processNotificationTemplate(response.data);
|
||||
})
|
||||
.catch(function (data) {
|
||||
throw new Error('Template (' + args.template + ') could not be loaded. ' + data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function processNotificationTemplate(template) {
|
||||
|
||||
var scope = args.scope.$new();
|
||||
scope.message = $sce.trustAsHtml(args.message);
|
||||
scope.title = $sce.trustAsHtml(args.title);
|
||||
scope.t = args.type.substr(0, 1);
|
||||
scope.delay = args.delay;
|
||||
scope.onClose = args.onClose;
|
||||
scope.onClick = args.onClick;
|
||||
|
||||
var priorityCompareTop = function (a, b) {
|
||||
return a._priority - b._priority;
|
||||
};
|
||||
|
||||
var priorityCompareBtm = function (a, b) {
|
||||
return b._priority - a._priority;
|
||||
};
|
||||
|
||||
var reposite = function () {
|
||||
var j = 0;
|
||||
var k = 0;
|
||||
var lastTop = startTop;
|
||||
var lastRight = startRight;
|
||||
var lastPosition = [];
|
||||
|
||||
if (args.positionY === 'top') {
|
||||
messageElements.sort(priorityCompareTop);
|
||||
} else if (args.positionY === 'bottom') {
|
||||
messageElements.sort(priorityCompareBtm);
|
||||
}
|
||||
|
||||
for (var i = messageElements.length - 1; i >= 0; i--) {
|
||||
var element = messageElements[i];
|
||||
if (args.replaceMessage && i < messageElements.length - 1) {
|
||||
element.addClass('killed');
|
||||
continue;
|
||||
}
|
||||
var elHeight = parseInt(element[0].offsetHeight);
|
||||
var elWidth = parseInt(element[0].offsetWidth);
|
||||
var position = lastPosition[element._positionY + element._positionX];
|
||||
|
||||
if ((top + elHeight) > window.innerHeight) {
|
||||
position = startTop;
|
||||
k++;
|
||||
j = 0;
|
||||
}
|
||||
|
||||
var top = (lastTop = position ? (j === 0 ? position : position + verticalSpacing) : startTop);
|
||||
var right = lastRight + (k * (horizontalSpacing + elWidth));
|
||||
|
||||
element.css(element._positionY, top + 'px');
|
||||
if (element._positionX === 'center') {
|
||||
element.css('left', parseInt(window.innerWidth / 2 - elWidth / 2) + 'px');
|
||||
} else {
|
||||
element.css(element._positionX, right + 'px');
|
||||
}
|
||||
|
||||
lastPosition[element._positionY + element._positionX] = top + elHeight;
|
||||
|
||||
if (options.maxCount > 0 && messageElements.length > options.maxCount && i === 0) {
|
||||
element.scope().kill(true);
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
};
|
||||
|
||||
var templateElement = $compile(template)(scope);
|
||||
templateElement._positionY = args.positionY;
|
||||
templateElement._positionX = args.positionX;
|
||||
templateElement._priority = args.priority;
|
||||
templateElement.addClass(args.type);
|
||||
|
||||
var closeEvent = function (e) {
|
||||
e = e.originalEvent || e;
|
||||
if (e.type === 'click' || e.propertyName === 'opacity' && e.elapsedTime >= 1) {
|
||||
|
||||
if (scope.onClose) {
|
||||
scope.$apply(scope.onClose(templateElement));
|
||||
}
|
||||
|
||||
if (e.type === 'click')
|
||||
if (scope.onClick) {
|
||||
scope.$apply(scope.onClick(templateElement));
|
||||
}
|
||||
|
||||
templateElement.remove();
|
||||
messageElements.splice(messageElements.indexOf(templateElement), 1);
|
||||
scope.$destroy();
|
||||
reposite();
|
||||
}
|
||||
};
|
||||
|
||||
if (args.closeOnClick) {
|
||||
templateElement.addClass('clickable');
|
||||
templateElement.bind('click', closeEvent);
|
||||
}
|
||||
|
||||
templateElement.bind('webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd', closeEvent);
|
||||
|
||||
if (angular.isNumber(args.delay)) {
|
||||
$timeout(function () {
|
||||
templateElement.addClass('killed');
|
||||
}, args.delay);
|
||||
}
|
||||
|
||||
setCssTransitions('none');
|
||||
|
||||
angular.element(document.querySelector(args.container)).append(templateElement);
|
||||
var offset = -(parseInt(templateElement[0].offsetHeight) + 50);
|
||||
templateElement.css(templateElement._positionY, offset + "px");
|
||||
messageElements.push(templateElement);
|
||||
|
||||
if (args.positionX == 'center') {
|
||||
var elWidth = parseInt(templateElement[0].offsetWidth);
|
||||
templateElement.css('left', parseInt(window.innerWidth / 2 - elWidth / 2) + 'px');
|
||||
}
|
||||
|
||||
$timeout(function () {
|
||||
setCssTransitions('');
|
||||
});
|
||||
|
||||
function setCssTransitions(value) {
|
||||
['-webkit-transition', '-o-transition', 'transition'].forEach(function (prefix) {
|
||||
templateElement.css(prefix, value);
|
||||
});
|
||||
}
|
||||
|
||||
scope._templateElement = templateElement;
|
||||
|
||||
scope.kill = function (isHard) {
|
||||
if (isHard) {
|
||||
if (scope.onClose) {
|
||||
scope.$apply(scope.onClose(scope._templateElement));
|
||||
}
|
||||
|
||||
messageElements.splice(messageElements.indexOf(scope._templateElement), 1);
|
||||
scope._templateElement.remove();
|
||||
scope.$destroy();
|
||||
$timeout(reposite);
|
||||
} else {
|
||||
scope._templateElement.addClass('killed');
|
||||
}
|
||||
};
|
||||
|
||||
$timeout(reposite);
|
||||
|
||||
if (!isResizeBound) {
|
||||
angular.element($window).bind('resize', function (e) {
|
||||
$timeout(reposite);
|
||||
});
|
||||
isResizeBound = true;
|
||||
}
|
||||
|
||||
deferred.resolve(scope);
|
||||
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
notify.primary = function (args) {
|
||||
return this(args, 'primary');
|
||||
};
|
||||
notify.error = function (args) {
|
||||
return this(args, 'error');
|
||||
};
|
||||
notify.success = function (args) {
|
||||
return this(args, 'success');
|
||||
};
|
||||
notify.info = function (args) {
|
||||
return this(args, 'info');
|
||||
};
|
||||
notify.warning = function (args) {
|
||||
return this(args, 'warning');
|
||||
};
|
||||
|
||||
notify.clearAll = function () {
|
||||
angular.forEach(messageElements, function (element) {
|
||||
element.addClass('killed');
|
||||
});
|
||||
};
|
||||
|
||||
return notify;
|
||||
}];
|
||||
});
|
||||
|
||||
angular.module("ui-notification").run(["$templateCache", function($templateCache) {$templateCache.put("angular-ui-notification.html","<div class=\"ui-notification\"><h3 ng-show=\"title\" ng-bind-html=\"title\"></h3><div class=\"message\" ng-bind-html=\"message\"></div></div>");}]);
|
||||
318
dashboard/public/js/angular.min.js
vendored
@@ -1,318 +0,0 @@
|
||||
/*
|
||||
AngularJS v1.5.8
|
||||
(c) 2010-2016 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(C){'use strict';function N(a){return function(){var b=arguments[0],d;d="["+(a?a+":":"")+b+"] http://errors.angularjs.org/1.5.8/"+(a?a+"/":"")+b;for(b=1;b<arguments.length;b++){d=d+(1==b?"?":"&")+"p"+(b-1)+"=";var c=encodeURIComponent,e;e=arguments[b];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;d+=c(e)}return Error(d)}}function ta(a){if(null==a||Va(a))return!1;if(L(a)||G(a)||F&&a instanceof F)return!0;
|
||||
var b="length"in Object(a)&&a.length;return T(b)&&(0<=b&&(b-1 in a||a instanceof Array)||"function"==typeof a.item)}function q(a,b,d){var c,e;if(a)if(z(a))for(c in a)"prototype"==c||"length"==c||"name"==c||a.hasOwnProperty&&!a.hasOwnProperty(c)||b.call(d,a[c],c,a);else if(L(a)||ta(a)){var f="object"!==typeof a;c=0;for(e=a.length;c<e;c++)(f||c in a)&&b.call(d,a[c],c,a)}else if(a.forEach&&a.forEach!==q)a.forEach(b,d,a);else if(sc(a))for(c in a)b.call(d,a[c],c,a);else if("function"===typeof a.hasOwnProperty)for(c in a)a.hasOwnProperty(c)&&
|
||||
b.call(d,a[c],c,a);else for(c in a)ua.call(a,c)&&b.call(d,a[c],c,a);return a}function tc(a,b,d){for(var c=Object.keys(a).sort(),e=0;e<c.length;e++)b.call(d,a[c[e]],c[e]);return c}function uc(a){return function(b,d){a(d,b)}}function Yd(){return++pb}function Pb(a,b,d){for(var c=a.$$hashKey,e=0,f=b.length;e<f;++e){var g=b[e];if(D(g)||z(g))for(var h=Object.keys(g),k=0,l=h.length;k<l;k++){var m=h[k],n=g[m];d&&D(n)?da(n)?a[m]=new Date(n.valueOf()):Wa(n)?a[m]=new RegExp(n):n.nodeName?a[m]=n.cloneNode(!0):
|
||||
Qb(n)?a[m]=n.clone():(D(a[m])||(a[m]=L(n)?[]:{}),Pb(a[m],[n],!0)):a[m]=n}}c?a.$$hashKey=c:delete a.$$hashKey;return a}function S(a){return Pb(a,va.call(arguments,1),!1)}function Zd(a){return Pb(a,va.call(arguments,1),!0)}function Z(a){return parseInt(a,10)}function Rb(a,b){return S(Object.create(a),b)}function A(){}function Xa(a){return a}function ha(a){return function(){return a}}function vc(a){return z(a.toString)&&a.toString!==ma}function y(a){return"undefined"===typeof a}function w(a){return"undefined"!==
|
||||
typeof a}function D(a){return null!==a&&"object"===typeof a}function sc(a){return null!==a&&"object"===typeof a&&!wc(a)}function G(a){return"string"===typeof a}function T(a){return"number"===typeof a}function da(a){return"[object Date]"===ma.call(a)}function z(a){return"function"===typeof a}function Wa(a){return"[object RegExp]"===ma.call(a)}function Va(a){return a&&a.window===a}function Ya(a){return a&&a.$evalAsync&&a.$watch}function Ga(a){return"boolean"===typeof a}function $d(a){return a&&T(a.length)&&
|
||||
ae.test(ma.call(a))}function Qb(a){return!(!a||!(a.nodeName||a.prop&&a.attr&&a.find))}function be(a){var b={};a=a.split(",");var d;for(d=0;d<a.length;d++)b[a[d]]=!0;return b}function wa(a){return Q(a.nodeName||a[0]&&a[0].nodeName)}function Za(a,b){var d=a.indexOf(b);0<=d&&a.splice(d,1);return d}function pa(a,b){function d(a,b){var d=b.$$hashKey,e;if(L(a)){e=0;for(var f=a.length;e<f;e++)b.push(c(a[e]))}else if(sc(a))for(e in a)b[e]=c(a[e]);else if(a&&"function"===typeof a.hasOwnProperty)for(e in a)a.hasOwnProperty(e)&&
|
||||
(b[e]=c(a[e]));else for(e in a)ua.call(a,e)&&(b[e]=c(a[e]));d?b.$$hashKey=d:delete b.$$hashKey;return b}function c(a){if(!D(a))return a;var b=f.indexOf(a);if(-1!==b)return g[b];if(Va(a)||Ya(a))throw xa("cpws");var b=!1,c=e(a);void 0===c&&(c=L(a)?[]:Object.create(wc(a)),b=!0);f.push(a);g.push(c);return b?d(a,c):c}function e(a){switch(ma.call(a)){case "[object Int8Array]":case "[object Int16Array]":case "[object Int32Array]":case "[object Float32Array]":case "[object Float64Array]":case "[object Uint8Array]":case "[object Uint8ClampedArray]":case "[object Uint16Array]":case "[object Uint32Array]":return new a.constructor(c(a.buffer),
|
||||
a.byteOffset,a.length);case "[object ArrayBuffer]":if(!a.slice){var b=new ArrayBuffer(a.byteLength);(new Uint8Array(b)).set(new Uint8Array(a));return b}return a.slice(0);case "[object Boolean]":case "[object Number]":case "[object String]":case "[object Date]":return new a.constructor(a.valueOf());case "[object RegExp]":return b=new RegExp(a.source,a.toString().match(/[^\/]*$/)[0]),b.lastIndex=a.lastIndex,b;case "[object Blob]":return new a.constructor([a],{type:a.type})}if(z(a.cloneNode))return a.cloneNode(!0)}
|
||||
var f=[],g=[];if(b){if($d(b)||"[object ArrayBuffer]"===ma.call(b))throw xa("cpta");if(a===b)throw xa("cpi");L(b)?b.length=0:q(b,function(a,d){"$$hashKey"!==d&&delete b[d]});f.push(a);g.push(b);return d(a,b)}return c(a)}function na(a,b){if(a===b)return!0;if(null===a||null===b)return!1;if(a!==a&&b!==b)return!0;var d=typeof a,c;if(d==typeof b&&"object"==d)if(L(a)){if(!L(b))return!1;if((d=a.length)==b.length){for(c=0;c<d;c++)if(!na(a[c],b[c]))return!1;return!0}}else{if(da(a))return da(b)?na(a.getTime(),
|
||||
b.getTime()):!1;if(Wa(a))return Wa(b)?a.toString()==b.toString():!1;if(Ya(a)||Ya(b)||Va(a)||Va(b)||L(b)||da(b)||Wa(b))return!1;d=U();for(c in a)if("$"!==c.charAt(0)&&!z(a[c])){if(!na(a[c],b[c]))return!1;d[c]=!0}for(c in b)if(!(c in d)&&"$"!==c.charAt(0)&&w(b[c])&&!z(b[c]))return!1;return!0}return!1}function $a(a,b,d){return a.concat(va.call(b,d))}function ab(a,b){var d=2<arguments.length?va.call(arguments,2):[];return!z(b)||b instanceof RegExp?b:d.length?function(){return arguments.length?b.apply(a,
|
||||
$a(d,arguments,0)):b.apply(a,d)}:function(){return arguments.length?b.apply(a,arguments):b.call(a)}}function ce(a,b){var d=b;"string"===typeof a&&"$"===a.charAt(0)&&"$"===a.charAt(1)?d=void 0:Va(b)?d="$WINDOW":b&&C.document===b?d="$DOCUMENT":Ya(b)&&(d="$SCOPE");return d}function bb(a,b){if(!y(a))return T(b)||(b=b?2:null),JSON.stringify(a,ce,b)}function xc(a){return G(a)?JSON.parse(a):a}function yc(a,b){a=a.replace(de,"");var d=Date.parse("Jan 01, 1970 00:00:00 "+a)/6E4;return isNaN(d)?b:d}function Sb(a,
|
||||
b,d){d=d?-1:1;var c=a.getTimezoneOffset();b=yc(b,c);d*=b-c;a=new Date(a.getTime());a.setMinutes(a.getMinutes()+d);return a}function ya(a){a=F(a).clone();try{a.empty()}catch(b){}var d=F("<div>").append(a).html();try{return a[0].nodeType===Ma?Q(d):d.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+Q(b)})}catch(c){return Q(d)}}function zc(a){try{return decodeURIComponent(a)}catch(b){}}function Ac(a){var b={};q((a||"").split("&"),function(a){var c,e,f;a&&(e=a=a.replace(/\+/g,"%20"),
|
||||
c=a.indexOf("="),-1!==c&&(e=a.substring(0,c),f=a.substring(c+1)),e=zc(e),w(e)&&(f=w(f)?zc(f):!0,ua.call(b,e)?L(b[e])?b[e].push(f):b[e]=[b[e],f]:b[e]=f))});return b}function Tb(a){var b=[];q(a,function(a,c){L(a)?q(a,function(a){b.push(ea(c,!0)+(!0===a?"":"="+ea(a,!0)))}):b.push(ea(c,!0)+(!0===a?"":"="+ea(a,!0)))});return b.length?b.join("&"):""}function qb(a){return ea(a,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ea(a,b){return encodeURIComponent(a).replace(/%40/gi,
|
||||
"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,b?"%20":"+")}function ee(a,b){var d,c,e=Na.length;for(c=0;c<e;++c)if(d=Na[c]+b,G(d=a.getAttribute(d)))return d;return null}function fe(a,b){var d,c,e={};q(Na,function(b){b+="app";!d&&a.hasAttribute&&a.hasAttribute(b)&&(d=a,c=a.getAttribute(b))});q(Na,function(b){b+="app";var e;!d&&(e=a.querySelector("["+b.replace(":","\\:")+"]"))&&(d=e,c=e.getAttribute(b))});d&&(e.strictDi=null!==ee(d,"strict-di"),
|
||||
b(d,c?[c]:[],e))}function Bc(a,b,d){D(d)||(d={});d=S({strictDi:!1},d);var c=function(){a=F(a);if(a.injector()){var c=a[0]===C.document?"document":ya(a);throw xa("btstrpd",c.replace(/</,"<").replace(/>/,">"));}b=b||[];b.unshift(["$provide",function(b){b.value("$rootElement",a)}]);d.debugInfoEnabled&&b.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);b.unshift("ng");c=cb(b,d.strictDi);c.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",
|
||||
d);c(b)(a)})}]);return c},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;C&&e.test(C.name)&&(d.debugInfoEnabled=!0,C.name=C.name.replace(e,""));if(C&&!f.test(C.name))return c();C.name=C.name.replace(f,"");ca.resumeBootstrap=function(a){q(a,function(a){b.push(a)});return c()};z(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function ge(){C.name="NG_ENABLE_DEBUG_INFO!"+C.name;C.location.reload()}function he(a){a=ca.element(a).injector();if(!a)throw xa("test");return a.get("$$testability")}
|
||||
function Cc(a,b){b=b||"_";return a.replace(ie,function(a,c){return(c?b:"")+a.toLowerCase()})}function je(){var a;if(!Dc){var b=rb();(qa=y(b)?C.jQuery:b?C[b]:void 0)&&qa.fn.on?(F=qa,S(qa.fn,{scope:Oa.scope,isolateScope:Oa.isolateScope,controller:Oa.controller,injector:Oa.injector,inheritedData:Oa.inheritedData}),a=qa.cleanData,qa.cleanData=function(b){for(var c,e=0,f;null!=(f=b[e]);e++)(c=qa._data(f,"events"))&&c.$destroy&&qa(f).triggerHandler("$destroy");a(b)}):F=O;ca.element=F;Dc=!0}}function sb(a,
|
||||
b,d){if(!a)throw xa("areq",b||"?",d||"required");return a}function Pa(a,b,d){d&&L(a)&&(a=a[a.length-1]);sb(z(a),b,"not a function, got "+(a&&"object"===typeof a?a.constructor.name||"Object":typeof a));return a}function Qa(a,b){if("hasOwnProperty"===a)throw xa("badname",b);}function Ec(a,b,d){if(!b)return a;b=b.split(".");for(var c,e=a,f=b.length,g=0;g<f;g++)c=b[g],a&&(a=(e=a)[c]);return!d&&z(a)?ab(e,a):a}function tb(a){for(var b=a[0],d=a[a.length-1],c,e=1;b!==d&&(b=b.nextSibling);e++)if(c||a[e]!==
|
||||
b)c||(c=F(va.call(a,0,e))),c.push(b);return c||a}function U(){return Object.create(null)}function ke(a){function b(a,b,c){return a[b]||(a[b]=c())}var d=N("$injector"),c=N("ng");a=b(a,"angular",Object);a.$$minErr=a.$$minErr||N;return b(a,"module",function(){var a={};return function(f,g,h){if("hasOwnProperty"===f)throw c("badname","module");g&&a.hasOwnProperty(f)&&(a[f]=null);return b(a,f,function(){function a(b,d,e,f){f||(f=c);return function(){f[e||"push"]([b,d,arguments]);return R}}function b(a,
|
||||
d){return function(b,e){e&&z(e)&&(e.$$moduleName=f);c.push([a,d,arguments]);return R}}if(!g)throw d("nomod",f);var c=[],e=[],p=[],u=a("$injector","invoke","push",e),R={_invokeQueue:c,_configBlocks:e,_runBlocks:p,requires:g,name:f,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),decorator:b("$provide","decorator"),animation:b("$animateProvider","register"),filter:b("$filterProvider",
|
||||
"register"),controller:b("$controllerProvider","register"),directive:b("$compileProvider","directive"),component:b("$compileProvider","component"),config:u,run:function(a){p.push(a);return this}};h&&u(h);return R})}})}function ia(a,b){if(L(a)){b=b||[];for(var d=0,c=a.length;d<c;d++)b[d]=a[d]}else if(D(a))for(d in b=b||{},a)if("$"!==d.charAt(0)||"$"!==d.charAt(1))b[d]=a[d];return b||a}function le(a){S(a,{bootstrap:Bc,copy:pa,extend:S,merge:Zd,equals:na,element:F,forEach:q,injector:cb,noop:A,bind:ab,
|
||||
toJson:bb,fromJson:xc,identity:Xa,isUndefined:y,isDefined:w,isString:G,isFunction:z,isObject:D,isNumber:T,isElement:Qb,isArray:L,version:me,isDate:da,lowercase:Q,uppercase:ub,callbacks:{$$counter:0},getTestability:he,$$minErr:N,$$csp:Ba,reloadWithDebugInfo:ge});Ub=ke(C);Ub("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:ne});a.provider("$compile",Fc).directive({a:oe,input:Gc,textarea:Gc,form:pe,script:qe,select:re,style:se,option:te,ngBind:ue,ngBindHtml:ve,ngBindTemplate:we,ngClass:xe,
|
||||
ngClassEven:ye,ngClassOdd:ze,ngCloak:Ae,ngController:Be,ngForm:Ce,ngHide:De,ngIf:Ee,ngInclude:Fe,ngInit:Ge,ngNonBindable:He,ngPluralize:Ie,ngRepeat:Je,ngShow:Ke,ngStyle:Le,ngSwitch:Me,ngSwitchWhen:Ne,ngSwitchDefault:Oe,ngOptions:Pe,ngTransclude:Qe,ngModel:Re,ngList:Se,ngChange:Te,pattern:Hc,ngPattern:Hc,required:Ic,ngRequired:Ic,minlength:Jc,ngMinlength:Jc,maxlength:Kc,ngMaxlength:Kc,ngValue:Ue,ngModelOptions:Ve}).directive({ngInclude:We}).directive(vb).directive(Lc);a.provider({$anchorScroll:Xe,
|
||||
$animate:Ye,$animateCss:Ze,$$animateJs:$e,$$animateQueue:af,$$AnimateRunner:bf,$$animateAsyncRun:cf,$browser:df,$cacheFactory:ef,$controller:ff,$document:gf,$exceptionHandler:hf,$filter:Mc,$$forceReflow:jf,$interpolate:kf,$interval:lf,$http:mf,$httpParamSerializer:nf,$httpParamSerializerJQLike:of,$httpBackend:pf,$xhrFactory:qf,$jsonpCallbacks:rf,$location:sf,$log:tf,$parse:uf,$rootScope:vf,$q:wf,$$q:xf,$sce:yf,$sceDelegate:zf,$sniffer:Af,$templateCache:Bf,$templateRequest:Cf,$$testability:Df,$timeout:Ef,
|
||||
$window:Ff,$$rAF:Gf,$$jqLite:Hf,$$HashMap:If,$$cookieReader:Jf})}])}function db(a){return a.replace(Kf,function(a,d,c,e){return e?c.toUpperCase():c}).replace(Lf,"Moz$1")}function Nc(a){a=a.nodeType;return 1===a||!a||9===a}function Oc(a,b){var d,c,e=b.createDocumentFragment(),f=[];if(Vb.test(a)){d=e.appendChild(b.createElement("div"));c=(Mf.exec(a)||["",""])[1].toLowerCase();c=ja[c]||ja._default;d.innerHTML=c[1]+a.replace(Nf,"<$1></$2>")+c[2];for(c=c[0];c--;)d=d.lastChild;f=$a(f,d.childNodes);d=e.firstChild;
|
||||
d.textContent=""}else f.push(b.createTextNode(a));e.textContent="";e.innerHTML="";q(f,function(a){e.appendChild(a)});return e}function Pc(a,b){var d=a.parentNode;d&&d.replaceChild(b,a);b.appendChild(a)}function O(a){if(a instanceof O)return a;var b;G(a)&&(a=W(a),b=!0);if(!(this instanceof O)){if(b&&"<"!=a.charAt(0))throw Wb("nosel");return new O(a)}if(b){b=C.document;var d;a=(d=Of.exec(a))?[b.createElement(d[1])]:(d=Oc(a,b))?d.childNodes:[]}Qc(this,a)}function Xb(a){return a.cloneNode(!0)}function wb(a,
|
||||
b){b||eb(a);if(a.querySelectorAll)for(var d=a.querySelectorAll("*"),c=0,e=d.length;c<e;c++)eb(d[c])}function Rc(a,b,d,c){if(w(c))throw Wb("offargs");var e=(c=xb(a))&&c.events,f=c&&c.handle;if(f)if(b){var g=function(b){var c=e[b];w(d)&&Za(c||[],d);w(d)&&c&&0<c.length||(a.removeEventListener(b,f,!1),delete e[b])};q(b.split(" "),function(a){g(a);yb[a]&&g(yb[a])})}else for(b in e)"$destroy"!==b&&a.removeEventListener(b,f,!1),delete e[b]}function eb(a,b){var d=a.ng339,c=d&&fb[d];c&&(b?delete c.data[b]:
|
||||
(c.handle&&(c.events.$destroy&&c.handle({},"$destroy"),Rc(a)),delete fb[d],a.ng339=void 0))}function xb(a,b){var d=a.ng339,d=d&&fb[d];b&&!d&&(a.ng339=d=++Pf,d=fb[d]={events:{},data:{},handle:void 0});return d}function Yb(a,b,d){if(Nc(a)){var c=w(d),e=!c&&b&&!D(b),f=!b;a=(a=xb(a,!e))&&a.data;if(c)a[b]=d;else{if(f)return a;if(e)return a&&a[b];S(a,b)}}}function zb(a,b){return a.getAttribute?-1<(" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+b+" "):!1}function Ab(a,b){b&&a.setAttribute&&
|
||||
q(b.split(" "),function(b){a.setAttribute("class",W((" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+W(b)+" "," ")))})}function Bb(a,b){if(b&&a.setAttribute){var d=(" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");q(b.split(" "),function(a){a=W(a);-1===d.indexOf(" "+a+" ")&&(d+=a+" ")});a.setAttribute("class",W(d))}}function Qc(a,b){if(b)if(b.nodeType)a[a.length++]=b;else{var d=b.length;if("number"===typeof d&&b.window!==b){if(d)for(var c=0;c<d;c++)a[a.length++]=
|
||||
b[c]}else a[a.length++]=b}}function Sc(a,b){return Cb(a,"$"+(b||"ngController")+"Controller")}function Cb(a,b,d){9==a.nodeType&&(a=a.documentElement);for(b=L(b)?b:[b];a;){for(var c=0,e=b.length;c<e;c++)if(w(d=F.data(a,b[c])))return d;a=a.parentNode||11===a.nodeType&&a.host}}function Tc(a){for(wb(a,!0);a.firstChild;)a.removeChild(a.firstChild)}function Db(a,b){b||wb(a);var d=a.parentNode;d&&d.removeChild(a)}function Qf(a,b){b=b||C;if("complete"===b.document.readyState)b.setTimeout(a);else F(b).on("load",
|
||||
a)}function Uc(a,b){var d=Eb[b.toLowerCase()];return d&&Vc[wa(a)]&&d}function Rf(a,b){var d=function(c,d){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=b[d||c.type],g=f?f.length:0;if(g){if(y(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};var k=f.specialHandlerWrapper||
|
||||
Sf;1<g&&(f=ia(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||k(a,c,f[l])}};d.elem=a;return d}function Sf(a,b,d){d.call(a,b)}function Tf(a,b,d){var c=b.relatedTarget;c&&(c===a||Uf.call(a,c))||d.call(a,b)}function Hf(){this.$get=function(){return S(O,{hasClass:function(a,b){a.attr&&(a=a[0]);return zb(a,b)},addClass:function(a,b){a.attr&&(a=a[0]);return Bb(a,b)},removeClass:function(a,b){a.attr&&(a=a[0]);return Ab(a,b)}})}}function Ca(a,b){var d=a&&a.$$hashKey;if(d)return"function"===typeof d&&
|
||||
(d=a.$$hashKey()),d;d=typeof a;return d="function"==d||"object"==d&&null!==a?a.$$hashKey=d+":"+(b||Yd)():d+":"+a}function Ra(a,b){if(b){var d=0;this.nextUid=function(){return++d}}q(a,this.put,this)}function Wc(a){a=(Function.prototype.toString.call(a)+" ").replace(Vf,"");return a.match(Wf)||a.match(Xf)}function Yf(a){return(a=Wc(a))?"function("+(a[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function cb(a,b){function d(a){return function(b,c){if(D(b))q(b,uc(a));else return a(b,c)}}function c(a,b){Qa(a,
|
||||
"service");if(z(b)||L(b))b=p.instantiate(b);if(!b.$get)throw Ha("pget",a);return n[a+"Provider"]=b}function e(a,b){return function(){var c=B.invoke(b,this);if(y(c))throw Ha("undef",a);return c}}function f(a,b,d){return c(a,{$get:!1!==d?e(a,b):b})}function g(a){sb(y(a)||L(a),"modulesToLoad","not an array");var b=[],c;q(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=p.get(e[0]);f[e[1]].apply(f,e[2])}}if(!m.get(a)){m.put(a,!0);try{G(a)?(c=Ub(a),b=b.concat(g(c.requires)).concat(c._runBlocks),
|
||||
d(c._invokeQueue),d(c._configBlocks)):z(a)?b.push(p.invoke(a)):L(a)?b.push(p.invoke(a)):Pa(a,"module")}catch(e){throw L(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ha("modulerr",a,e.stack||e.message||e);}}});return b}function h(a,c){function d(b,e){if(a.hasOwnProperty(b)){if(a[b]===k)throw Ha("cdep",b+" <- "+l.join(" <- "));return a[b]}try{return l.unshift(b),a[b]=k,a[b]=c(b,e)}catch(f){throw a[b]===k&&delete a[b],f;}finally{l.shift()}}function e(a,
|
||||
c,f){var g=[];a=cb.$$annotate(a,b,f);for(var h=0,k=a.length;h<k;h++){var l=a[h];if("string"!==typeof l)throw Ha("itkn",l);g.push(c&&c.hasOwnProperty(l)?c[l]:d(l,f))}return g}return{invoke:function(a,b,c,d){"string"===typeof c&&(d=c,c=null);c=e(a,c,d);L(a)&&(a=a[a.length-1]);d=11>=Ea?!1:"function"===typeof a&&/^(?:class\b|constructor\()/.test(Function.prototype.toString.call(a)+" ");return d?(c.unshift(null),new (Function.prototype.bind.apply(a,c))):a.apply(b,c)},instantiate:function(a,b,c){var d=
|
||||
L(a)?a[a.length-1]:a;a=e(a,b,c);a.unshift(null);return new (Function.prototype.bind.apply(d,a))},get:d,annotate:cb.$$annotate,has:function(b){return n.hasOwnProperty(b+"Provider")||a.hasOwnProperty(b)}}}b=!0===b;var k={},l=[],m=new Ra([],!0),n={$provide:{provider:d(c),factory:d(f),service:d(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:d(function(a,b){return f(a,ha(b),!1)}),constant:d(function(a,b){Qa(a,"constant");n[a]=b;u[a]=b}),decorator:function(a,b){var c=
|
||||
p.get(a+"Provider"),d=c.$get;c.$get=function(){var a=B.invoke(d,c);return B.invoke(b,null,{$delegate:a})}}}},p=n.$injector=h(n,function(a,b){ca.isString(b)&&l.push(b);throw Ha("unpr",l.join(" <- "));}),u={},R=h(u,function(a,b){var c=p.get(a+"Provider",b);return B.invoke(c.$get,c,void 0,a)}),B=R;n.$injectorProvider={$get:ha(R)};var r=g(a),B=R.get("$injector");B.strictDi=b;q(r,function(a){a&&B.invoke(a)});return B}function Xe(){var a=!0;this.disableAutoScrolling=function(){a=!1};this.$get=["$window",
|
||||
"$location","$rootScope",function(b,d,c){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===wa(a))return b=a,!0});return b}function f(a){if(a){a.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():Qb(c)?(c=c[0],c="fixed"!==b.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):T(c)||(c=0);c&&(a=a.getBoundingClientRect().top,b.scrollBy(0,a-c))}else b.scrollTo(0,0)}function g(a){a=G(a)?a:d.hash();var b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===
|
||||
a&&f(null):f(null)}var h=b.document;a&&c.$watch(function(){return d.hash()},function(a,b){a===b&&""===a||Qf(function(){c.$evalAsync(g)})});return g}]}function gb(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;L(a)&&(a=a.join(" "));L(b)&&(b=b.join(" "));return a+" "+b}function Zf(a){G(a)&&(a=a.split(" "));var b=U();q(a,function(a){a.length&&(b[a]=!0)});return b}function Ia(a){return D(a)?a:{}}function $f(a,b,d,c){function e(a){try{a.apply(null,va.call(arguments,1))}finally{if(R--,0===R)for(;B.length;)try{B.pop()()}catch(b){d.error(b)}}}
|
||||
function f(){t=null;g();h()}function g(){r=K();r=y(r)?null:r;na(r,E)&&(r=E);E=r}function h(){if(v!==k.url()||J!==r)v=k.url(),J=r,q(M,function(a){a(k.url(),r)})}var k=this,l=a.location,m=a.history,n=a.setTimeout,p=a.clearTimeout,u={};k.isMock=!1;var R=0,B=[];k.$$completeOutstandingRequest=e;k.$$incOutstandingRequestCount=function(){R++};k.notifyWhenNoOutstandingRequests=function(a){0===R?a():B.push(a)};var r,J,v=l.href,fa=b.find("base"),t=null,K=c.history?function(){try{return m.state}catch(a){}}:
|
||||
A;g();J=r;k.url=function(b,d,e){y(e)&&(e=null);l!==a.location&&(l=a.location);m!==a.history&&(m=a.history);if(b){var f=J===e;if(v===b&&(!c.history||f))return k;var h=v&&Ja(v)===Ja(b);v=b;J=e;!c.history||h&&f?(h||(t=b),d?l.replace(b):h?(d=l,e=b.indexOf("#"),e=-1===e?"":b.substr(e),d.hash=e):l.href=b,l.href!==b&&(t=b)):(m[d?"replaceState":"pushState"](e,"",b),g(),J=r);t&&(t=b);return k}return t||l.href.replace(/%27/g,"'")};k.state=function(){return r};var M=[],H=!1,E=null;k.onUrlChange=function(b){if(!H){if(c.history)F(a).on("popstate",
|
||||
f);F(a).on("hashchange",f);H=!0}M.push(b);return b};k.$$applicationDestroyed=function(){F(a).off("hashchange popstate",f)};k.$$checkUrlChange=h;k.baseHref=function(){var a=fa.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};k.defer=function(a,b){var c;R++;c=n(function(){delete u[c];e(a)},b||0);u[c]=!0;return c};k.defer.cancel=function(a){return u[a]?(delete u[a],p(a),e(A),!0):!1}}function df(){this.$get=["$window","$log","$sniffer","$document",function(a,b,d,c){return new $f(a,c,b,
|
||||
d)}]}function ef(){this.$get=function(){function a(a,c){function e(a){a!=n&&(p?p==a&&(p=a.n):p=a,f(a.n,a.p),f(a,n),n=a,n.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(a in b)throw N("$cacheFactory")("iid",a);var g=0,h=S({},c,{id:a}),k=U(),l=c&&c.capacity||Number.MAX_VALUE,m=U(),n=null,p=null;return b[a]={put:function(a,b){if(!y(b)){if(l<Number.MAX_VALUE){var c=m[a]||(m[a]={key:a});e(c)}a in k||g++;k[a]=b;g>l&&this.remove(p.key);return b}},get:function(a){if(l<Number.MAX_VALUE){var b=m[a];
|
||||
if(!b)return;e(b)}return k[a]},remove:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;b==n&&(n=b.p);b==p&&(p=b.n);f(b.n,b.p);delete m[a]}a in k&&(delete k[a],g--)},removeAll:function(){k=U();g=0;m=U();n=p=null},destroy:function(){m=h=k=null;delete b[a]},info:function(){return S({},h,{size:g})}}}var b={};a.info=function(){var a={};q(b,function(b,e){a[e]=b.info()});return a};a.get=function(a){return b[a]};return a}}function Bf(){this.$get=["$cacheFactory",function(a){return a("templates")}]}
|
||||
function Fc(a,b){function d(a,b,c){var d=/^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/,e=U();q(a,function(a,f){if(a in n)e[f]=n[a];else{var g=a.match(d);if(!g)throw ga("iscp",b,f,a,c?"controller bindings definition":"isolate scope definition");e[f]={mode:g[1][0],collection:"*"===g[2],optional:"?"===g[3],attrName:g[4]||f};g[4]&&(n[a]=e[f])}});return e}function c(a){var b=a.charAt(0);if(!b||b!==Q(b))throw ga("baddir",a);if(a!==a.trim())throw ga("baddir",a);}function e(a){var b=a.require||a.controller&&a.name;
|
||||
!L(b)&&D(b)&&q(b,function(a,c){var d=a.match(l);a.substring(d[0].length)||(b[c]=d[0]+c)});return b}var f={},g=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,h=/(([\w\-]+)(?:\:([^;]+))?;?)/,k=be("ngSrc,ngSrcset,src,srcset"),l=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,m=/^(on[a-z]+|formaction)$/,n=U();this.directive=function B(b,d){Qa(b,"directive");G(b)?(c(b),sb(d,"directiveFactory"),f.hasOwnProperty(b)||(f[b]=[],a.factory(b+"Directive",["$injector","$exceptionHandler",function(a,c){var d=[];q(f[b],function(f,g){try{var h=
|
||||
a.invoke(f);z(h)?h={compile:ha(h)}:!h.compile&&h.link&&(h.compile=ha(h.link));h.priority=h.priority||0;h.index=g;h.name=h.name||b;h.require=e(h);h.restrict=h.restrict||"EA";h.$$moduleName=f.$$moduleName;d.push(h)}catch(k){c(k)}});return d}])),f[b].push(d)):q(b,uc(B));return this};this.component=function(a,b){function c(a){function e(b){return z(b)||L(b)?function(c,d){return a.invoke(b,this,{$element:c,$attrs:d})}:b}var f=b.template||b.templateUrl?b.template:"",g={controller:d,controllerAs:Xc(b.controller)||
|
||||
b.controllerAs||"$ctrl",template:e(f),templateUrl:e(b.templateUrl),transclude:b.transclude,scope:{},bindToController:b.bindings||{},restrict:"E",require:b.require};q(b,function(a,b){"$"===b.charAt(0)&&(g[b]=a)});return g}var d=b.controller||function(){};q(b,function(a,b){"$"===b.charAt(0)&&(c[b]=a,z(d)&&(d[b]=a))});c.$inject=["$injector"];return this.directive(a,c)};this.aHrefSanitizationWhitelist=function(a){return w(a)?(b.aHrefSanitizationWhitelist(a),this):b.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=
|
||||
function(a){return w(a)?(b.imgSrcSanitizationWhitelist(a),this):b.imgSrcSanitizationWhitelist()};var p=!0;this.debugInfoEnabled=function(a){return w(a)?(p=a,this):p};var u=10;this.onChangesTtl=function(a){return arguments.length?(u=a,this):u};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$sce","$animate","$$sanitizeUri",function(a,b,c,e,n,t,K,M,H,E){function I(){try{if(!--qa)throw Y=void 0,ga("infchng",u);K.$apply(function(){for(var a=
|
||||
[],b=0,c=Y.length;b<c;++b)try{Y[b]()}catch(d){a.push(d)}Y=void 0;if(a.length)throw a;})}finally{qa++}}function Da(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=a}function P(a,b,c){pa.innerHTML="<span "+b+">";b=pa.firstChild.attributes;var d=b[0];b.removeNamedItem(d.name);d.value=c;a.attributes.setNamedItem(d)}function x(a,b){try{a.addClass(b)}catch(c){}}function aa(a,b,c,d,e){a instanceof F||(a=F(a));for(var f=/\S+/,g=0,h=a.length;g<
|
||||
h;g++){var k=a[g];k.nodeType===Ma&&k.nodeValue.match(f)&&Pc(k,a[g]=C.document.createElement("span"))}var l=s(a,b,a,c,d,e);aa.$$addScopeClass(a);var m=null;return function(b,c,d){sb(b,"scope");e&&e.needsNewScope&&(b=b.$parent.$new());d=d||{};var f=d.parentBoundTranscludeFn,g=d.transcludeControllers;d=d.futureParentElement;f&&f.$$boundTransclude&&(f=f.$$boundTransclude);m||(m=(d=d&&d[0])?"foreignobject"!==wa(d)&&ma.call(d).match(/SVG/)?"svg":"html":"html");d="html"!==m?F(da(m,F("<div>").append(a).html())):
|
||||
c?Oa.clone.call(a):a;if(g)for(var h in g)d.data("$"+h+"Controller",g[h].instance);aa.$$addScopeInfo(d,b);c&&c(d,b);l&&l(b,d,d,f);return d}}function s(a,b,c,d,e,f){function g(a,c,d,e){var f,k,l,m,p,r,v;if(n)for(v=Array(c.length),m=0;m<h.length;m+=3)f=h[m],v[f]=c[f];else v=c;m=0;for(p=h.length;m<p;)k=v[h[m++]],c=h[m++],f=h[m++],c?(c.scope?(l=a.$new(),aa.$$addScopeInfo(F(k),l)):l=a,r=c.transcludeOnThisElement?za(a,c.transclude,e):!c.templateOnThisElement&&e?e:!e&&b?za(a,b):null,c(f,l,k,d,r)):f&&f(a,
|
||||
k.childNodes,void 0,e)}for(var h=[],k,l,m,p,n,r=0;r<a.length;r++){k=new Da;l=$b(a[r],[],k,0===r?d:void 0,e);(f=l.length?oa(l,a[r],k,b,c,null,[],[],f):null)&&f.scope&&aa.$$addScopeClass(k.$$element);k=f&&f.terminal||!(m=a[r].childNodes)||!m.length?null:s(m,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||k)h.push(r,f,k),p=!0,n=n||f;f=null}return p?g:null}function za(a,b,c){function d(e,f,g,h,k){e||(e=a.$new(!1,k),e.$$transcluded=!0);return b(e,f,{parentBoundTranscludeFn:c,
|
||||
transcludeControllers:g,futureParentElement:h})}var e=d.$$slots=U(),f;for(f in b.$$slots)e[f]=b.$$slots[f]?za(a,b.$$slots[f],c):null;return d}function $b(a,b,c,d,e){var f=c.$attr;switch(a.nodeType){case 1:O(b,Aa(wa(a)),"E",d,e);for(var g,k,l,m,p=a.attributes,n=0,r=p&&p.length;n<r;n++){var v=!1,u=!1;g=p[n];k=g.name;l=W(g.value);g=Aa(k);if(m=Ba.test(g))k=k.replace(Yc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});(g=g.match(Ca))&&V(g[1])&&(v=k,u=k.substr(0,k.length-5)+"end",k=
|
||||
k.substr(0,k.length-6));g=Aa(k.toLowerCase());f[g]=k;if(m||!c.hasOwnProperty(g))c[g]=l,Uc(a,g)&&(c[g]=!0);ia(a,b,l,g,m);O(b,g,"A",d,e,v,u)}f=a.className;D(f)&&(f=f.animVal);if(G(f)&&""!==f)for(;a=h.exec(f);)g=Aa(a[2]),O(b,g,"C",d,e)&&(c[g]=W(a[3])),f=f.substr(a.index+a[0].length);break;case Ma:if(11===Ea)for(;a.parentNode&&a.nextSibling&&a.nextSibling.nodeType===Ma;)a.nodeValue+=a.nextSibling.nodeValue,a.parentNode.removeChild(a.nextSibling);ca(b,a.nodeValue);break;case 8:hb(a,b,c,d,e)}b.sort(Z);
|
||||
return b}function hb(a,b,c,d,e){try{var f=g.exec(a.nodeValue);if(f){var h=Aa(f[1]);O(b,h,"M",d,e)&&(c[h]=W(f[2]))}}catch(k){}}function N(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ga("uterdir",b,c);1==a.nodeType&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return F(d)}function Zc(a,b,c){return function(d,e,f,g,h){e=N(e[0],b,c);return a(d,e,f,g,h)}}function ac(a,b,c,d,e,f){var g;return a?aa(b,c,d,e,f):function(){g||
|
||||
(g=aa(b,c,d,e,f),b=c=f=null);return g.apply(this,arguments)}}function oa(a,b,d,e,f,g,h,k,l){function m(a,b,c,d){if(a){c&&(a=Zc(a,c,d));a.require=x.require;a.directiveName=I;if(u===x||x.$$isolateScope)a=ja(a,{isolateScope:!0});h.push(a)}if(b){c&&(b=Zc(b,c,d));b.require=x.require;b.directiveName=I;if(u===x||x.$$isolateScope)b=ja(b,{isolateScope:!0});k.push(b)}}function p(a,e,f,g,l){function m(a,b,c,d){var e;Ya(a)||(d=c,c=b,b=a,a=void 0);fa&&(e=t);c||(c=fa?I.parent():I);if(d){var f=l.$$slots[d];if(f)return f(a,
|
||||
b,e,c,s);if(y(f))throw ga("noslot",d,ya(I));}else return l(a,b,e,c,s)}var n,E,x,M,B,t,P,I;b===f?(g=d,I=d.$$element):(I=F(f),g=new Da(I,d));B=e;u?M=e.$new(!0):r&&(B=e.$parent);l&&(P=m,P.$$boundTransclude=l,P.isSlotFilled=function(a){return!!l.$$slots[a]});v&&(t=ag(I,g,P,v,M,e,u));u&&(aa.$$addScopeInfo(I,M,!0,!(H&&(H===u||H===u.$$originalDirective))),aa.$$addScopeClass(I,!0),M.$$isolateBindings=u.$$isolateBindings,E=ka(e,g,M,M.$$isolateBindings,u),E.removeWatches&&M.$on("$destroy",E.removeWatches));
|
||||
for(n in t){E=v[n];x=t[n];var Zb=E.$$bindings.bindToController;x.bindingInfo=x.identifier&&Zb?ka(B,g,x.instance,Zb,E):{};var K=x();K!==x.instance&&(x.instance=K,I.data("$"+E.name+"Controller",K),x.bindingInfo.removeWatches&&x.bindingInfo.removeWatches(),x.bindingInfo=ka(B,g,x.instance,Zb,E))}q(v,function(a,b){var c=a.require;a.bindToController&&!L(c)&&D(c)&&S(t[b].instance,ib(b,c,I,t))});q(t,function(a){var b=a.instance;if(z(b.$onChanges))try{b.$onChanges(a.bindingInfo.initialChanges)}catch(d){c(d)}if(z(b.$onInit))try{b.$onInit()}catch(e){c(e)}z(b.$doCheck)&&
|
||||
(B.$watch(function(){b.$doCheck()}),b.$doCheck());z(b.$onDestroy)&&B.$on("$destroy",function(){b.$onDestroy()})});n=0;for(E=h.length;n<E;n++)x=h[n],la(x,x.isolateScope?M:e,I,g,x.require&&ib(x.directiveName,x.require,I,t),P);var s=e;u&&(u.template||null===u.templateUrl)&&(s=M);a&&a(s,f.childNodes,void 0,l);for(n=k.length-1;0<=n;n--)x=k[n],la(x,x.isolateScope?M:e,I,g,x.require&&ib(x.directiveName,x.require,I,t),P);q(t,function(a){a=a.instance;z(a.$postLink)&&a.$postLink()})}l=l||{};for(var n=-Number.MAX_VALUE,
|
||||
r=l.newScopeDirective,v=l.controllerDirectives,u=l.newIsolateScopeDirective,H=l.templateDirective,E=l.nonTlbTranscludeDirective,M=!1,B=!1,fa=l.hasElementTranscludeDirective,t=d.$$element=F(b),x,I,P,K=e,s,Fa=!1,za=!1,w,A=0,C=a.length;A<C;A++){x=a[A];var G=x.$$start,hb=x.$$end;G&&(t=N(b,G,hb));P=void 0;if(n>x.priority)break;if(w=x.scope)x.templateUrl||(D(w)?(X("new/isolated scope",u||r,x,t),u=x):X("new/isolated scope",u,x,t)),r=r||x;I=x.name;if(!Fa&&(x.replace&&(x.templateUrl||x.template)||x.transclude&&
|
||||
!x.$$tlb)){for(w=A+1;Fa=a[w++];)if(Fa.transclude&&!Fa.$$tlb||Fa.replace&&(Fa.templateUrl||Fa.template)){za=!0;break}Fa=!0}!x.templateUrl&&x.controller&&(w=x.controller,v=v||U(),X("'"+I+"' controller",v[I],x,t),v[I]=x);if(w=x.transclude)if(M=!0,x.$$tlb||(X("transclusion",E,x,t),E=x),"element"==w)fa=!0,n=x.priority,P=t,t=d.$$element=F(aa.$$createComment(I,d[I])),b=t[0],ea(f,va.call(P,0),b),P[0].$$parentNode=P[0].parentNode,K=ac(za,P,e,n,g&&g.name,{nonTlbTranscludeDirective:E});else{var oa=U();P=F(Xb(b)).contents();
|
||||
if(D(w)){P=[];var Q=U(),O=U();q(w,function(a,b){var c="?"===a.charAt(0);a=c?a.substring(1):a;Q[a]=b;oa[b]=null;O[b]=c});q(t.contents(),function(a){var b=Q[Aa(wa(a))];b?(O[b]=!0,oa[b]=oa[b]||[],oa[b].push(a)):P.push(a)});q(O,function(a,b){if(!a)throw ga("reqslot",b);});for(var V in oa)oa[V]&&(oa[V]=ac(za,oa[V],e))}t.empty();K=ac(za,P,e,void 0,void 0,{needsNewScope:x.$$isolateScope||x.$$newScope});K.$$slots=oa}if(x.template)if(B=!0,X("template",H,x,t),H=x,w=z(x.template)?x.template(t,d):x.template,
|
||||
w=xa(w),x.replace){g=x;P=Vb.test(w)?$c(da(x.templateNamespace,W(w))):[];b=P[0];if(1!=P.length||1!==b.nodeType)throw ga("tplrt",I,"");ea(f,t,b);C={$attr:{}};w=$b(b,[],C);var Z=a.splice(A+1,a.length-(A+1));(u||r)&&T(w,u,r);a=a.concat(w).concat(Z);$(d,C);C=a.length}else t.html(w);if(x.templateUrl)B=!0,X("template",H,x,t),H=x,x.replace&&(g=x),p=ba(a.splice(A,a.length-A),t,d,f,M&&K,h,k,{controllerDirectives:v,newScopeDirective:r!==x&&r,newIsolateScopeDirective:u,templateDirective:H,nonTlbTranscludeDirective:E}),
|
||||
C=a.length;else if(x.compile)try{s=x.compile(t,d,K);var Y=x.$$originalDirective||x;z(s)?m(null,ab(Y,s),G,hb):s&&m(ab(Y,s.pre),ab(Y,s.post),G,hb)}catch(ca){c(ca,ya(t))}x.terminal&&(p.terminal=!0,n=Math.max(n,x.priority))}p.scope=r&&!0===r.scope;p.transcludeOnThisElement=M;p.templateOnThisElement=B;p.transclude=K;l.hasElementTranscludeDirective=fa;return p}function ib(a,b,c,d){var e;if(G(b)){var f=b.match(l);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&&
|
||||
e.instance;if(!e){var h="$"+b+"Controller";e=g?c.inheritedData(h):c.data(h)}if(!e&&!f)throw ga("ctreq",b,a);}else if(L(b))for(e=[],g=0,f=b.length;g<f;g++)e[g]=ib(a,b[g],c,d);else D(b)&&(e={},q(b,function(b,f){e[f]=ib(a,b,c,d)}));return e||null}function ag(a,b,c,d,e,f,g){var h=U(),k;for(k in d){var l=d[k],m={$scope:l===g||l.$$isolateScope?e:f,$element:a,$attrs:b,$transclude:c},p=l.controller;"@"==p&&(p=b[l.name]);m=t(p,m,!0,l.controllerAs);h[l.name]=m;a.data("$"+l.name+"Controller",m.instance)}return h}
|
||||
function T(a,b,c){for(var d=0,e=a.length;d<e;d++)a[d]=Rb(a[d],{$$isolateScope:b,$$newScope:c})}function O(b,e,g,h,k,l,m){if(e===k)return null;k=null;if(f.hasOwnProperty(e)){var p;e=a.get(e+"Directive");for(var n=0,r=e.length;n<r;n++)try{if(p=e[n],(y(h)||h>p.priority)&&-1!=p.restrict.indexOf(g)){l&&(p=Rb(p,{$$start:l,$$end:m}));if(!p.$$bindings){var u=p,v=p,x=p.name,H={isolateScope:null,bindToController:null};D(v.scope)&&(!0===v.bindToController?(H.bindToController=d(v.scope,x,!0),H.isolateScope={}):
|
||||
H.isolateScope=d(v.scope,x,!1));D(v.bindToController)&&(H.bindToController=d(v.bindToController,x,!0));if(D(H.bindToController)){var E=v.controller,M=v.controllerAs;if(!E)throw ga("noctrl",x);if(!Xc(E,M))throw ga("noident",x);}var t=u.$$bindings=H;D(t.isolateScope)&&(p.$$isolateBindings=t.isolateScope)}b.push(p);k=p}}catch(I){c(I)}}return k}function V(b){if(f.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,e=c.length;d<e;d++)if(b=c[d],b.multiElement)return!0;return!1}function $(a,b){var c=b.$attr,
|
||||
d=a.$attr;q(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});q(b,function(b,e){a.hasOwnProperty(e)||"$"===e.charAt(0)||(a[e]=b,"class"!==e&&"style"!==e&&(d[e]=c[e]))})}function ba(a,b,c,d,f,g,h,k){var l=[],m,p,n=b[0],r=a.shift(),u=Rb(r,{templateUrl:null,transclude:null,replace:null,$$originalDirective:r}),H=z(r.templateUrl)?r.templateUrl(b,c):r.templateUrl,E=r.templateNamespace;b.empty();e(H).then(function(e){var v,M;e=xa(e);if(r.replace){e=
|
||||
Vb.test(e)?$c(da(E,W(e))):[];v=e[0];if(1!=e.length||1!==v.nodeType)throw ga("tplrt",r.name,H);e={$attr:{}};ea(d,b,v);var B=$b(v,[],e);D(r.scope)&&T(B,!0);a=B.concat(a);$(c,e)}else v=n,b.html(e);a.unshift(u);m=oa(a,v,c,f,b,r,g,h,k);q(d,function(a,c){a==v&&(d[c]=b[0])});for(p=s(b[0].childNodes,f);l.length;){e=l.shift();M=l.shift();var t=l.shift(),I=l.shift(),B=b[0];if(!e.$$destroyed){if(M!==n){var P=M.className;k.hasElementTranscludeDirective&&r.replace||(B=Xb(v));ea(t,F(M),B);x(F(B),P)}M=m.transcludeOnThisElement?
|
||||
za(e,m.transclude,I):I;m(p,e,B,d,M)}}l=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(m.transcludeOnThisElement&&(a=za(b,m.transclude,e)),m(p,b,c,d,a)))}}function Z(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function X(a,b,c,d){function e(a){return a?" (module: "+a+")":""}if(b)throw ga("multidir",b.name,e(b.$$moduleName),c.name,e(c.$$moduleName),a,ya(d));}function ca(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=
|
||||
a.parent();var b=!!a.length;b&&aa.$$addBindingClass(a);return function(a,c){var e=c.parent();b||aa.$$addBindingClass(e);aa.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function da(a,b){a=Q(a||"html");switch(a){case "svg":case "math":var c=C.document.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function ha(a,b){if("srcdoc"==b)return M.HTML;var c=wa(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=
|
||||
c&&("src"==b||"ngSrc"==b))return M.RESOURCE_URL}function ia(a,c,d,e,f){var g=ha(a,e);f=k[e]||f;var h=b(d,!0,g,f);if(h){if("multiple"===e&&"select"===wa(a))throw ga("selmulti",ya(a));c.push({priority:100,compile:function(){return{pre:function(a,c,k){c=k.$$observers||(k.$$observers=U());if(m.test(e))throw ga("nodomevents");var l=k[e];l!==d&&(h=l&&b(l,!0,g,f),d=l);h&&(k[e]=h(a),(c[e]||(c[e]=[])).$$inter=!0,(k.$$observers&&k.$$observers[e].$$scope||a).$watch(h,function(a,b){"class"===e&&a!=b?k.$updateClass(a,
|
||||
b):k.$set(e,a)}))}}}})}}function ea(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var k=a.length;g<k;g++,h++)h<k?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=C.document.createDocumentFragment();for(g=0;g<e;g++)a.appendChild(b[g]);F.hasData(d)&&(F.data(c,F.data(d)),F(d).off("$destroy"));F.cleanData(a.querySelectorAll("*"));for(g=1;g<e;g++)delete b[g];b[0]=c;b.length=1}function ja(a,
|
||||
b){return S(function(){return a.apply(null,arguments)},a,b)}function la(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,ya(d))}}function ka(a,c,d,e,f){function g(b,c,e){z(d.$onChanges)&&c!==e&&(Y||(a.$$postDigest(I),Y=[]),m||(m={},Y.push(h)),m[b]&&(e=m[b].previousValue),m[b]=new Fb(e,c))}function h(){d.$onChanges(m);m=void 0}var k=[],l={},m;q(e,function(e,h){var m=e.attrName,p=e.optional,v,u,x,H;switch(e.mode){case "@":p||ua.call(c,m)||(d[h]=c[m]=void 0);c.$observe(m,function(a){if(G(a)||Ga(a))g(h,a,d[h]),
|
||||
d[h]=a});c.$$observers[m].$$scope=a;v=c[m];G(v)?d[h]=b(v)(a):Ga(v)&&(d[h]=v);l[h]=new Fb(bc,d[h]);break;case "=":if(!ua.call(c,m)){if(p)break;c[m]=void 0}if(p&&!c[m])break;u=n(c[m]);H=u.literal?na:function(a,b){return a===b||a!==a&&b!==b};x=u.assign||function(){v=d[h]=u(a);throw ga("nonassign",c[m],m,f.name);};v=d[h]=u(a);p=function(b){H(b,d[h])||(H(b,v)?x(a,b=d[h]):d[h]=b);return v=b};p.$stateful=!0;p=e.collection?a.$watchCollection(c[m],p):a.$watch(n(c[m],p),null,u.literal);k.push(p);break;case "<":if(!ua.call(c,
|
||||
m)){if(p)break;c[m]=void 0}if(p&&!c[m])break;u=n(c[m]);var E=d[h]=u(a);l[h]=new Fb(bc,d[h]);p=a.$watch(u,function(a,b){if(b===a){if(b===E)return;b=E}g(h,a,b);d[h]=a},u.literal);k.push(p);break;case "&":u=c.hasOwnProperty(m)?n(c[m]):A;if(u===A&&p)break;d[h]=function(b){return u(a,b)}}});return{initialChanges:l,removeWatches:k.length&&function(){for(var a=0,b=k.length;a<b;++a)k[a]()}}}var ta=/^\w/,pa=C.document.createElement("div"),qa=u,Y;Da.prototype={$normalize:Aa,$addClass:function(a){a&&0<a.length&&
|
||||
H.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&H.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=ad(a,b);c&&c.length&&H.addClass(this.$$element,c);(c=ad(b,a))&&c.length&&H.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=Uc(this.$$element[0],a),g=bd[a],h=a;f?(this.$$element.prop(a,b),e=f):g&&(this[g]=b,h=g);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=Cc(a,"-"));f=wa(this.$$element);if("a"===f&&("href"===a||"xlinkHref"===a)||"img"===
|
||||
f&&"src"===a)this[a]=b=E(b,"src"===a);else if("img"===f&&"srcset"===a&&w(b)){for(var f="",g=W(b),k=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,k=/\s/.test(g)?k:/(,)/,g=g.split(k),k=Math.floor(g.length/2),l=0;l<k;l++)var m=2*l,f=f+E(W(g[m]),!0),f=f+(" "+W(g[m+1]));g=W(g[2*l]).split(/\s/);f+=E(W(g[0]),!0);2===g.length&&(f+=" "+W(g[1]));this[a]=b=f}!1!==d&&(null===b||y(b)?this.$$element.removeAttr(e):ta.test(e)?this.$$element.attr(e,b):P(this.$$element[0],e,b));(a=this.$$observers)&&q(a[h],function(a){try{a(b)}catch(d){c(d)}})},
|
||||
$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=U()),e=d[a]||(d[a]=[]);e.push(b);K.$evalAsync(function(){e.$$inter||!c.hasOwnProperty(a)||y(c[a])||b(c[a])});return function(){Za(e,b)}}};var ra=b.startSymbol(),sa=b.endSymbol(),xa="{{"==ra&&"}}"==sa?Xa:function(a){return a.replace(/\{\{/g,ra).replace(/}}/g,sa)},Ba=/^ngAttr[A-Z]/,Ca=/^(.+)Start$/;aa.$$addBindingInfo=p?function(a,b){var c=a.data("$binding")||[];L(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:A;aa.$$addBindingClass=
|
||||
p?function(a){x(a,"ng-binding")}:A;aa.$$addScopeInfo=p?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:A;aa.$$addScopeClass=p?function(a,b){x(a,b?"ng-isolate-scope":"ng-scope")}:A;aa.$$createComment=function(a,b){var c="";p&&(c=" "+(a||"")+": ",b&&(c+=b+" "));return C.document.createComment(c)};return aa}]}function Fb(a,b){this.previousValue=a;this.currentValue=b}function Aa(a){return db(a.replace(Yc,""))}function ad(a,b){var d="",c=a.split(/\s+/),e=b.split(/\s+/),
|
||||
f=0;a:for(;f<c.length;f++){for(var g=c[f],h=0;h<e.length;h++)if(g==e[h])continue a;d+=(0<d.length?" ":"")+g}return d}function $c(a){a=F(a);var b=a.length;if(1>=b)return a;for(;b--;)8===a[b].nodeType&&bg.call(a,b,1);return a}function Xc(a,b){if(b&&G(b))return b;if(G(a)){var d=cd.exec(a);if(d)return d[3]}}function ff(){var a={},b=!1;this.has=function(b){return a.hasOwnProperty(b)};this.register=function(b,c){Qa(b,"controller");D(b)?S(a,b):a[b]=c};this.allowGlobals=function(){b=!0};this.$get=["$injector",
|
||||
"$window",function(d,c){function e(a,b,c,d){if(!a||!D(a.$scope))throw N("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,k){var l,m,n;h=!0===h;k&&G(k)&&(n=k);if(G(f)){k=f.match(cd);if(!k)throw cg("ctrlfmt",f);m=k[1];n=n||k[3];f=a.hasOwnProperty(m)?a[m]:Ec(g.$scope,m,!0)||(b?Ec(c,m,!0):void 0);Pa(f,m,!0)}if(h)return h=(L(f)?f[f.length-1]:f).prototype,l=Object.create(h||null),n&&e(g,n,l,m||f.name),S(function(){var a=d.invoke(f,l,g,m);a!==l&&(D(a)||z(a))&&(l=a,n&&e(g,n,l,m||f.name));return l},
|
||||
{instance:l,identifier:n});l=d.instantiate(f,g,m);n&&e(g,n,l,m||f.name);return l}}]}function gf(){this.$get=["$window",function(a){return F(a.document)}]}function hf(){this.$get=["$log",function(a){return function(b,d){a.error.apply(a,arguments)}}]}function cc(a){return D(a)?da(a)?a.toISOString():bb(a):a}function nf(){this.$get=function(){return function(a){if(!a)return"";var b=[];tc(a,function(a,c){null===a||y(a)||(L(a)?q(a,function(a){b.push(ea(c)+"="+ea(cc(a)))}):b.push(ea(c)+"="+ea(cc(a))))});
|
||||
return b.join("&")}}}function of(){this.$get=function(){return function(a){function b(a,e,f){null===a||y(a)||(L(a)?q(a,function(a,c){b(a,e+"["+(D(a)?c:"")+"]")}):D(a)&&!da(a)?tc(a,function(a,c){b(a,e+(f?"":"[")+c+(f?"":"]"))}):d.push(ea(e)+"="+ea(cc(a))))}if(!a)return"";var d=[];b(a,"",!0);return d.join("&")}}}function dc(a,b){if(G(a)){var d=a.replace(dg,"").trim();if(d){var c=b("Content-Type");(c=c&&0===c.indexOf(dd))||(c=(c=d.match(eg))&&fg[c[0]].test(d));c&&(a=xc(d))}}return a}function ed(a){var b=
|
||||
U(),d;G(a)?q(a.split("\n"),function(a){d=a.indexOf(":");var e=Q(W(a.substr(0,d)));a=W(a.substr(d+1));e&&(b[e]=b[e]?b[e]+", "+a:a)}):D(a)&&q(a,function(a,d){var f=Q(d),g=W(a);f&&(b[f]=b[f]?b[f]+", "+g:g)});return b}function fd(a){var b;return function(d){b||(b=ed(a));return d?(d=b[Q(d)],void 0===d&&(d=null),d):b}}function gd(a,b,d,c){if(z(c))return c(a,b,d);q(c,function(c){a=c(a,b,d)});return a}function mf(){var a=this.defaults={transformResponse:[dc],transformRequest:[function(a){return D(a)&&"[object File]"!==
|
||||
ma.call(a)&&"[object Blob]"!==ma.call(a)&&"[object FormData]"!==ma.call(a)?bb(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ia(ec),put:ia(ec),patch:ia(ec)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},b=!1;this.useApplyAsync=function(a){return w(a)?(b=!!a,this):b};var d=!0;this.useLegacyPromiseExtensions=function(a){return w(a)?(d=!!a,this):d};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory",
|
||||
"$rootScope","$q","$injector",function(e,f,g,h,k,l){function m(b){function c(a,b){for(var d=0,e=b.length;d<e;){var f=b[d++],g=b[d++];a=a.then(f,g)}b.length=0;return a}function e(a,b){var c,d={};q(a,function(a,e){z(a)?(c=a(b),null!=c&&(d[e]=c)):d[e]=a});return d}function f(a){var b=S({},a);b.data=gd(a.data,a.headers,a.status,g.transformResponse);a=a.status;return 200<=a&&300>a?b:k.reject(b)}if(!D(b))throw N("$http")("badreq",b);if(!G(b.url))throw N("$http")("badreq",b.url);var g=S({method:"get",transformRequest:a.transformRequest,
|
||||
transformResponse:a.transformResponse,paramSerializer:a.paramSerializer},b);g.headers=function(b){var c=a.headers,d=S({},b.headers),f,g,h,c=S({},c.common,c[Q(b.method)]);a:for(f in c){g=Q(f);for(h in d)if(Q(h)===g)continue a;d[f]=c[f]}return e(d,ia(b))}(b);g.method=ub(g.method);g.paramSerializer=G(g.paramSerializer)?l.get(g.paramSerializer):g.paramSerializer;var h=[],m=[],p=k.when(g);q(R,function(a){(a.request||a.requestError)&&h.unshift(a.request,a.requestError);(a.response||a.responseError)&&m.push(a.response,
|
||||
a.responseError)});p=c(p,h);p=p.then(function(b){var c=b.headers,d=gd(b.data,fd(c),void 0,b.transformRequest);y(d)&&q(c,function(a,b){"content-type"===Q(b)&&delete c[b]});y(b.withCredentials)&&!y(a.withCredentials)&&(b.withCredentials=a.withCredentials);return n(b,d).then(f,f)});p=c(p,m);d?(p.success=function(a){Pa(a,"fn");p.then(function(b){a(b.data,b.status,b.headers,g)});return p},p.error=function(a){Pa(a,"fn");p.then(null,function(b){a(b.data,b.status,b.headers,g)});return p}):(p.success=hd("success"),
|
||||
p.error=hd("error"));return p}function n(c,d){function g(a){if(a){var c={};q(a,function(a,d){c[d]=function(c){function d(){a(c)}b?h.$applyAsync(d):h.$$phase?d():h.$apply(d)}});return c}}function l(a,c,d,e){function f(){n(c,a,d,e)}E&&(200<=a&&300>a?E.put(P,[a,c,ed(d),e]):E.remove(P));b?h.$applyAsync(f):(f(),h.$$phase||h.$apply())}function n(a,b,d,e){b=-1<=b?b:0;(200<=b&&300>b?M.resolve:M.reject)({data:a,status:b,headers:fd(d),config:c,statusText:e})}function t(a){n(a.data,a.status,ia(a.headers()),
|
||||
a.statusText)}function R(){var a=m.pendingRequests.indexOf(c);-1!==a&&m.pendingRequests.splice(a,1)}var M=k.defer(),H=M.promise,E,I,Da=c.headers,P=p(c.url,c.paramSerializer(c.params));m.pendingRequests.push(c);H.then(R,R);!c.cache&&!a.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(E=D(c.cache)?c.cache:D(a.cache)?a.cache:u);E&&(I=E.get(P),w(I)?I&&z(I.then)?I.then(t,t):L(I)?n(I[1],I[0],ia(I[2]),I[3]):n(I,200,{},"OK"):E.put(P,H));y(I)&&((I=id(c.url)?f()[c.xsrfCookieName||a.xsrfCookieName]:
|
||||
void 0)&&(Da[c.xsrfHeaderName||a.xsrfHeaderName]=I),e(c.method,P,d,l,Da,c.timeout,c.withCredentials,c.responseType,g(c.eventHandlers),g(c.uploadEventHandlers)));return H}function p(a,b){0<b.length&&(a+=(-1==a.indexOf("?")?"?":"&")+b);return a}var u=g("$http");a.paramSerializer=G(a.paramSerializer)?l.get(a.paramSerializer):a.paramSerializer;var R=[];q(c,function(a){R.unshift(G(a)?l.get(a):l.invoke(a))});m.pendingRequests=[];(function(a){q(arguments,function(a){m[a]=function(b,c){return m(S({},c||{},
|
||||
{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){q(arguments,function(a){m[a]=function(b,c,d){return m(S({},d||{},{method:a,url:b,data:c}))}})})("post","put","patch");m.defaults=a;return m}]}function qf(){this.$get=function(){return function(){return new C.XMLHttpRequest}}}function pf(){this.$get=["$browser","$jsonpCallbacks","$document","$xhrFactory",function(a,b,d,c){return gg(a,c,a.defer,b,d[0])}]}function gg(a,b,d,c,e){function f(a,b,d){a=a.replace("JSON_CALLBACK",b);var f=
|
||||
e.createElement("script"),m=null;f.type="text/javascript";f.src=a;f.async=!0;m=function(a){f.removeEventListener("load",m,!1);f.removeEventListener("error",m,!1);e.body.removeChild(f);f=null;var g=-1,u="unknown";a&&("load"!==a.type||c.wasCalled(b)||(a={type:"error"}),u=a.type,g="error"===a.type?404:200);d&&d(g,u)};f.addEventListener("load",m,!1);f.addEventListener("error",m,!1);e.body.appendChild(f);return m}return function(e,h,k,l,m,n,p,u,R,B){function r(){fa&&fa();t&&t.abort()}function J(b,c,e,
|
||||
f,g){w(M)&&d.cancel(M);fa=t=null;b(c,e,f,g);a.$$completeOutstandingRequest(A)}a.$$incOutstandingRequestCount();h=h||a.url();if("jsonp"===Q(e))var v=c.createCallback(h),fa=f(h,v,function(a,b){var d=200===a&&c.getResponse(v);J(l,a,d,"",b);c.removeCallback(v)});else{var t=b(e,h);t.open(e,h,!0);q(m,function(a,b){w(a)&&t.setRequestHeader(b,a)});t.onload=function(){var a=t.statusText||"",b="response"in t?t.response:t.responseText,c=1223===t.status?204:t.status;0===c&&(c=b?200:"file"==Y(h).protocol?404:
|
||||
0);J(l,c,b,t.getAllResponseHeaders(),a)};e=function(){J(l,-1,null,null,"")};t.onerror=e;t.onabort=e;q(R,function(a,b){t.addEventListener(b,a)});q(B,function(a,b){t.upload.addEventListener(b,a)});p&&(t.withCredentials=!0);if(u)try{t.responseType=u}catch(K){if("json"!==u)throw K;}t.send(y(k)?null:k)}if(0<n)var M=d(r,n);else n&&z(n.then)&&n.then(r)}}function kf(){var a="{{",b="}}";this.startSymbol=function(b){return b?(a=b,this):a};this.endSymbol=function(a){return a?(b=a,this):b};this.$get=["$parse",
|
||||
"$exceptionHandler","$sce",function(d,c,e){function f(a){return"\\\\\\"+a}function g(c){return c.replace(n,a).replace(p,b)}function h(a,b,c,d){var e;return e=a.$watch(function(a){e();return d(a)},b,c)}function k(f,k,p,n){function J(a){try{var b=a;a=p?e.getTrusted(p,b):e.valueOf(b);var d;if(n&&!w(a))d=a;else if(null==a)d="";else{switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=bb(a)}d=a}return d}catch(g){c(Ka.interr(f,g))}}if(!f.length||-1===f.indexOf(a)){var v;k||(k=g(f),
|
||||
v=ha(k),v.exp=f,v.expressions=[],v.$$watchDelegate=h);return v}n=!!n;var q,t,K=0,M=[],H=[];v=f.length;for(var E=[],I=[];K<v;)if(-1!=(q=f.indexOf(a,K))&&-1!=(t=f.indexOf(b,q+l)))K!==q&&E.push(g(f.substring(K,q))),K=f.substring(q+l,t),M.push(K),H.push(d(K,J)),K=t+m,I.push(E.length),E.push("");else{K!==v&&E.push(g(f.substring(K)));break}p&&1<E.length&&Ka.throwNoconcat(f);if(!k||M.length){var Da=function(a){for(var b=0,c=M.length;b<c;b++){if(n&&y(a[b]))return;E[I[b]]=a[b]}return E.join("")};return S(function(a){var b=
|
||||
0,d=M.length,e=Array(d);try{for(;b<d;b++)e[b]=H[b](a);return Da(e)}catch(g){c(Ka.interr(f,g))}},{exp:f,expressions:M,$$watchDelegate:function(a,b){var c;return a.$watchGroup(H,function(d,e){var f=Da(d);z(b)&&b.call(this,f,d!==e?c:f,a);c=f})}})}}var l=a.length,m=b.length,n=new RegExp(a.replace(/./g,f),"g"),p=new RegExp(b.replace(/./g,f),"g");k.startSymbol=function(){return a};k.endSymbol=function(){return b};return k}]}function lf(){this.$get=["$rootScope","$window","$q","$$q","$browser",function(a,
|
||||
b,d,c,e){function f(f,k,l,m){function n(){p?f.apply(null,u):f(r)}var p=4<arguments.length,u=p?va.call(arguments,4):[],R=b.setInterval,q=b.clearInterval,r=0,J=w(m)&&!m,v=(J?c:d).defer(),fa=v.promise;l=w(l)?l:0;fa.$$intervalId=R(function(){J?e.defer(n):a.$evalAsync(n);v.notify(r++);0<l&&r>=l&&(v.resolve(r),q(fa.$$intervalId),delete g[fa.$$intervalId]);J||a.$apply()},k);g[fa.$$intervalId]=v;return fa}var g={};f.cancel=function(a){return a&&a.$$intervalId in g?(g[a.$$intervalId].reject("canceled"),b.clearInterval(a.$$intervalId),
|
||||
delete g[a.$$intervalId],!0):!1};return f}]}function fc(a){a=a.split("/");for(var b=a.length;b--;)a[b]=qb(a[b]);return a.join("/")}function jd(a,b){var d=Y(a);b.$$protocol=d.protocol;b.$$host=d.hostname;b.$$port=Z(d.port)||hg[d.protocol]||null}function kd(a,b){var d="/"!==a.charAt(0);d&&(a="/"+a);var c=Y(a);b.$$path=decodeURIComponent(d&&"/"===c.pathname.charAt(0)?c.pathname.substring(1):c.pathname);b.$$search=Ac(c.search);b.$$hash=decodeURIComponent(c.hash);b.$$path&&"/"!=b.$$path.charAt(0)&&(b.$$path=
|
||||
"/"+b.$$path)}function ka(a,b){if(0===b.lastIndexOf(a,0))return b.substr(a.length)}function Ja(a){var b=a.indexOf("#");return-1==b?a:a.substr(0,b)}function jb(a){return a.replace(/(#.+)|#$/,"$1")}function gc(a,b,d){this.$$html5=!0;d=d||"";jd(a,this);this.$$parse=function(a){var d=ka(b,a);if(!G(d))throw Gb("ipthprfx",a,b);kd(d,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Tb(this.$$search),d=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=fc(this.$$path)+(a?"?"+
|
||||
a:"")+d;this.$$absUrl=b+this.$$url.substr(1)};this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;w(f=ka(a,c))?(g=f,g=w(f=ka(d,f))?b+(ka("/",f)||f):a+g):w(f=ka(b,c))?g=b+f:b==c+"/"&&(g=b);g&&this.$$parse(g);return!!g}}function hc(a,b,d){jd(a,this);this.$$parse=function(c){var e=ka(a,c)||ka(b,c),f;y(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",y(e)&&(a=c,this.replace())):(f=ka(d,e),y(f)&&(f=e));kd(f,this);c=this.$$path;var e=a,g=/^\/[A-Z]:(\/.*)/;0===f.lastIndexOf(e,
|
||||
0)&&(f=f.replace(e,""));g.exec(f)||(c=(f=g.exec(c))?f[1]:c);this.$$path=c;this.$$compose()};this.$$compose=function(){var b=Tb(this.$$search),e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=fc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+(this.$$url?d+this.$$url:"")};this.$$parseLinkUrl=function(b,d){return Ja(a)==Ja(b)?(this.$$parse(b),!0):!1}}function ld(a,b,d){this.$$html5=!0;hc.apply(this,arguments);this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;a==Ja(c)?
|
||||
f=c:(g=ka(b,c))?f=a+d+g:b===c+"/"&&(f=b);f&&this.$$parse(f);return!!f};this.$$compose=function(){var b=Tb(this.$$search),e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=fc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+d+this.$$url}}function Hb(a){return function(){return this[a]}}function md(a,b){return function(d){if(y(d))return this[a];this[a]=b(d);this.$$compose();return this}}function sf(){var a="",b={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(b){return w(b)?(a=b,this):
|
||||
a};this.html5Mode=function(a){return Ga(a)?(b.enabled=a,this):D(a)?(Ga(a.enabled)&&(b.enabled=a.enabled),Ga(a.requireBase)&&(b.requireBase=a.requireBase),Ga(a.rewriteLinks)&&(b.rewriteLinks=a.rewriteLinks),this):b};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(d,c,e,f,g){function h(a,b,d){var e=l.url(),f=l.$$state;try{c.url(a,b,d),l.$$state=c.state()}catch(g){throw l.url(e),l.$$state=f,g;}}function k(a,b){d.$broadcast("$locationChangeSuccess",l.absUrl(),a,l.$$state,
|
||||
b)}var l,m;m=c.baseHref();var n=c.url(),p;if(b.enabled){if(!m&&b.requireBase)throw Gb("nobase");p=n.substring(0,n.indexOf("/",n.indexOf("//")+2))+(m||"/");m=e.history?gc:ld}else p=Ja(n),m=hc;var u=p.substr(0,Ja(p).lastIndexOf("/")+1);l=new m(p,u,"#"+a);l.$$parseLinkUrl(n,n);l.$$state=c.state();var R=/^\s*(javascript|mailto):/i;f.on("click",function(a){if(b.rewriteLinks&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&2!=a.which&&2!=a.button){for(var e=F(a.target);"a"!==wa(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;
|
||||
var h=e.prop("href"),k=e.attr("href")||e.attr("xlink:href");D(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Y(h.animVal).href);R.test(h)||!h||e.attr("target")||a.isDefaultPrevented()||!l.$$parseLinkUrl(h,k)||(a.preventDefault(),l.absUrl()!=c.url()&&(d.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});jb(l.absUrl())!=jb(n)&&c.url(l.absUrl(),!0);var q=!0;c.onUrlChange(function(a,b){y(ka(u,a))?g.location.href=a:(d.$evalAsync(function(){var c=l.absUrl(),e=l.$$state,f;a=jb(a);l.$$parse(a);l.$$state=
|
||||
b;f=d.$broadcast("$locationChangeStart",a,c,b,e).defaultPrevented;l.absUrl()===a&&(f?(l.$$parse(c),l.$$state=e,h(c,!1,e)):(q=!1,k(c,e)))}),d.$$phase||d.$digest())});d.$watch(function(){var a=jb(c.url()),b=jb(l.absUrl()),f=c.state(),g=l.$$replace,m=a!==b||l.$$html5&&e.history&&f!==l.$$state;if(q||m)q=!1,d.$evalAsync(function(){var b=l.absUrl(),c=d.$broadcast("$locationChangeStart",b,a,l.$$state,f).defaultPrevented;l.absUrl()===b&&(c?(l.$$parse(a),l.$$state=f):(m&&h(b,g,f===l.$$state?null:l.$$state),
|
||||
k(a,f)))});l.$$replace=!1});return l}]}function tf(){var a=!0,b=this;this.debugEnabled=function(b){return w(b)?(a=b,this):a};this.$get=["$window",function(d){function c(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=d.console||{},e=b[a]||b.log||A;a=!1;try{a=!!e.apply}catch(k){}return a?function(){var a=[];q(arguments,function(b){a.push(c(b))});
|
||||
return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){a&&c.apply(b,arguments)}}()}}]}function Sa(a,b){if("__defineGetter__"===a||"__defineSetter__"===a||"__lookupGetter__"===a||"__lookupSetter__"===a||"__proto__"===a)throw X("isecfld",b);return a}function ig(a){return a+""}function ra(a,b){if(a){if(a.constructor===a)throw X("isecfn",b);if(a.window===a)throw X("isecwindow",b);if(a.children&&
|
||||
(a.nodeName||a.prop&&a.attr&&a.find))throw X("isecdom",b);if(a===Object)throw X("isecobj",b);}return a}function nd(a,b){if(a){if(a.constructor===a)throw X("isecfn",b);if(a===jg||a===kg||a===lg)throw X("isecff",b);}}function Ib(a,b){if(a&&(a===(0).constructor||a===(!1).constructor||a==="".constructor||a==={}.constructor||a===[].constructor||a===Function.constructor))throw X("isecaf",b);}function mg(a,b){return"undefined"!==typeof a?a:b}function od(a,b){return"undefined"===typeof a?b:"undefined"===
|
||||
typeof b?a:a+b}function V(a,b){var d,c;switch(a.type){case s.Program:d=!0;q(a.body,function(a){V(a.expression,b);d=d&&a.expression.constant});a.constant=d;break;case s.Literal:a.constant=!0;a.toWatch=[];break;case s.UnaryExpression:V(a.argument,b);a.constant=a.argument.constant;a.toWatch=a.argument.toWatch;break;case s.BinaryExpression:V(a.left,b);V(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.left.toWatch.concat(a.right.toWatch);break;case s.LogicalExpression:V(a.left,b);V(a.right,
|
||||
b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.constant?[]:[a];break;case s.ConditionalExpression:V(a.test,b);V(a.alternate,b);V(a.consequent,b);a.constant=a.test.constant&&a.alternate.constant&&a.consequent.constant;a.toWatch=a.constant?[]:[a];break;case s.Identifier:a.constant=!1;a.toWatch=[a];break;case s.MemberExpression:V(a.object,b);a.computed&&V(a.property,b);a.constant=a.object.constant&&(!a.computed||a.property.constant);a.toWatch=[a];break;case s.CallExpression:d=a.filter?!b(a.callee.name).$stateful:
|
||||
!1;c=[];q(a.arguments,function(a){V(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=a.filter&&!b(a.callee.name).$stateful?c:[a];break;case s.AssignmentExpression:V(a.left,b);V(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=[a];break;case s.ArrayExpression:d=!0;c=[];q(a.elements,function(a){V(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=c;break;case s.ObjectExpression:d=!0;c=[];q(a.properties,function(a){V(a.value,
|
||||
b);d=d&&a.value.constant&&!a.computed;a.value.constant||c.push.apply(c,a.value.toWatch)});a.constant=d;a.toWatch=c;break;case s.ThisExpression:a.constant=!1;a.toWatch=[];break;case s.LocalsExpression:a.constant=!1,a.toWatch=[]}}function pd(a){if(1==a.length){a=a[0].expression;var b=a.toWatch;return 1!==b.length?b:b[0]!==a?b:void 0}}function qd(a){return a.type===s.Identifier||a.type===s.MemberExpression}function rd(a){if(1===a.body.length&&qd(a.body[0].expression))return{type:s.AssignmentExpression,
|
||||
left:a.body[0].expression,right:{type:s.NGValueParameter},operator:"="}}function sd(a){return 0===a.body.length||1===a.body.length&&(a.body[0].expression.type===s.Literal||a.body[0].expression.type===s.ArrayExpression||a.body[0].expression.type===s.ObjectExpression)}function td(a,b){this.astBuilder=a;this.$filter=b}function ud(a,b){this.astBuilder=a;this.$filter=b}function Jb(a){return"constructor"==a}function ic(a){return z(a.valueOf)?a.valueOf():ng.call(a)}function uf(){var a=U(),b=U(),d={"true":!0,
|
||||
"false":!1,"null":null,undefined:void 0},c,e;this.addLiteral=function(a,b){d[a]=b};this.setIdentifierFns=function(a,b){c=a;e=b;return this};this.$get=["$filter",function(f){function g(c,d,e){var g,k,H;e=e||J;switch(typeof c){case "string":H=c=c.trim();var E=e?b:a;g=E[H];if(!g){":"===c.charAt(0)&&":"===c.charAt(1)&&(k=!0,c=c.substring(2));g=e?r:B;var q=new jc(g);g=(new kc(q,f,g)).parse(c);g.constant?g.$$watchDelegate=p:k?g.$$watchDelegate=g.literal?n:m:g.inputs&&(g.$$watchDelegate=l);e&&(g=h(g));E[H]=
|
||||
g}return u(g,d);case "function":return u(c,d);default:return u(A,d)}}function h(a){function b(c,d,e,f){var g=J;J=!0;try{return a(c,d,e,f)}finally{J=g}}if(!a)return a;b.$$watchDelegate=a.$$watchDelegate;b.assign=h(a.assign);b.constant=a.constant;b.literal=a.literal;for(var c=0;a.inputs&&c<a.inputs.length;++c)a.inputs[c]=h(a.inputs[c]);b.inputs=a.inputs;return b}function k(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=ic(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function l(a,b,c,d,
|
||||
e){var f=d.inputs,g;if(1===f.length){var h=k,f=f[0];return a.$watch(function(a){var b=f(a);k(b,h)||(g=d(a,void 0,void 0,[b]),h=b&&ic(b));return g},b,c,e)}for(var l=[],m=[],p=0,n=f.length;p<n;p++)l[p]=k,m[p]=null;return a.$watch(function(a){for(var b=!1,c=0,e=f.length;c<e;c++){var h=f[c](a);if(b||(b=!k(h,l[c])))m[c]=h,l[c]=h&&ic(h)}b&&(g=d(a,void 0,void 0,m));return g},b,c,e)}function m(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;z(b)&&b.apply(this,arguments);w(a)&&
|
||||
d.$$postDigest(function(){w(f)&&e()})},c)}function n(a,b,c,d){function e(a){var b=!0;q(a,function(a){w(a)||(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;z(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function p(a,b,c,d){var e;return e=a.$watch(function(a){e();return d(a)},b,c)}function u(a,b){if(!b)return a;var c=a.$$watchDelegate,d=!1,c=c!==n&&c!==m?function(c,e,f,g){f=d&&g?g[0]:a(c,e,f,g);return b(f,c,e)}:function(c,d,e,f){e=a(c,
|
||||
d,e,f);c=b(e,c,d);return w(e)?c:e};a.$$watchDelegate&&a.$$watchDelegate!==l?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=l,d=!a.inputs,c.inputs=a.inputs?a.inputs:[a]);return c}var R=Ba().noUnsafeEval,B={csp:R,expensiveChecks:!1,literals:pa(d),isIdentifierStart:z(c)&&c,isIdentifierContinue:z(e)&&e},r={csp:R,expensiveChecks:!0,literals:pa(d),isIdentifierStart:z(c)&&c,isIdentifierContinue:z(e)&&e},J=!1;g.$$runningExpensiveChecks=function(){return J};return g}]}function wf(){this.$get=
|
||||
["$rootScope","$exceptionHandler",function(a,b){return vd(function(b){a.$evalAsync(b)},b)}]}function xf(){this.$get=["$browser","$exceptionHandler",function(a,b){return vd(function(b){a.defer(b)},b)}]}function vd(a,b){function d(){this.$$state={status:0}}function c(a,b){return function(c){b.call(a,c)}}function e(c){!c.processScheduled&&c.pending&&(c.processScheduled=!0,a(function(){var a,d,e;e=c.pending;c.processScheduled=!1;c.pending=void 0;for(var f=0,g=e.length;f<g;++f){d=e[f][0];a=e[f][c.status];
|
||||
try{z(a)?d.resolve(a(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),b(h)}}}))}function f(){this.promise=new d}var g=N("$q",TypeError),h=function(){var a=new f;a.resolve=c(a,a.resolve);a.reject=c(a,a.reject);a.notify=c(a,a.notify);return a};S(d.prototype,{then:function(a,b,c){if(y(a)&&y(b)&&y(c))return this;var d=new f;this.$$state.pending=this.$$state.pending||[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&e(this.$$state);return d.promise},"catch":function(a){return this.then(null,
|
||||
a)},"finally":function(a,b){return this.then(function(b){return l(b,!0,a)},function(b){return l(b,!1,a)},b)}});S(f.prototype,{resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(g("qcycle",a)):this.$$resolve(a))},$$resolve:function(a){function d(a){k||(k=!0,h.$$resolve(a))}function f(a){k||(k=!0,h.$$reject(a))}var g,h=this,k=!1;try{if(D(a)||z(a))g=a&&a.then;z(g)?(this.promise.$$state.status=-1,g.call(a,d,f,c(this,this.notify))):(this.promise.$$state.value=a,this.promise.$$state.status=
|
||||
1,e(this.promise.$$state))}catch(l){f(l),b(l)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;e(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&a(function(){for(var a,e,f=0,g=d.length;f<g;f++){e=d[f][0];a=d[f][3];try{e.notify(z(a)?a(c):c)}catch(h){b(h)}}})}});var k=function(a,b){var c=new f;b?c.resolve(a):c.reject(a);return c.promise},
|
||||
l=function(a,b,c){var d=null;try{z(c)&&(d=c())}catch(e){return k(e,!1)}return d&&z(d.then)?d.then(function(){return k(a,b)},function(a){return k(a,!1)}):k(a,b)},m=function(a,b,c,d){var e=new f;e.resolve(a);return e.promise.then(b,c,d)},n=function(a){if(!z(a))throw g("norslvr",a);var b=new f;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};n.prototype=d.prototype;n.defer=h;n.reject=function(a){var b=new f;b.reject(a);return b.promise};n.when=m;n.resolve=m;n.all=function(a){var b=
|
||||
new f,c=0,d=L(a)?[]:{};q(a,function(a,e){c++;m(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};n.race=function(a){var b=h();q(a,function(a){m(a).then(b.resolve,b.reject)});return b.promise};return n}function Gf(){this.$get=["$window","$timeout",function(a,b){var d=a.requestAnimationFrame||a.webkitRequestAnimationFrame,c=a.cancelAnimationFrame||a.webkitCancelAnimationFrame||a.webkitCancelRequestAnimationFrame,
|
||||
e=!!d,f=e?function(a){var b=d(a);return function(){c(b)}}:function(a){var c=b(a,16.66,!1);return function(){b.cancel(c)}};f.supported=e;return f}]}function vf(){function a(a){function b(){this.$$watchers=this.$$nextSibling=this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$id=++pb;this.$$ChildScope=null}b.prototype=a;return b}var b=10,d=N("$rootScope"),c=null,e=null;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=
|
||||
["$exceptionHandler","$parse","$browser",function(f,g,h){function k(a){a.currentScope.$$destroyed=!0}function l(a){9===Ea&&(a.$$childHead&&l(a.$$childHead),a.$$nextSibling&&l(a.$$nextSibling));a.$parent=a.$$nextSibling=a.$$prevSibling=a.$$childHead=a.$$childTail=a.$root=a.$$watchers=null}function m(){this.$id=++pb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount=
|
||||
{};this.$$watchersCount=0;this.$$isolateBindings=null}function n(a){if(J.$$phase)throw d("inprog",J.$$phase);J.$$phase=a}function p(a,b){do a.$$watchersCount+=b;while(a=a.$parent)}function u(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function s(){}function B(){for(;t.length;)try{t.shift()()}catch(a){f(a)}e=null}function r(){null===e&&(e=h.defer(function(){J.$apply(B)}))}m.prototype={constructor:m,$new:function(b,c){var d;c=c||this;b?
|
||||
(d=new m,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=a(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(b||c!=this)&&d.$on("$destroy",k);return d},$watch:function(a,b,d,e){var f=g(a);if(f.$$watchDelegate)return f.$$watchDelegate(this,b,d,f,a);var h=this,k=h.$$watchers,l={fn:b,last:s,get:f,exp:e||a,eq:!!d};c=null;z(b)||(l.fn=A);k||(k=h.$$watchers=[]);k.unshift(l);p(this,
|
||||
1);return function(){0<=Za(k,l)&&p(h,-1);c=null}},$watchGroup:function(a,b){function c(){h=!1;k?(k=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,k=!0;if(!a.length){var l=!0;g.$evalAsync(function(){l&&b(e,e,g)});return function(){l=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});q(a,function(a,b){var k=g.$watch(a,function(a,f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(k)});return function(){for(;f.length;)f.shift()()}},
|
||||
$watchCollection:function(a,b){function c(a){e=a;var b,d,g,h;if(!y(e)){if(D(e))if(ta(e))for(f!==n&&(f=n,u=f.length=0,l++),a=e.length,u!==a&&(l++,f.length=u=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(l++,f[b]=g);else{f!==p&&(f=p={},u=0,l++);a=0;for(b in e)ua.call(e,b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(l++,f[b]=g)):(u++,f[b]=g,l++));if(u>a)for(b in l++,f)ua.call(e,b)||(u--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,h,k=1<b.length,l=0,m=
|
||||
g(a,c),n=[],p={},r=!0,u=0;return this.$watch(m,function(){r?(r=!1,b(e,e,d)):b(e,h,d);if(k)if(D(e))if(ta(e)){h=Array(e.length);for(var a=0;a<e.length;a++)h[a]=e[a]}else for(a in h={},e)ua.call(e,a)&&(h[a]=e[a]);else h=e})},$digest:function(){var a,g,k,l,m,p,u,r,q=b,t,y=[],A,C;n("$digest");h.$$checkUrlChange();this===J&&null!==e&&(h.defer.cancel(e),B());c=null;do{r=!1;t=this;for(p=0;p<v.length;p++){try{C=v[p],C.scope.$eval(C.expression,C.locals)}catch(F){f(F)}c=null}v.length=0;a:do{if(p=t.$$watchers)for(u=
|
||||
p.length;u--;)try{if(a=p[u])if(m=a.get,(g=m(t))!==(k=a.last)&&!(a.eq?na(g,k):"number"===typeof g&&"number"===typeof k&&isNaN(g)&&isNaN(k)))r=!0,c=a,a.last=a.eq?pa(g,null):g,l=a.fn,l(g,k===s?g:k,t),5>q&&(A=4-q,y[A]||(y[A]=[]),y[A].push({msg:z(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):a.exp,newVal:g,oldVal:k}));else if(a===c){r=!1;break a}}catch(G){f(G)}if(!(p=t.$$watchersCount&&t.$$childHead||t!==this&&t.$$nextSibling))for(;t!==this&&!(p=t.$$nextSibling);)t=t.$parent}while(t=p);if((r||v.length)&&
|
||||
!q--)throw J.$$phase=null,d("infdig",b,y);}while(r||v.length);for(J.$$phase=null;K<w.length;)try{w[K++]()}catch(D){f(D)}w.length=K=0},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===J&&h.$$applicationDestroyed();p(this,-this.$$watchersCount);for(var b in this.$$listenerCount)u(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&
|
||||
(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=A;this.$on=this.$watch=this.$watchGroup=function(){return A};this.$$listeners={};this.$$nextSibling=null;l(this)}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a,b){J.$$phase||v.length||h.defer(function(){v.length&&J.$digest()});v.push({scope:this,expression:g(a),locals:b})},$$postDigest:function(a){w.push(a)},
|
||||
$apply:function(a){try{n("$apply");try{return this.$eval(a)}finally{J.$$phase=null}}catch(b){f(b)}finally{try{J.$digest()}catch(c){throw f(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&t.push(b);a=g(a);r()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,u(e,1,a))}},$emit:function(a,
|
||||
b){var c=[],d,e=this,g=!1,h={name:a,targetScope:e,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=$a([h],arguments,1),l,m;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(m=d.length;l<m;l++)if(d[l])try{d[l].apply(null,k)}catch(n){f(n)}else d.splice(l,1),l--,m--;if(g)return h.currentScope=null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=
|
||||
!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var g=$a([e],arguments,1),h,k;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,g)}catch(l){f(l)}else d.splice(h,1),h--,k--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var J=new m,v=J.$$asyncQueue=[],w=J.$$postDigestQueue=[],t=J.$$applyAsyncQueue=[],K=0;return J}]}function ne(){var a=
|
||||
/^\s*(https?|ftp|mailto|tel|file):/,b=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(b){return w(b)?(a=b,this):a};this.imgSrcSanitizationWhitelist=function(a){return w(a)?(b=a,this):b};this.$get=function(){return function(d,c){var e=c?b:a,f;f=Y(d).href;return""===f||f.match(e)?d:"unsafe:"+f}}}function og(a){if("self"===a)return a;if(G(a)){if(-1<a.indexOf("***"))throw sa("iwcard",a);a=wd(a).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+
|
||||
a+"$")}if(Wa(a))return new RegExp("^"+a.source+"$");throw sa("imatcher");}function xd(a){var b=[];w(a)&&q(a,function(a){b.push(og(a))});return b}function zf(){this.SCE_CONTEXTS=la;var a=["self"],b=[];this.resourceUrlWhitelist=function(b){arguments.length&&(a=xd(b));return a};this.resourceUrlBlacklist=function(a){arguments.length&&(b=xd(a));return b};this.$get=["$injector",function(d){function c(a,b){return"self"===a?id(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=
|
||||
function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw sa("unsafe");};d.has("$sanitize")&&(f=d.get("$sanitize"));var g=e(),h={};h[la.HTML]=e(g);h[la.CSS]=e(g);h[la.URL]=e(g);h[la.JS]=e(g);h[la.RESOURCE_URL]=e(h[la.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw sa("icontext",a,b);if(null===b||y(b)||
|
||||
""===b)return b;if("string"!==typeof b)throw sa("itype",a);return new c(b)},getTrusted:function(d,e){if(null===e||y(e)||""===e)return e;var g=h.hasOwnProperty(d)?h[d]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(d===la.RESOURCE_URL){var g=Y(e.toString()),n,p,u=!1;n=0;for(p=a.length;n<p;n++)if(c(a[n],g)){u=!0;break}if(u)for(n=0,p=b.length;n<p;n++)if(c(b[n],g)){u=!1;break}if(u)return e;throw sa("insecurl",e.toString());}if(d===la.HTML)return f(e);throw sa("unsafe");},valueOf:function(a){return a instanceof
|
||||
g?a.$$unwrapTrustedValue():a}}}]}function yf(){var a=!0;this.enabled=function(b){arguments.length&&(a=!!b);return a};this.$get=["$parse","$sceDelegate",function(b,d){if(a&&8>Ea)throw sa("iequirks");var c=ia(la);c.isEnabled=function(){return a};c.trustAs=d.trustAs;c.getTrusted=d.getTrusted;c.valueOf=d.valueOf;a||(c.trustAs=c.getTrusted=function(a,b){return b},c.valueOf=Xa);c.parseAs=function(a,d){var e=b(d);return e.literal&&e.constant?e:b(d,function(b){return c.getTrusted(a,b)})};var e=c.parseAs,
|
||||
f=c.getTrusted,g=c.trustAs;q(la,function(a,b){var d=Q(b);c[db("parse_as_"+d)]=function(b){return e(a,b)};c[db("get_trusted_"+d)]=function(b){return f(a,b)};c[db("trust_as_"+d)]=function(b){return g(a,b)}});return c}]}function Af(){this.$get=["$window","$document",function(a,b){var d={},c=!(a.chrome&&a.chrome.app&&a.chrome.app.runtime)&&a.history&&a.history.pushState,e=Z((/android (\d+)/.exec(Q((a.navigator||{}).userAgent))||[])[1]),f=/Boxee/i.test((a.navigator||{}).userAgent),g=b[0]||{},h,k=/^(Moz|webkit|ms)(?=[A-Z])/,
|
||||
l=g.body&&g.body.style,m=!1,n=!1;if(l){for(var p in l)if(m=k.exec(p)){h=m[0];h=h[0].toUpperCase()+h.substr(1);break}h||(h="WebkitOpacity"in l&&"webkit");m=!!("transition"in l||h+"Transition"in l);n=!!("animation"in l||h+"Animation"in l);!e||m&&n||(m=G(l.webkitTransition),n=G(l.webkitAnimation))}return{history:!(!c||4>e||f),hasEvent:function(a){if("input"===a&&11>=Ea)return!1;if(y(d[a])){var b=g.createElement("div");d[a]="on"+a in b}return d[a]},csp:Ba(),vendorPrefix:h,transitions:m,animations:n,android:e}}]}
|
||||
function Cf(){var a;this.httpOptions=function(b){return b?(a=b,this):a};this.$get=["$templateCache","$http","$q","$sce",function(b,d,c,e){function f(g,h){f.totalPendingRequests++;if(!G(g)||y(b.get(g)))g=e.getTrustedResourceUrl(g);var k=d.defaults&&d.defaults.transformResponse;L(k)?k=k.filter(function(a){return a!==dc}):k===dc&&(k=null);return d.get(g,S({cache:b,transformResponse:k},a))["finally"](function(){f.totalPendingRequests--}).then(function(a){b.put(g,a.data);return a.data},function(a){if(!h)throw pg("tpload",
|
||||
g,a.status,a.statusText);return c.reject(a)})}f.totalPendingRequests=0;return f}]}function Df(){this.$get=["$rootScope","$browser","$location",function(a,b,d){return{findBindings:function(a,b,d){a=a.getElementsByClassName("ng-binding");var g=[];q(a,function(a){var c=ca.element(a).data("$binding");c&&q(c,function(c){d?(new RegExp("(^|\\s)"+wd(b)+"(\\s|\\||$)")).test(c)&&g.push(a):-1!=c.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,d){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var k=
|
||||
a.querySelectorAll("["+g[h]+"model"+(d?"=":"*=")+'"'+b+'"]');if(k.length)return k}},getLocation:function(){return d.url()},setLocation:function(b){b!==d.url()&&(d.url(b),a.$digest())},whenStable:function(a){b.notifyWhenNoOutstandingRequests(a)}}}]}function Ef(){this.$get=["$rootScope","$browser","$q","$$q","$exceptionHandler",function(a,b,d,c,e){function f(f,k,l){z(f)||(l=k,k=f,f=A);var m=va.call(arguments,3),n=w(l)&&!l,p=(n?c:d).defer(),u=p.promise,q;q=b.defer(function(){try{p.resolve(f.apply(null,
|
||||
m))}catch(b){p.reject(b),e(b)}finally{delete g[u.$$timeoutId]}n||a.$apply()},k);u.$$timeoutId=q;g[q]=p;return u}var g={};f.cancel=function(a){return a&&a.$$timeoutId in g?(g[a.$$timeoutId].reject("canceled"),delete g[a.$$timeoutId],b.defer.cancel(a.$$timeoutId)):!1};return f}]}function Y(a){Ea&&($.setAttribute("href",a),a=$.href);$.setAttribute("href",a);return{href:$.href,protocol:$.protocol?$.protocol.replace(/:$/,""):"",host:$.host,search:$.search?$.search.replace(/^\?/,""):"",hash:$.hash?$.hash.replace(/^#/,
|
||||
""):"",hostname:$.hostname,port:$.port,pathname:"/"===$.pathname.charAt(0)?$.pathname:"/"+$.pathname}}function id(a){a=G(a)?Y(a):a;return a.protocol===yd.protocol&&a.host===yd.host}function Ff(){this.$get=ha(C)}function zd(a){function b(a){try{return decodeURIComponent(a)}catch(b){return a}}var d=a[0]||{},c={},e="";return function(){var a,g,h,k,l;a=d.cookie||"";if(a!==e)for(e=a,a=e.split("; "),c={},h=0;h<a.length;h++)g=a[h],k=g.indexOf("="),0<k&&(l=b(g.substring(0,k)),y(c[l])&&(c[l]=b(g.substring(k+
|
||||
1))));return c}}function Jf(){this.$get=zd}function Mc(a){function b(d,c){if(D(d)){var e={};q(d,function(a,c){e[c]=b(c,a)});return e}return a.factory(d+"Filter",c)}this.register=b;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];b("currency",Ad);b("date",Bd);b("filter",qg);b("json",rg);b("limitTo",sg);b("lowercase",tg);b("number",Cd);b("orderBy",Dd);b("uppercase",ug)}function qg(){return function(a,b,d,c){if(!ta(a)){if(null==a)return a;throw N("filter")("notarray",
|
||||
a);}c=c||"$";var e;switch(lc(b)){case "function":break;case "boolean":case "null":case "number":case "string":e=!0;case "object":b=vg(b,d,c,e);break;default:return a}return Array.prototype.filter.call(a,b)}}function vg(a,b,d,c){var e=D(a)&&d in a;!0===b?b=na:z(b)||(b=function(a,b){if(y(a))return!1;if(null===a||null===b)return a===b;if(D(b)||D(a)&&!vc(a))return!1;a=Q(""+a);b=Q(""+b);return-1!==a.indexOf(b)});return function(f){return e&&!D(f)?La(f,a[d],b,d,!1):La(f,a,b,d,c)}}function La(a,b,d,c,e,
|
||||
f){var g=lc(a),h=lc(b);if("string"===h&&"!"===b.charAt(0))return!La(a,b.substring(1),d,c,e);if(L(a))return a.some(function(a){return La(a,b,d,c,e)});switch(g){case "object":var k;if(e){for(k in a)if("$"!==k.charAt(0)&&La(a[k],b,d,c,!0))return!0;return f?!1:La(a,b,d,c,!1)}if("object"===h){for(k in b)if(f=b[k],!z(f)&&!y(f)&&(g=k===c,!La(g?a:a[k],f,d,c,g,g)))return!1;return!0}return d(a,b);case "function":return!1;default:return d(a,b)}}function lc(a){return null===a?"null":typeof a}function Ad(a){var b=
|
||||
a.NUMBER_FORMATS;return function(a,c,e){y(c)&&(c=b.CURRENCY_SYM);y(e)&&(e=b.PATTERNS[1].maxFrac);return null==a?a:Ed(a,b.PATTERNS[1],b.GROUP_SEP,b.DECIMAL_SEP,e).replace(/\u00A4/g,c)}}function Cd(a){var b=a.NUMBER_FORMATS;return function(a,c){return null==a?a:Ed(a,b.PATTERNS[0],b.GROUP_SEP,b.DECIMAL_SEP,c)}}function wg(a){var b=0,d,c,e,f,g;-1<(c=a.indexOf(Fd))&&(a=a.replace(Fd,""));0<(e=a.search(/e/i))?(0>c&&(c=e),c+=+a.slice(e+1),a=a.substring(0,e)):0>c&&(c=a.length);for(e=0;a.charAt(e)==mc;e++);
|
||||
if(e==(g=a.length))d=[0],c=1;else{for(g--;a.charAt(g)==mc;)g--;c-=e;d=[];for(f=0;e<=g;e++,f++)d[f]=+a.charAt(e)}c>Gd&&(d=d.splice(0,Gd-1),b=c-1,c=1);return{d:d,e:b,i:c}}function xg(a,b,d,c){var e=a.d,f=e.length-a.i;b=y(b)?Math.min(Math.max(d,f),c):+b;d=b+a.i;c=e[d];if(0<d){e.splice(Math.max(a.i,d));for(var g=d;g<e.length;g++)e[g]=0}else for(f=Math.max(0,f),a.i=1,e.length=Math.max(1,d=b+1),e[0]=0,g=1;g<d;g++)e[g]=0;if(5<=c)if(0>d-1){for(c=0;c>d;c--)e.unshift(0),a.i++;e.unshift(1);a.i++}else e[d-1]++;
|
||||
for(;f<Math.max(0,b);f++)e.push(0);if(b=e.reduceRight(function(a,b,c,d){b+=a;d[c]=b%10;return Math.floor(b/10)},0))e.unshift(b),a.i++}function Ed(a,b,d,c,e){if(!G(a)&&!T(a)||isNaN(a))return"";var f=!isFinite(a),g=!1,h=Math.abs(a)+"",k="";if(f)k="\u221e";else{g=wg(h);xg(g,e,b.minFrac,b.maxFrac);k=g.d;h=g.i;e=g.e;f=[];for(g=k.reduce(function(a,b){return a&&!b},!0);0>h;)k.unshift(0),h++;0<h?f=k.splice(h,k.length):(f=k,k=[0]);h=[];for(k.length>=b.lgSize&&h.unshift(k.splice(-b.lgSize,k.length).join(""));k.length>
|
||||
b.gSize;)h.unshift(k.splice(-b.gSize,k.length).join(""));k.length&&h.unshift(k.join(""));k=h.join(d);f.length&&(k+=c+f.join(""));e&&(k+="e+"+e)}return 0>a&&!g?b.negPre+k+b.negSuf:b.posPre+k+b.posSuf}function Kb(a,b,d,c){var e="";if(0>a||c&&0>=a)c?a=-a+1:(a=-a,e="-");for(a=""+a;a.length<b;)a=mc+a;d&&(a=a.substr(a.length-b));return e+a}function ba(a,b,d,c,e){d=d||0;return function(f){f=f["get"+a]();if(0<d||f>-d)f+=d;0===f&&-12==d&&(f=12);return Kb(f,b,c,e)}}function kb(a,b,d){return function(c,e){var f=
|
||||
c["get"+a](),g=ub((d?"STANDALONE":"")+(b?"SHORT":"")+a);return e[g][f]}}function Hd(a){var b=(new Date(a,0,1)).getDay();return new Date(a,0,(4>=b?5:12)-b)}function Id(a){return function(b){var d=Hd(b.getFullYear());b=+new Date(b.getFullYear(),b.getMonth(),b.getDate()+(4-b.getDay()))-+d;b=1+Math.round(b/6048E5);return Kb(b,a)}}function nc(a,b){return 0>=a.getFullYear()?b.ERAS[0]:b.ERAS[1]}function Bd(a){function b(a){var b;if(b=a.match(d)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,
|
||||
k=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=Z(b[9]+b[10]),g=Z(b[9]+b[11]));h.call(a,Z(b[1]),Z(b[2])-1,Z(b[3]));f=Z(b[4]||0)-f;g=Z(b[5]||0)-g;h=Z(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));k.call(a,f,g,h,b)}return a}var d=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,d,f){var g="",h=[],k,l;d=d||"mediumDate";d=a.DATETIME_FORMATS[d]||d;G(c)&&(c=yg.test(c)?Z(c):b(c));T(c)&&(c=new Date(c));if(!da(c)||!isFinite(c.getTime()))return c;
|
||||
for(;d;)(l=zg.exec(d))?(h=$a(h,l,1),d=h.pop()):(h.push(d),d=null);var m=c.getTimezoneOffset();f&&(m=yc(f,m),c=Sb(c,f,!0));q(h,function(b){k=Ag[b];g+=k?k(c,a.DATETIME_FORMATS,m):"''"===b?"'":b.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function rg(){return function(a,b){y(b)&&(b=2);return bb(a,b)}}function sg(){return function(a,b,d){b=Infinity===Math.abs(Number(b))?Number(b):Z(b);if(isNaN(b))return a;T(a)&&(a=a.toString());if(!ta(a))return a;d=!d||isNaN(d)?0:Z(d);d=0>d?Math.max(0,a.length+
|
||||
d):d;return 0<=b?oc(a,d,d+b):0===d?oc(a,b,a.length):oc(a,Math.max(0,d+b),d)}}function oc(a,b,d){return G(a)?a.slice(b,d):va.call(a,b,d)}function Dd(a){function b(b){return b.map(function(b){var c=1,d=Xa;if(z(b))d=b;else if(G(b)){if("+"==b.charAt(0)||"-"==b.charAt(0))c="-"==b.charAt(0)?-1:1,b=b.substring(1);if(""!==b&&(d=a(b),d.constant))var e=d(),d=function(a){return a[e]}}return{get:d,descending:c}})}function d(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}
|
||||
function c(a,b){var c=0,d=a.type,k=b.type;if(d===k){var k=a.value,l=b.value;"string"===d?(k=k.toLowerCase(),l=l.toLowerCase()):"object"===d&&(D(k)&&(k=a.index),D(l)&&(l=b.index));k!==l&&(c=k<l?-1:1)}else c=d<k?-1:1;return c}return function(a,f,g,h){if(null==a)return a;if(!ta(a))throw N("orderBy")("notarray",a);L(f)||(f=[f]);0===f.length&&(f=["+"]);var k=b(f),l=g?-1:1,m=z(h)?h:c;a=Array.prototype.map.call(a,function(a,b){return{value:a,tieBreaker:{value:b,type:"number",index:b},predicateValues:k.map(function(c){var e=
|
||||
c.get(a);c=typeof e;if(null===e)c="string",e="null";else if("object"===c)a:{if(z(e.valueOf)&&(e=e.valueOf(),d(e)))break a;vc(e)&&(e=e.toString(),d(e))}return{value:e,type:c,index:b}})}});a.sort(function(a,b){for(var c=0,d=k.length;c<d;c++){var e=m(a.predicateValues[c],b.predicateValues[c]);if(e)return e*k[c].descending*l}return m(a.tieBreaker,b.tieBreaker)*l});return a=a.map(function(a){return a.value})}}function Ta(a){z(a)&&(a={link:a});a.restrict=a.restrict||"AC";return ha(a)}function Jd(a,b,d,
|
||||
c,e){var f=this,g=[];f.$error={};f.$$success={};f.$pending=void 0;f.$name=e(b.name||b.ngForm||"")(d);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;f.$$parentForm=Lb;f.$rollbackViewValue=function(){q(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=function(){q(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Qa(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a);a.$$parentForm=f};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=
|
||||
a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];q(f.$pending,function(b,c){f.$setValidity(c,null,a)});q(f.$error,function(b,c){f.$setValidity(c,null,a)});q(f.$$success,function(b,c){f.$setValidity(c,null,a)});Za(g,a);a.$$parentForm=Lb};Kd({ctrl:this,$element:a,set:function(a,b,c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&(Za(d,c),0===d.length&&delete a[b])},$animate:c});f.$setDirty=function(){c.removeClass(a,Ua);c.addClass(a,
|
||||
Mb);f.$dirty=!0;f.$pristine=!1;f.$$parentForm.$setDirty()};f.$setPristine=function(){c.setClass(a,Ua,Mb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;q(g,function(a){a.$setPristine()})};f.$setUntouched=function(){q(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){c.addClass(a,"ng-submitted");f.$submitted=!0;f.$$parentForm.$setSubmitted()}}function pc(a){a.$formatters.push(function(b){return a.$isEmpty(b)?b:b.toString()})}function lb(a,b,d,c,e,f){var g=Q(b[0].type);if(!e.android){var h=
|
||||
!1;b.on("compositionstart",function(){h=!0});b.on("compositionend",function(){h=!1;l()})}var k,l=function(a){k&&(f.defer.cancel(k),k=null);if(!h){var e=b.val();a=a&&a.type;"password"===g||d.ngTrim&&"false"===d.ngTrim||(e=W(e));(c.$viewValue!==e||""===e&&c.$$hasNativeValidators)&&c.$setViewValue(e,a)}};if(e.hasEvent("input"))b.on("input",l);else{var m=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};b.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||
|
||||
m(a,this,this.value)});if(e.hasEvent("paste"))b.on("paste cut",m)}b.on("change",l);if(Ld[g]&&c.$$hasNativeValidators&&g===d.type)b.on("keydown wheel mousedown",function(a){if(!k){var b=this.validity,c=b.badInput,d=b.typeMismatch;k=f.defer(function(){k=null;b.badInput===c&&b.typeMismatch===d||l(a)})}});c.$render=function(){var a=c.$isEmpty(c.$viewValue)?"":c.$viewValue;b.val()!==a&&b.val(a)}}function Nb(a,b){return function(d,c){var e,f;if(da(d))return d;if(G(d)){'"'==d.charAt(0)&&'"'==d.charAt(d.length-
|
||||
1)&&(d=d.substring(1,d.length-1));if(Bg.test(d))return new Date(d);a.lastIndex=0;if(e=a.exec(d))return e.shift(),f=c?{yyyy:c.getFullYear(),MM:c.getMonth()+1,dd:c.getDate(),HH:c.getHours(),mm:c.getMinutes(),ss:c.getSeconds(),sss:c.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},q(e,function(a,c){c<b.length&&(f[b[c]]=+a)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function mb(a,b,d,c){return function(e,f,g,h,k,l,m){function n(a){return a&&!(a.getTime&&
|
||||
a.getTime()!==a.getTime())}function p(a){return w(a)&&!da(a)?d(a)||void 0:a}Md(e,f,g,h);lb(e,f,g,h,k,l);var u=h&&h.$options&&h.$options.timezone,q;h.$$parserName=a;h.$parsers.push(function(a){if(h.$isEmpty(a))return null;if(b.test(a))return a=d(a,q),u&&(a=Sb(a,u)),a});h.$formatters.push(function(a){if(a&&!da(a))throw nb("datefmt",a);if(n(a))return(q=a)&&u&&(q=Sb(q,u,!0)),m("date")(a,c,u);q=null;return""});if(w(g.min)||g.ngMin){var s;h.$validators.min=function(a){return!n(a)||y(s)||d(a)>=s};g.$observe("min",
|
||||
function(a){s=p(a);h.$validate()})}if(w(g.max)||g.ngMax){var r;h.$validators.max=function(a){return!n(a)||y(r)||d(a)<=r};g.$observe("max",function(a){r=p(a);h.$validate()})}}}function Md(a,b,d,c){(c.$$hasNativeValidators=D(b[0].validity))&&c.$parsers.push(function(a){var c=b.prop("validity")||{};return c.badInput||c.typeMismatch?void 0:a})}function Nd(a,b,d,c,e){if(w(c)){a=a(c);if(!a.constant)throw nb("constexpr",d,c);return a(b)}return e}function qc(a,b){a="ngClass"+a;return["$animate",function(d){function c(a,
|
||||
b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=a[d],m=0;m<b.length;m++)if(e==b[m])continue a;c.push(e)}return c}function e(a){var b=[];return L(a)?(q(a,function(a){b=b.concat(e(a))}),b):G(a)?a.split(" "):D(a)?(q(a,function(a,c){a&&(b=b.concat(c.split(" ")))}),b):a}return{restrict:"AC",link:function(f,g,h){function k(a){a=l(a,1);h.$addClass(a)}function l(a,b){var c=g.data("$classCounts")||U(),d=[];q(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}
|
||||
function m(a,b){var e=c(b,a),f=c(a,b),e=l(e,1),f=l(f,-1);e&&e.length&&d.addClass(g,e);f&&f.length&&d.removeClass(g,f)}function n(a){if(!0===b||(f.$index&1)===b){var c=e(a||[]);if(!p)k(c);else if(!na(a,p)){var d=e(p);m(d,c)}}p=L(a)?a.map(function(a){return ia(a)}):ia(a)}var p;f.$watch(h[a],n,!0);h.$observe("class",function(b){n(f.$eval(h[a]))});"ngClass"!==a&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var m=e(f.$eval(h[a]));g===b?k(m):(g=l(m,-1),h.$removeClass(g))}})}}}]}function Kd(a){function b(a,
|
||||
b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}function d(a,c){a=a?"-"+Cc(a,"-"):"";b(ob+a,!0===c);b(Od+a,!1===c)}var c=a.ctrl,e=a.$element,f={},g=a.set,h=a.unset,k=a.$animate;f[Od]=!(f[ob]=e.hasClass(ob));c.$setValidity=function(a,e,f){y(e)?(c.$pending||(c.$pending={}),g(c.$pending,a,f)):(c.$pending&&h(c.$pending,a,f),Pd(c.$pending)&&(c.$pending=void 0));Ga(e)?e?(h(c.$error,a,f),g(c.$$success,a,f)):(g(c.$error,a,f),h(c.$$success,a,f)):(h(c.$error,a,f),h(c.$$success,
|
||||
a,f));c.$pending?(b(Qd,!0),c.$valid=c.$invalid=void 0,d("",null)):(b(Qd,!1),c.$valid=Pd(c.$error),c.$invalid=!c.$valid,d("",c.$valid));e=c.$pending&&c.$pending[a]?void 0:c.$error[a]?!1:c.$$success[a]?!0:null;d(a,e);c.$$parentForm.$setValidity(a,e,c)}}function Pd(a){if(a)for(var b in a)if(a.hasOwnProperty(b))return!1;return!0}var Cg=/^\/(.+)\/([a-z]*)$/,ua=Object.prototype.hasOwnProperty,Q=function(a){return G(a)?a.toLowerCase():a},ub=function(a){return G(a)?a.toUpperCase():a},Ea,F,qa,va=[].slice,
|
||||
bg=[].splice,Dg=[].push,ma=Object.prototype.toString,wc=Object.getPrototypeOf,xa=N("ng"),ca=C.angular||(C.angular={}),Ub,pb=0;Ea=C.document.documentMode;A.$inject=[];Xa.$inject=[];var L=Array.isArray,ae=/^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/,W=function(a){return G(a)?a.trim():a},wd=function(a){return a.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},Ba=function(){if(!w(Ba.rules)){var a=C.document.querySelector("[ng-csp]")||
|
||||
C.document.querySelector("[data-ng-csp]");if(a){var b=a.getAttribute("ng-csp")||a.getAttribute("data-ng-csp");Ba.rules={noUnsafeEval:!b||-1!==b.indexOf("no-unsafe-eval"),noInlineStyle:!b||-1!==b.indexOf("no-inline-style")}}else{a=Ba;try{new Function(""),b=!1}catch(d){b=!0}a.rules={noUnsafeEval:b,noInlineStyle:!1}}}return Ba.rules},rb=function(){if(w(rb.name_))return rb.name_;var a,b,d=Na.length,c,e;for(b=0;b<d;++b)if(c=Na[b],a=C.document.querySelector("["+c.replace(":","\\:")+"jq]")){e=a.getAttribute(c+
|
||||
"jq");break}return rb.name_=e},de=/:/g,Na=["ng-","data-ng-","ng:","x-ng-"],ie=/[A-Z]/g,Dc=!1,Ma=3,me={full:"1.5.8",major:1,minor:5,dot:8,codeName:"arbitrary-fallbacks"};O.expando="ng339";var fb=O.cache={},Pf=1;O._data=function(a){return this.cache[a[this.expando]]||{}};var Kf=/([\:\-\_]+(.))/g,Lf=/^moz([A-Z])/,yb={mouseleave:"mouseout",mouseenter:"mouseover"},Wb=N("jqLite"),Of=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,Vb=/<|&#?\w+;/,Mf=/<([\w:-]+)/,Nf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,
|
||||
ja={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ja.optgroup=ja.option;ja.tbody=ja.tfoot=ja.colgroup=ja.caption=ja.thead;ja.th=ja.td;var Uf=C.Node.prototype.contains||function(a){return!!(this.compareDocumentPosition(a)&16)},Oa=O.prototype={ready:function(a){function b(){d||(d=!0,a())}var d=!1;"complete"===
|
||||
C.document.readyState?C.setTimeout(b):(this.on("DOMContentLoaded",b),O(C).on("load",b))},toString:function(){var a=[];q(this,function(b){a.push(""+b)});return"["+a.join(", ")+"]"},eq:function(a){return 0<=a?F(this[a]):F(this[this.length+a])},length:0,push:Dg,sort:[].sort,splice:[].splice},Eb={};q("multiple selected checked disabled readOnly required open".split(" "),function(a){Eb[Q(a)]=a});var Vc={};q("input select option textarea button form details".split(" "),function(a){Vc[a]=!0});var bd={ngMinlength:"minlength",
|
||||
ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};q({data:Yb,removeData:eb,hasData:function(a){for(var b in fb[a.ng339])return!0;return!1},cleanData:function(a){for(var b=0,d=a.length;b<d;b++)eb(a[b])}},function(a,b){O[b]=a});q({data:Yb,inheritedData:Cb,scope:function(a){return F.data(a,"$scope")||Cb(a.parentNode||a,["$isolateScope","$scope"])},isolateScope:function(a){return F.data(a,"$isolateScope")||F.data(a,"$isolateScopeNoTemplate")},controller:Sc,injector:function(a){return Cb(a,
|
||||
"$injector")},removeAttr:function(a,b){a.removeAttribute(b)},hasClass:zb,css:function(a,b,d){b=db(b);if(w(d))a.style[b]=d;else return a.style[b]},attr:function(a,b,d){var c=a.nodeType;if(c!==Ma&&2!==c&&8!==c)if(c=Q(b),Eb[c])if(w(d))d?(a[b]=!0,a.setAttribute(b,c)):(a[b]=!1,a.removeAttribute(c));else return a[b]||(a.attributes.getNamedItem(b)||A).specified?c:void 0;else if(w(d))a.setAttribute(b,d);else if(a.getAttribute)return a=a.getAttribute(b,2),null===a?void 0:a},prop:function(a,b,d){if(w(d))a[b]=
|
||||
d;else return a[b]},text:function(){function a(a,d){if(y(d)){var c=a.nodeType;return 1===c||c===Ma?a.textContent:""}a.textContent=d}a.$dv="";return a}(),val:function(a,b){if(y(b)){if(a.multiple&&"select"===wa(a)){var d=[];q(a.options,function(a){a.selected&&d.push(a.value||a.text)});return 0===d.length?null:d}return a.value}a.value=b},html:function(a,b){if(y(b))return a.innerHTML;wb(a,!0);a.innerHTML=b},empty:Tc},function(a,b){O.prototype[b]=function(b,c){var e,f,g=this.length;if(a!==Tc&&y(2==a.length&&
|
||||
a!==zb&&a!==Sc?b:c)){if(D(b)){for(e=0;e<g;e++)if(a===Yb)a(this[e],b);else for(f in b)a(this[e],f,b[f]);return this}e=a.$dv;g=y(e)?Math.min(g,1):g;for(f=0;f<g;f++){var h=a(this[f],b,c);e=e?e+h:h}return e}for(e=0;e<g;e++)a(this[e],b,c);return this}});q({removeData:eb,on:function(a,b,d,c){if(w(c))throw Wb("onargs");if(Nc(a)){c=xb(a,!0);var e=c.events,f=c.handle;f||(f=c.handle=Rf(a,e));c=0<=b.indexOf(" ")?b.split(" "):[b];for(var g=c.length,h=function(b,c,g){var h=e[b];h||(h=e[b]=[],h.specialHandlerWrapper=
|
||||
c,"$destroy"===b||g||a.addEventListener(b,f,!1));h.push(d)};g--;)b=c[g],yb[b]?(h(yb[b],Tf),h(b,void 0,!0)):h(b)}},off:Rc,one:function(a,b,d){a=F(a);a.on(b,function e(){a.off(b,d);a.off(b,e)});a.on(b,d)},replaceWith:function(a,b){var d,c=a.parentNode;wb(a);q(new O(b),function(b){d?c.insertBefore(b,d.nextSibling):c.replaceChild(b,a);d=b})},children:function(a){var b=[];q(a.childNodes,function(a){1===a.nodeType&&b.push(a)});return b},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,
|
||||
b){var d=a.nodeType;if(1===d||11===d){b=new O(b);for(var d=0,c=b.length;d<c;d++)a.appendChild(b[d])}},prepend:function(a,b){if(1===a.nodeType){var d=a.firstChild;q(new O(b),function(b){a.insertBefore(b,d)})}},wrap:function(a,b){Pc(a,F(b).eq(0).clone()[0])},remove:Db,detach:function(a){Db(a,!0)},after:function(a,b){var d=a,c=a.parentNode;b=new O(b);for(var e=0,f=b.length;e<f;e++){var g=b[e];c.insertBefore(g,d.nextSibling);d=g}},addClass:Bb,removeClass:Ab,toggleClass:function(a,b,d){b&&q(b.split(" "),
|
||||
function(b){var e=d;y(e)&&(e=!zb(a,b));(e?Bb:Ab)(a,b)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,b){return a.getElementsByTagName?a.getElementsByTagName(b):[]},clone:Xb,triggerHandler:function(a,b,d){var c,e,f=b.type||b,g=xb(a);if(g=(g=g&&g.events)&&g[f])c={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=
|
||||
!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:A,type:f,target:a},b.type&&(c=S(c,b)),b=ia(g),e=d?[c].concat(d):[c],q(b,function(b){c.isImmediatePropagationStopped()||b.apply(a,e)})}},function(a,b){O.prototype[b]=function(b,c,e){for(var f,g=0,h=this.length;g<h;g++)y(f)?(f=a(this[g],b,c,e),w(f)&&(f=F(f))):Qc(f,a(this[g],b,c,e));return w(f)?f:this};O.prototype.bind=O.prototype.on;O.prototype.unbind=O.prototype.off});Ra.prototype={put:function(a,
|
||||
b){this[Ca(a,this.nextUid)]=b},get:function(a){return this[Ca(a,this.nextUid)]},remove:function(a){var b=this[a=Ca(a,this.nextUid)];delete this[a];return b}};var If=[function(){this.$get=[function(){return Ra}]}],Wf=/^([^\(]+?)=>/,Xf=/^[^\(]*\(\s*([^\)]*)\)/m,Eg=/,/,Fg=/^\s*(_?)(\S+?)\1\s*$/,Vf=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ha=N("$injector");cb.$$annotate=function(a,b,d){var c;if("function"===typeof a){if(!(c=a.$inject)){c=[];if(a.length){if(b)throw G(d)&&d||(d=a.name||Yf(a)),Ha("strictdi",d);
|
||||
b=Wc(a);q(b[1].split(Eg),function(a){a.replace(Fg,function(a,b,d){c.push(d)})})}a.$inject=c}}else L(a)?(b=a.length-1,Pa(a[b],"fn"),c=a.slice(0,b)):Pa(a,"fn",!0);return c};var Rd=N("$animate"),$e=function(){this.$get=A},af=function(){var a=new Ra,b=[];this.$get=["$$AnimateRunner","$rootScope",function(d,c){function e(a,b,c){var d=!1;b&&(b=G(b)?b.split(" "):L(b)?b:[],q(b,function(b){b&&(d=!0,a[b]=c)}));return d}function f(){q(b,function(b){var c=a.get(b);if(c){var d=Zf(b.attr("class")),e="",f="";q(c,
|
||||
function(a,b){a!==!!d[b]&&(a?e+=(e.length?" ":"")+b:f+=(f.length?" ":"")+b)});q(b,function(a){e&&Bb(a,e);f&&Ab(a,f)});a.remove(b)}});b.length=0}return{enabled:A,on:A,off:A,pin:A,push:function(g,h,k,l){l&&l();k=k||{};k.from&&g.css(k.from);k.to&&g.css(k.to);if(k.addClass||k.removeClass)if(h=k.addClass,l=k.removeClass,k=a.get(g)||{},h=e(k,h,!0),l=e(k,l,!1),h||l)a.put(g,k),b.push(g),1===b.length&&c.$$postDigest(f);g=new d;g.complete();return g}}}]},Ye=["$provide",function(a){var b=this;this.$$registeredAnimations=
|
||||
Object.create(null);this.register=function(d,c){if(d&&"."!==d.charAt(0))throw Rd("notcsel",d);var e=d+"-animation";b.$$registeredAnimations[d.substr(1)]=e;a.factory(e,c)};this.classNameFilter=function(a){if(1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null)&&/(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString()))throw Rd("nongcls","ng-animate");return this.$$classNameFilter};this.$get=["$$animateQueue",function(a){function b(a,c,d){if(d){var h;a:{for(h=0;h<d.length;h++){var k=
|
||||
d[h];if(1===k.nodeType){h=k;break a}}h=void 0}!h||h.parentNode||h.previousElementSibling||(d=null)}d?d.after(a):c.prepend(a)}return{on:a.on,off:a.off,pin:a.pin,enabled:a.enabled,cancel:function(a){a.end&&a.end()},enter:function(e,f,g,h){f=f&&F(f);g=g&&F(g);f=f||g.parent();b(e,f,g);return a.push(e,"enter",Ia(h))},move:function(e,f,g,h){f=f&&F(f);g=g&&F(g);f=f||g.parent();b(e,f,g);return a.push(e,"move",Ia(h))},leave:function(b,c){return a.push(b,"leave",Ia(c),function(){b.remove()})},addClass:function(b,
|
||||
c,g){g=Ia(g);g.addClass=gb(g.addclass,c);return a.push(b,"addClass",g)},removeClass:function(b,c,g){g=Ia(g);g.removeClass=gb(g.removeClass,c);return a.push(b,"removeClass",g)},setClass:function(b,c,g,h){h=Ia(h);h.addClass=gb(h.addClass,c);h.removeClass=gb(h.removeClass,g);return a.push(b,"setClass",h)},animate:function(b,c,g,h,k){k=Ia(k);k.from=k.from?S(k.from,c):c;k.to=k.to?S(k.to,g):g;k.tempClasses=gb(k.tempClasses,h||"ng-inline-animate");return a.push(b,"animate",k)}}}]}],cf=function(){this.$get=
|
||||
["$$rAF",function(a){function b(b){d.push(b);1<d.length||a(function(){for(var a=0;a<d.length;a++)d[a]();d=[]})}var d=[];return function(){var a=!1;b(function(){a=!0});return function(d){a?d():b(d)}}}]},bf=function(){this.$get=["$q","$sniffer","$$animateAsyncRun","$document","$timeout",function(a,b,d,c,e){function f(a){this.setHost(a);var b=d();this._doneCallbacks=[];this._tick=function(a){var d=c[0];d&&d.hidden?e(a,0,!1):b(a)};this._state=0}f.chain=function(a,b){function c(){if(d===a.length)b(!0);
|
||||
else a[d](function(a){!1===a?b(!1):(d++,c())})}var d=0;c()};f.all=function(a,b){function c(f){e=e&&f;++d===a.length&&b(e)}var d=0,e=!0;q(a,function(a){a.done(c)})};f.prototype={setHost:function(a){this.host=a||{}},done:function(a){2===this._state?a():this._doneCallbacks.push(a)},progress:A,getPromise:function(){if(!this.promise){var b=this;this.promise=a(function(a,c){b.done(function(b){!1===b?c():a()})})}return this.promise},then:function(a,b){return this.getPromise().then(a,b)},"catch":function(a){return this.getPromise()["catch"](a)},
|
||||
"finally":function(a){return this.getPromise()["finally"](a)},pause:function(){this.host.pause&&this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&this.host.end();this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel();this._resolve(!1)},complete:function(a){var b=this;0===b._state&&(b._state=1,b._tick(function(){b._resolve(a)}))},_resolve:function(a){2!==this._state&&(q(this._doneCallbacks,function(b){b(a)}),this._doneCallbacks.length=
|
||||
0,this._state=2)}};return f}]},Ze=function(){this.$get=["$$rAF","$q","$$AnimateRunner",function(a,b,d){return function(b,e){function f(){a(function(){g.addClass&&(b.addClass(g.addClass),g.addClass=null);g.removeClass&&(b.removeClass(g.removeClass),g.removeClass=null);g.to&&(b.css(g.to),g.to=null);h||k.complete();h=!0});return k}var g=e||{};g.$$prepared||(g=pa(g));g.cleanupStyles&&(g.from=g.to=null);g.from&&(b.css(g.from),g.from=null);var h,k=new d;return{start:f,end:f}}}]},ga=N("$compile"),bc=new function(){};
|
||||
Fc.$inject=["$provide","$$sanitizeUriProvider"];Fb.prototype.isFirstChange=function(){return this.previousValue===bc};var Yc=/^((?:x|data)[\:\-_])/i,cg=N("$controller"),cd=/^(\S+)(\s+as\s+([\w$]+))?$/,jf=function(){this.$get=["$document",function(a){return function(b){b?!b.nodeType&&b instanceof F&&(b=b[0]):b=a[0].body;return b.offsetWidth+1}}]},dd="application/json",ec={"Content-Type":dd+";charset=utf-8"},eg=/^\[|^\{(?!\{)/,fg={"[":/]$/,"{":/}$/},dg=/^\)\]\}',?\n/,Gg=N("$http"),hd=function(a){return function(){throw Gg("legacy",
|
||||
a);}},Ka=ca.$interpolateMinErr=N("$interpolate");Ka.throwNoconcat=function(a){throw Ka("noconcat",a);};Ka.interr=function(a,b){return Ka("interr",a,b.toString())};var rf=function(){this.$get=["$window",function(a){function b(a){var b=function(a){b.data=a;b.called=!0};b.id=a;return b}var d=a.angular.callbacks,c={};return{createCallback:function(a){a="_"+(d.$$counter++).toString(36);var f="angular.callbacks."+a,g=b(a);c[f]=d[a]=g;return f},wasCalled:function(a){return c[a].called},getResponse:function(a){return c[a].data},
|
||||
removeCallback:function(a){delete d[c[a].id];delete c[a]}}}]},Hg=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,hg={http:80,https:443,ftp:21},Gb=N("$location"),Ig={$$absUrl:"",$$html5:!1,$$replace:!1,absUrl:Hb("$$absUrl"),url:function(a){if(y(a))return this.$$url;var b=Hg.exec(a);(b[1]||""===a)&&this.path(decodeURIComponent(b[1]));(b[2]||b[1]||""===a)&&this.search(b[3]||"");this.hash(b[5]||"");return this},protocol:Hb("$$protocol"),host:Hb("$$host"),port:Hb("$$port"),path:md("$$path",function(a){a=null!==a?a.toString():
|
||||
"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,b){switch(arguments.length){case 0:return this.$$search;case 1:if(G(a)||T(a))a=a.toString(),this.$$search=Ac(a);else if(D(a))a=pa(a,{}),q(a,function(b,c){null==b&&delete a[c]}),this.$$search=a;else throw Gb("isrcharg");break;default:y(b)||null===b?delete this.$$search[a]:this.$$search[a]=b}this.$$compose();return this},hash:md("$$hash",function(a){return null!==a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};q([ld,hc,gc],
|
||||
function(a){a.prototype=Object.create(Ig);a.prototype.state=function(b){if(!arguments.length)return this.$$state;if(a!==gc||!this.$$html5)throw Gb("nostate");this.$$state=y(b)?null:b;return this}});var X=N("$parse"),jg=Function.prototype.call,kg=Function.prototype.apply,lg=Function.prototype.bind,Ob=U();q("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(a){Ob[a]=!0});var Jg={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},jc=function(a){this.options=a};jc.prototype={constructor:jc,
|
||||
lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdentifierStart(this.peekMultichar()))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++;else{var b=a+this.peek(),d=b+this.peek(2),c=Ob[b],e=Ob[d];Ob[a]||
|
||||
c||e?(a=e?d:c?b:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,b){return-1!==b.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdentifierStart:function(a){return this.options.isIdentifierStart?
|
||||
this.options.isIdentifierStart(a,this.codePointAt(a)):this.isValidIdentifierStart(a)},isValidIdentifierStart:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isIdentifierContinue:function(a){return this.options.isIdentifierContinue?this.options.isIdentifierContinue(a,this.codePointAt(a)):this.isValidIdentifierContinue(a)},isValidIdentifierContinue:function(a,b){return this.isValidIdentifierStart(a,b)||this.isNumber(a)},codePointAt:function(a){return 1===a.length?a.charCodeAt(0):
|
||||
(a.charCodeAt(0)<<10)+a.charCodeAt(1)-56613888},peekMultichar:function(){var a=this.text.charAt(this.index),b=this.peek();if(!b)return a;var d=a.charCodeAt(0),c=b.charCodeAt(0);return 55296<=d&&56319>=d&&56320<=c&&57343>=c?a+b:a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,b,d){d=d||this.index;b=w(b)?"s "+b+"-"+this.index+" ["+this.text.substring(b,d)+"]":" "+d;throw X("lexerr",a,b,this.text);},readNumber:function(){for(var a="",b=this.index;this.index<
|
||||
this.text.length;){var d=Q(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var c=this.peek();if("e"==d&&this.isExpOperator(c))a+=d;else if(this.isExpOperator(d)&&c&&this.isNumber(c)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||c&&this.isNumber(c)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:b,text:a,constant:!0,value:Number(a)})},readIdent:function(){var a=this.index;for(this.index+=this.peekMultichar().length;this.index<
|
||||
this.text.length;){var b=this.peekMultichar();if(!this.isIdentifierContinue(b))break;this.index+=b.length}this.tokens.push({index:a,text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var b=this.index;this.index++;for(var d="",c=a,e=!1;this.index<this.text.length;){var f=this.text.charAt(this.index),c=c+f;if(e)"u"===f?(e=this.text.substring(this.index+1,this.index+5),e.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+e+"]"),this.index+=4,d+=String.fromCharCode(parseInt(e,
|
||||
16))):d+=Jg[f]||f,e=!1;else if("\\"===f)e=!0;else{if(f===a){this.index++;this.tokens.push({index:b,text:c,constant:!0,value:d});return}d+=f}this.index++}this.throwError("Unterminated quote",b)}};var s=function(a,b){this.lexer=a;this.options=b};s.Program="Program";s.ExpressionStatement="ExpressionStatement";s.AssignmentExpression="AssignmentExpression";s.ConditionalExpression="ConditionalExpression";s.LogicalExpression="LogicalExpression";s.BinaryExpression="BinaryExpression";s.UnaryExpression="UnaryExpression";
|
||||
s.CallExpression="CallExpression";s.MemberExpression="MemberExpression";s.Identifier="Identifier";s.Literal="Literal";s.ArrayExpression="ArrayExpression";s.Property="Property";s.ObjectExpression="ObjectExpression";s.ThisExpression="ThisExpression";s.LocalsExpression="LocalsExpression";s.NGValueParameter="NGValueParameter";s.prototype={ast:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.program();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);return a},
|
||||
program:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.expressionStatement()),!this.expect(";"))return{type:s.Program,body:a}},expressionStatement:function(){return{type:s.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary();this.expect("=")&&(a={type:s.AssignmentExpression,
|
||||
left:a,right:this.assignment(),operator:"="});return a},ternary:function(){var a=this.logicalOR(),b,d;return this.expect("?")&&(b=this.expression(),this.consume(":"))?(d=this.expression(),{type:s.ConditionalExpression,test:a,alternate:b,consequent:d}):a},logicalOR:function(){for(var a=this.logicalAND();this.expect("||");)a={type:s.LogicalExpression,operator:"||",left:a,right:this.logicalAND()};return a},logicalAND:function(){for(var a=this.equality();this.expect("&&");)a={type:s.LogicalExpression,
|
||||
operator:"&&",left:a,right:this.equality()};return a},equality:function(){for(var a=this.relational(),b;b=this.expect("==","!=","===","!==");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.relational()};return a},relational:function(){for(var a=this.additive(),b;b=this.expect("<",">","<=",">=");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),b;b=this.expect("+","-");)a={type:s.BinaryExpression,operator:b.text,
|
||||
left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),b;b=this.expect("*","/","%");)a={type:s.BinaryExpression,operator:b.text,left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:s.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():
|
||||
this.selfReferential.hasOwnProperty(this.peek().text)?a=pa(this.selfReferential[this.consume().text]):this.options.literals.hasOwnProperty(this.peek().text)?a={type:s.Literal,value:this.options.literals[this.consume().text]}:this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var b;b=this.expect("(","[",".");)"("===b.text?(a={type:s.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):
|
||||
"["===b.text?(a={type:s.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===b.text?a={type:s.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var b={type:s.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return b},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.filterChain());while(this.expect(","))
|
||||
}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:s.Identifier,name:a.text}},constant:function(){return{type:s.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:s.ArrayExpression,elements:a}},object:function(){var a=[],b;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;
|
||||
b={type:s.Property,kind:"init"};this.peek().constant?(b.key=this.constant(),b.computed=!1,this.consume(":"),b.value=this.expression()):this.peek().identifier?(b.key=this.identifier(),b.computed=!1,this.peek(":")?(this.consume(":"),b.value=this.expression()):b.value=b.key):this.peek("[")?(this.consume("["),b.key=this.expression(),this.consume("]"),b.computed=!0,this.consume(":"),b.value=this.expression()):this.throwError("invalid key",this.peek());a.push(b)}while(this.expect(","))}this.consume("}");
|
||||
return{type:s.ObjectExpression,properties:a}},throwError:function(a,b){throw X("syntax",b.text,a,b.index+1,this.text,this.text.substring(b.index));},consume:function(a){if(0===this.tokens.length)throw X("ueoe",this.text);var b=this.expect(a);b||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return b},peekToken:function(){if(0===this.tokens.length)throw X("ueoe",this.text);return this.tokens[0]},peek:function(a,b,d,c){return this.peekAhead(0,a,b,d,c)},peekAhead:function(a,b,d,c,e){if(this.tokens.length>
|
||||
a){a=this.tokens[a];var f=a.text;if(f===b||f===d||f===c||f===e||!(b||d||c||e))return a}return!1},expect:function(a,b,d,c){return(a=this.peek(a,b,d,c))?(this.tokens.shift(),a):!1},selfReferential:{"this":{type:s.ThisExpression},$locals:{type:s.LocalsExpression}}};td.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:b,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]};V(c,d.$filter);var e="",f;this.stage="assign";
|
||||
if(f=rd(c))this.state.computing="assign",e=this.nextId(),this.recurse(f,e),this.return_(e),e="fn.assign="+this.generateFunction("assign","s,v,l");f=pd(c.body);d.stage="inputs";q(f,function(a,b){var c="fn"+b;d.state[c]={vars:[],body:[],own:{}};d.state.computing=c;var e=d.nextId();d.recurse(a,e);d.return_(e);d.state.inputs.push(c);a.watchId=b});this.state.computing="fn";this.stage="main";this.recurse(c);e='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+
|
||||
e+this.watchFns()+"return fn;";e=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","getStringValue","ensureSafeAssignContext","ifDefined","plus","text",e))(this.$filter,Sa,ra,nd,ig,Ib,mg,od,a);this.state=this.stage=void 0;e.literal=sd(c);e.constant=c.constant;return e},USE:"use",STRICT:"strict",watchFns:function(){var a=[],b=this.state.inputs,d=this;q(b,function(b){a.push("var "+b+"="+d.generateFunction(b,"s"))});b.length&&a.push("fn.inputs=["+b.join(",")+"];");
|
||||
return a.join("")},generateFunction:function(a,b){return"function("+b+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],b=this;q(this.state.filters,function(d,c){a.push(d+"=$filter("+b.escape(c)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,b,d,c,e,f){var g,h,k=this,l,m,n;c=c||A;if(!f&&w(a.watchId))b=
|
||||
b||this.nextId(),this.if_("i",this.lazyAssign(b,this.computedMember("i",a.watchId)),this.lazyRecurse(a,b,d,c,e,!0));else switch(a.type){case s.Program:q(a.body,function(b,c){k.recurse(b.expression,void 0,void 0,function(a){h=a});c!==a.body.length-1?k.current().body.push(h,";"):k.return_(h)});break;case s.Literal:m=this.escape(a.value);this.assign(b,m);c(m);break;case s.UnaryExpression:this.recurse(a.argument,void 0,void 0,function(a){h=a});m=a.operator+"("+this.ifDefined(h,0)+")";this.assign(b,m);
|
||||
c(m);break;case s.BinaryExpression:this.recurse(a.left,void 0,void 0,function(a){g=a});this.recurse(a.right,void 0,void 0,function(a){h=a});m="+"===a.operator?this.plus(g,h):"-"===a.operator?this.ifDefined(g,0)+a.operator+this.ifDefined(h,0):"("+g+")"+a.operator+"("+h+")";this.assign(b,m);c(m);break;case s.LogicalExpression:b=b||this.nextId();k.recurse(a.left,b);k.if_("&&"===a.operator?b:k.not(b),k.lazyRecurse(a.right,b));c(b);break;case s.ConditionalExpression:b=b||this.nextId();k.recurse(a.test,
|
||||
b);k.if_(b,k.lazyRecurse(a.alternate,b),k.lazyRecurse(a.consequent,b));c(b);break;case s.Identifier:b=b||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Sa(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){e&&1!==e&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(b,k.nonComputedMember("s",
|
||||
a.name))})},b&&k.lazyAssign(b,k.nonComputedMember("l",a.name)));(k.state.expensiveChecks||Jb(a.name))&&k.addEnsureSafeObject(b);c(b);break;case s.MemberExpression:g=d&&(d.context=this.nextId())||this.nextId();b=b||this.nextId();k.recurse(a.object,g,void 0,function(){k.if_(k.notNull(g),function(){e&&1!==e&&k.addEnsureSafeAssignContext(g);if(a.computed)h=k.nextId(),k.recurse(a.property,h),k.getStringValue(h),k.addEnsureSafeMemberName(h),e&&1!==e&&k.if_(k.not(k.computedMember(g,h)),k.lazyAssign(k.computedMember(g,
|
||||
h),"{}")),m=k.ensureSafeObject(k.computedMember(g,h)),k.assign(b,m),d&&(d.computed=!0,d.name=h);else{Sa(a.property.name);e&&1!==e&&k.if_(k.not(k.nonComputedMember(g,a.property.name)),k.lazyAssign(k.nonComputedMember(g,a.property.name),"{}"));m=k.nonComputedMember(g,a.property.name);if(k.state.expensiveChecks||Jb(a.property.name))m=k.ensureSafeObject(m);k.assign(b,m);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(b,"undefined")});c(b)},!!e);break;case s.CallExpression:b=b||this.nextId();
|
||||
a.filter?(h=k.filter(a.callee.name),l=[],q(a.arguments,function(a){var b=k.nextId();k.recurse(a,b);l.push(b)}),m=h+"("+l.join(",")+")",k.assign(b,m),c(b)):(h=k.nextId(),g={},l=[],k.recurse(a.callee,h,g,function(){k.if_(k.notNull(h),function(){k.addEnsureSafeFunction(h);q(a.arguments,function(a){k.recurse(a,k.nextId(),void 0,function(a){l.push(k.ensureSafeObject(a))})});g.name?(k.state.expensiveChecks||k.addEnsureSafeObject(g.context),m=k.member(g.context,g.name,g.computed)+"("+l.join(",")+")"):m=
|
||||
h+"("+l.join(",")+")";m=k.ensureSafeObject(m);k.assign(b,m)},function(){k.assign(b,"undefined")});c(b)}));break;case s.AssignmentExpression:h=this.nextId();g={};if(!qd(a.left))throw X("lval");this.recurse(a.left,void 0,g,function(){k.if_(k.notNull(g.context),function(){k.recurse(a.right,h);k.addEnsureSafeObject(k.member(g.context,g.name,g.computed));k.addEnsureSafeAssignContext(g.context);m=k.member(g.context,g.name,g.computed)+a.operator+h;k.assign(b,m);c(b||m)})},1);break;case s.ArrayExpression:l=
|
||||
[];q(a.elements,function(a){k.recurse(a,k.nextId(),void 0,function(a){l.push(a)})});m="["+l.join(",")+"]";this.assign(b,m);c(m);break;case s.ObjectExpression:l=[];n=!1;q(a.properties,function(a){a.computed&&(n=!0)});n?(b=b||this.nextId(),this.assign(b,"{}"),q(a.properties,function(a){a.computed?(g=k.nextId(),k.recurse(a.key,g)):g=a.key.type===s.Identifier?a.key.name:""+a.key.value;h=k.nextId();k.recurse(a.value,h);k.assign(k.member(b,g,a.computed),h)})):(q(a.properties,function(b){k.recurse(b.value,
|
||||
a.constant?void 0:k.nextId(),void 0,function(a){l.push(k.escape(b.key.type===s.Identifier?b.key.name:""+b.key.value)+":"+a)})}),m="{"+l.join(",")+"}",this.assign(b,m));c(b||m);break;case s.ThisExpression:this.assign(b,"s");c("s");break;case s.LocalsExpression:this.assign(b,"l");c("l");break;case s.NGValueParameter:this.assign(b,"v"),c("v")}},getHasOwnProperty:function(a,b){var d=a+"."+b,c=this.current().own;c.hasOwnProperty(d)||(c[d]=this.nextId(!1,a+"&&("+this.escape(b)+" in "+a+")"));return c[d]},
|
||||
assign:function(a,b){if(a)return this.current().body.push(a,"=",b,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,b){return"ifDefined("+a+","+this.escape(b)+")"},plus:function(a,b){return"plus("+a+","+b+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,b,d){if(!0===a)b();else{var c=this.current().body;c.push("if(",a,"){");b();c.push("}");d&&(c.push("else{"),
|
||||
d(),c.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,b){var d=/[^$_a-zA-Z0-9]/g;return/[$_a-zA-Z][$_a-zA-Z0-9]*/.test(b)?a+"."+b:a+'["'+b.replace(d,this.stringEscapeFn)+'"]'},computedMember:function(a,b){return a+"["+b+"]"},member:function(a,b,d){return d?this.computedMember(a,b):this.nonComputedMember(a,b)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),
|
||||
";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},addEnsureSafeAssignContext:function(a){this.current().body.push(this.ensureSafeAssignContext(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},getStringValue:function(a){this.assign(a,"getStringValue("+a+")")},ensureSafeAssignContext:function(a){return"ensureSafeAssignContext("+
|
||||
a+",text)"},lazyRecurse:function(a,b,d,c,e,f){var g=this;return function(){g.recurse(a,b,d,c,e,f)}},lazyAssign:function(a,b){var d=this;return function(){d.assign(a,b)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(G(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(T(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"===
|
||||
typeof a)return"undefined";throw X("esc");},nextId:function(a,b){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(b?"="+b:""));return d},current:function(){return this.state[this.state.computing]}};ud.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=b;V(c,d.$filter);var e,f;if(e=rd(c))f=this.recurse(e);e=pd(c.body);var g;e&&(g=[],q(e,function(a,b){var c=d.recurse(a);a.input=c;g.push(c);a.watchId=b}));var h=[];q(c.body,function(a){h.push(d.recurse(a.expression))});
|
||||
e=0===c.body.length?A:1===c.body.length?h[0]:function(a,b){var c;q(h,function(d){c=d(a,b)});return c};f&&(e.assign=function(a,b,c){return f(a,c,b)});g&&(e.inputs=g);e.literal=sd(c);e.constant=c.constant;return e},recurse:function(a,b,d){var c,e,f=this,g;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case s.Literal:return this.value(a.value,b);case s.UnaryExpression:return e=this.recurse(a.argument),this["unary"+a.operator](e,b);case s.BinaryExpression:return c=this.recurse(a.left),
|
||||
e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case s.LogicalExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case s.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),b);case s.Identifier:return Sa(a.name,f.expression),f.identifier(a.name,f.expensiveChecks||Jb(a.name),b,d,f.expression);case s.MemberExpression:return c=this.recurse(a.object,!1,!!d),a.computed||(Sa(a.property.name,
|
||||
f.expression),e=a.property.name),a.computed&&(e=this.recurse(a.property)),a.computed?this.computedMember(c,e,b,d,f.expression):this.nonComputedMember(c,e,f.expensiveChecks,b,d,f.expression);case s.CallExpression:return g=[],q(a.arguments,function(a){g.push(f.recurse(a))}),a.filter&&(e=this.$filter(a.callee.name)),a.filter||(e=this.recurse(a.callee,!0)),a.filter?function(a,c,d,f){for(var n=[],p=0;p<g.length;++p)n.push(g[p](a,c,d,f));a=e.apply(void 0,n,f);return b?{context:void 0,name:void 0,value:a}:
|
||||
a}:function(a,c,d,m){var n=e(a,c,d,m),p;if(null!=n.value){ra(n.context,f.expression);nd(n.value,f.expression);p=[];for(var q=0;q<g.length;++q)p.push(ra(g[q](a,c,d,m),f.expression));p=ra(n.value.apply(n.context,p),f.expression)}return b?{value:p}:p};case s.AssignmentExpression:return c=this.recurse(a.left,!0,1),e=this.recurse(a.right),function(a,d,g,m){var n=c(a,d,g,m);a=e(a,d,g,m);ra(n.value,f.expression);Ib(n.context);n.context[n.name]=a;return b?{value:a}:a};case s.ArrayExpression:return g=[],q(a.elements,
|
||||
function(a){g.push(f.recurse(a))}),function(a,c,d,e){for(var f=[],p=0;p<g.length;++p)f.push(g[p](a,c,d,e));return b?{value:f}:f};case s.ObjectExpression:return g=[],q(a.properties,function(a){a.computed?g.push({key:f.recurse(a.key),computed:!0,value:f.recurse(a.value)}):g.push({key:a.key.type===s.Identifier?a.key.name:""+a.key.value,computed:!1,value:f.recurse(a.value)})}),function(a,c,d,e){for(var f={},p=0;p<g.length;++p)g[p].computed?f[g[p].key(a,c,d,e)]=g[p].value(a,c,d,e):f[g[p].key]=g[p].value(a,
|
||||
c,d,e);return b?{value:f}:f};case s.ThisExpression:return function(a){return b?{value:a}:a};case s.LocalsExpression:return function(a,c){return b?{value:c}:c};case s.NGValueParameter:return function(a,c,d){return b?{value:d}:d}}},"unary+":function(a,b){return function(d,c,e,f){d=a(d,c,e,f);d=w(d)?+d:0;return b?{value:d}:d}},"unary-":function(a,b){return function(d,c,e,f){d=a(d,c,e,f);d=w(d)?-d:0;return b?{value:d}:d}},"unary!":function(a,b){return function(d,c,e,f){d=!a(d,c,e,f);return b?{value:d}:
|
||||
d}},"binary+":function(a,b,d){return function(c,e,f,g){var h=a(c,e,f,g);c=b(c,e,f,g);h=od(h,c);return d?{value:h}:h}},"binary-":function(a,b,d){return function(c,e,f,g){var h=a(c,e,f,g);c=b(c,e,f,g);h=(w(h)?h:0)-(w(c)?c:0);return d?{value:h}:h}},"binary*":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)*b(c,e,f,g);return d?{value:c}:c}},"binary/":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)/b(c,e,f,g);return d?{value:c}:c}},"binary%":function(a,b,d){return function(c,e,f,g){c=a(c,e,
|
||||
f,g)%b(c,e,f,g);return d?{value:c}:c}},"binary===":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)===b(c,e,f,g);return d?{value:c}:c}},"binary!==":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)!==b(c,e,f,g);return d?{value:c}:c}},"binary==":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)==b(c,e,f,g);return d?{value:c}:c}},"binary!=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)!=b(c,e,f,g);return d?{value:c}:c}},"binary<":function(a,b,d){return function(c,e,f,g){c=a(c,e,
|
||||
f,g)<b(c,e,f,g);return d?{value:c}:c}},"binary>":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>b(c,e,f,g);return d?{value:c}:c}},"binary<=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)<=b(c,e,f,g);return d?{value:c}:c}},"binary>=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>=b(c,e,f,g);return d?{value:c}:c}},"binary&&":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)&&b(c,e,f,g);return d?{value:c}:c}},"binary||":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)||
|
||||
b(c,e,f,g);return d?{value:c}:c}},"ternary?:":function(a,b,d,c){return function(e,f,g,h){e=a(e,f,g,h)?b(e,f,g,h):d(e,f,g,h);return c?{value:e}:e}},value:function(a,b){return function(){return b?{context:void 0,name:void 0,value:a}:a}},identifier:function(a,b,d,c,e){return function(f,g,h,k){f=g&&a in g?g:f;c&&1!==c&&f&&!f[a]&&(f[a]={});g=f?f[a]:void 0;b&&ra(g,e);return d?{context:f,name:a,value:g}:g}},computedMember:function(a,b,d,c,e){return function(f,g,h,k){var l=a(f,g,h,k),m,n;null!=l&&(m=b(f,
|
||||
g,h,k),m+="",Sa(m,e),c&&1!==c&&(Ib(l),l&&!l[m]&&(l[m]={})),n=l[m],ra(n,e));return d?{context:l,name:m,value:n}:n}},nonComputedMember:function(a,b,d,c,e,f){return function(g,h,k,l){g=a(g,h,k,l);e&&1!==e&&(Ib(g),g&&!g[b]&&(g[b]={}));h=null!=g?g[b]:void 0;(d||Jb(b))&&ra(h,f);return c?{context:g,name:b,value:h}:h}},inputs:function(a,b){return function(d,c,e,f){return f?f[b]:a(d,c,e)}}};var kc=function(a,b,d){this.lexer=a;this.$filter=b;this.options=d;this.ast=new s(a,d);this.astCompiler=d.csp?new ud(this.ast,
|
||||
b):new td(this.ast,b)};kc.prototype={constructor:kc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};var ng=Object.prototype.valueOf,sa=N("$sce"),la={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},pg=N("$compile"),$=C.document.createElement("a"),yd=Y(C.location.href);zd.$inject=["$document"];Mc.$inject=["$provide"];var Gd=22,Fd=".",mc="0";Ad.$inject=["$locale"];Cd.$inject=["$locale"];var Ag={yyyy:ba("FullYear",4,0,!1,!0),yy:ba("FullYear",2,0,
|
||||
!0,!0),y:ba("FullYear",1,0,!1,!0),MMMM:kb("Month"),MMM:kb("Month",!0),MM:ba("Month",2,1),M:ba("Month",1,1),LLLL:kb("Month",!1,!0),dd:ba("Date",2),d:ba("Date",1),HH:ba("Hours",2),H:ba("Hours",1),hh:ba("Hours",2,-12),h:ba("Hours",1,-12),mm:ba("Minutes",2),m:ba("Minutes",1),ss:ba("Seconds",2),s:ba("Seconds",1),sss:ba("Milliseconds",3),EEEE:kb("Day"),EEE:kb("Day",!0),a:function(a,b){return 12>a.getHours()?b.AMPMS[0]:b.AMPMS[1]},Z:function(a,b,d){a=-1*d;return a=(0<=a?"+":"")+(Kb(Math[0<a?"floor":"ceil"](a/
|
||||
60),2)+Kb(Math.abs(a%60),2))},ww:Id(2),w:Id(1),G:nc,GG:nc,GGG:nc,GGGG:function(a,b){return 0>=a.getFullYear()?b.ERANAMES[0]:b.ERANAMES[1]}},zg=/((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,yg=/^\-?\d+$/;Bd.$inject=["$locale"];var tg=ha(Q),ug=ha(ub);Dd.$inject=["$parse"];var oe=ha({restrict:"E",compile:function(a,b){if(!b.href&&!b.xlinkHref)return function(a,b){if("a"===b[0].nodeName.toLowerCase()){var e="[object SVGAnimatedString]"===ma.call(b.prop("href"))?
|
||||
"xlink:href":"href";b.on("click",function(a){b.attr(e)||a.preventDefault()})}}}}),vb={};q(Eb,function(a,b){function d(a,d,e){a.$watch(e[c],function(a){e.$set(b,!!a)})}if("multiple"!=a){var c=Aa("ng-"+b),e=d;"checked"===a&&(e=function(a,b,e){e.ngModel!==e[c]&&d(a,b,e)});vb[c]=function(){return{restrict:"A",priority:100,link:e}}}});q(bd,function(a,b){vb[b]=function(){return{priority:100,link:function(a,c,e){if("ngPattern"===b&&"/"==e.ngPattern.charAt(0)&&(c=e.ngPattern.match(Cg))){e.$set("ngPattern",
|
||||
new RegExp(c[1],c[2]));return}a.$watch(e[b],function(a){e.$set(b,a)})}}}});q(["src","srcset","href"],function(a){var b=Aa("ng-"+a);vb[b]=function(){return{priority:99,link:function(d,c,e){var f=a,g=a;"href"===a&&"[object SVGAnimatedString]"===ma.call(c.prop("href"))&&(g="xlinkHref",e.$attr[g]="xlink:href",f=null);e.$observe(b,function(b){b?(e.$set(g,b),Ea&&f&&c.prop(f,e[g])):"href"===a&&e.$set(g,null)})}}}});var Lb={$addControl:A,$$renameControl:function(a,b){a.$name=b},$removeControl:A,$setValidity:A,
|
||||
$setDirty:A,$setPristine:A,$setSubmitted:A};Jd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Sd=function(a){return["$timeout","$parse",function(b,d){function c(a){return""===a?d('this[""]').assign:d(a).assign||A}return{name:"form",restrict:a?"EAC":"E",require:["form","^^?form"],controller:Jd,compile:function(d,f){d.addClass(Ua).addClass(ob);var g=f.name?"name":a&&f.ngForm?"ngForm":!1;return{pre:function(a,d,e,f){var n=f[0];if(!("action"in e)){var p=function(b){a.$apply(function(){n.$commitViewValue();
|
||||
n.$setSubmitted()});b.preventDefault()};d[0].addEventListener("submit",p,!1);d.on("$destroy",function(){b(function(){d[0].removeEventListener("submit",p,!1)},0,!1)})}(f[1]||n.$$parentForm).$addControl(n);var q=g?c(n.$name):A;g&&(q(a,n),e.$observe(g,function(b){n.$name!==b&&(q(a,void 0),n.$$parentForm.$$renameControl(n,b),q=c(n.$name),q(a,n))}));d.on("$destroy",function(){n.$$parentForm.$removeControl(n);q(a,void 0);S(n,Lb)})}}}}}]},pe=Sd(),Ce=Sd(!0),Bg=/^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/,
|
||||
Kg=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,Lg=/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/,Mg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Td=/^(\d{4,})-(\d{2})-(\d{2})$/,Ud=/^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,rc=/^(\d{4,})-W(\d\d)$/,Vd=/^(\d{4,})-(\d\d)$/,
|
||||
Wd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Ld=U();q(["date","datetime-local","month","time","week"],function(a){Ld[a]=!0});var Xd={text:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);pc(c)},date:mb("date",Td,Nb(Td,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":mb("datetimelocal",Ud,Nb(Ud,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:mb("time",Wd,Nb(Wd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:mb("week",rc,function(a,b){if(da(a))return a;if(G(a)){rc.lastIndex=0;var d=rc.exec(a);
|
||||
if(d){var c=+d[1],e=+d[2],f=d=0,g=0,h=0,k=Hd(c),e=7*(e-1);b&&(d=b.getHours(),f=b.getMinutes(),g=b.getSeconds(),h=b.getMilliseconds());return new Date(c,0,k.getDate()+e,d,f,g,h)}}return NaN},"yyyy-Www"),month:mb("month",Vd,Nb(Vd,["yyyy","MM"]),"yyyy-MM"),number:function(a,b,d,c,e,f){Md(a,b,d,c);lb(a,b,d,c,e,f);c.$$parserName="number";c.$parsers.push(function(a){if(c.$isEmpty(a))return null;if(Mg.test(a))return parseFloat(a)});c.$formatters.push(function(a){if(!c.$isEmpty(a)){if(!T(a))throw nb("numfmt",
|
||||
a);a=a.toString()}return a});if(w(d.min)||d.ngMin){var g;c.$validators.min=function(a){return c.$isEmpty(a)||y(g)||a>=g};d.$observe("min",function(a){w(a)&&!T(a)&&(a=parseFloat(a));g=T(a)&&!isNaN(a)?a:void 0;c.$validate()})}if(w(d.max)||d.ngMax){var h;c.$validators.max=function(a){return c.$isEmpty(a)||y(h)||a<=h};d.$observe("max",function(a){w(a)&&!T(a)&&(a=parseFloat(a));h=T(a)&&!isNaN(a)?a:void 0;c.$validate()})}},url:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);pc(c);c.$$parserName="url";c.$validators.url=
|
||||
function(a,b){var d=a||b;return c.$isEmpty(d)||Kg.test(d)}},email:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);pc(c);c.$$parserName="email";c.$validators.email=function(a,b){var d=a||b;return c.$isEmpty(d)||Lg.test(d)}},radio:function(a,b,d,c){y(d.name)&&b.attr("name",++pb);b.on("click",function(a){b[0].checked&&c.$setViewValue(d.value,a&&a.type)});c.$render=function(){b[0].checked=d.value==c.$viewValue};d.$observe("value",c.$render)},checkbox:function(a,b,d,c,e,f,g,h){var k=Nd(h,a,"ngTrueValue",d.ngTrueValue,
|
||||
!0),l=Nd(h,a,"ngFalseValue",d.ngFalseValue,!1);b.on("click",function(a){c.$setViewValue(b[0].checked,a&&a.type)});c.$render=function(){b[0].checked=c.$viewValue};c.$isEmpty=function(a){return!1===a};c.$formatters.push(function(a){return na(a,k)});c.$parsers.push(function(a){return a?k:l})},hidden:A,button:A,submit:A,reset:A,file:A},Gc=["$browser","$sniffer","$filter","$parse",function(a,b,d,c){return{restrict:"E",require:["?ngModel"],link:{pre:function(e,f,g,h){h[0]&&(Xd[Q(g.type)]||Xd.text)(e,f,
|
||||
g,h[0],b,a,d,c)}}}}],Ng=/^(true|false|\d+)$/,Ue=function(){return{restrict:"A",priority:100,compile:function(a,b){return Ng.test(b.ngValue)?function(a,b,e){e.$set("value",a.$eval(e.ngValue))}:function(a,b,e){a.$watch(e.ngValue,function(a){e.$set("value",a)})}}}},ue=["$compile",function(a){return{restrict:"AC",compile:function(b){a.$$addBindingClass(b);return function(b,c,e){a.$$addBindingInfo(c,e.ngBind);c=c[0];b.$watch(e.ngBind,function(a){c.textContent=y(a)?"":a})}}}}],we=["$interpolate","$compile",
|
||||
function(a,b){return{compile:function(d){b.$$addBindingClass(d);return function(c,d,f){c=a(d.attr(f.$attr.ngBindTemplate));b.$$addBindingInfo(d,c.expressions);d=d[0];f.$observe("ngBindTemplate",function(a){d.textContent=y(a)?"":a})}}}}],ve=["$sce","$parse","$compile",function(a,b,d){return{restrict:"A",compile:function(c,e){var f=b(e.ngBindHtml),g=b(e.ngBindHtml,function(b){return a.valueOf(b)});d.$$addBindingClass(c);return function(b,c,e){d.$$addBindingInfo(c,e.ngBindHtml);b.$watch(g,function(){var d=
|
||||
f(b);c.html(a.getTrustedHtml(d)||"")})}}}}],Te=ha({restrict:"A",require:"ngModel",link:function(a,b,d,c){c.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),xe=qc("",!0),ze=qc("Odd",0),ye=qc("Even",1),Ae=Ta({compile:function(a,b){b.$set("ngCloak",void 0);a.removeClass("ng-cloak")}}),Be=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Lc={},Og={blur:!0,focus:!0};q("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),
|
||||
function(a){var b=Aa("ng-"+a);Lc[b]=["$parse","$rootScope",function(d,c){return{restrict:"A",compile:function(e,f){var g=d(f[b],null,!0);return function(b,d){d.on(a,function(d){var e=function(){g(b,{$event:d})};Og[a]&&c.$$phase?b.$evalAsync(e):b.$apply(e)})}}}}]});var Ee=["$animate","$compile",function(a,b){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(d,c,e,f,g){var h,k,l;d.$watch(e.ngIf,function(d){d?k||g(function(d,f){k=f;d[d.length++]=
|
||||
b.$$createComment("end ngIf",e.ngIf);h={clone:d};a.enter(d,c.parent(),c)}):(l&&(l.remove(),l=null),k&&(k.$destroy(),k=null),h&&(l=tb(h.clone),a.leave(l).then(function(){l=null}),h=null))})}}}],Fe=["$templateRequest","$anchorScroll","$animate",function(a,b,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(c,e){var f=e.ngInclude||e.src,g=e.onload||"",h=e.autoscroll;return function(c,e,m,n,p){var q=0,s,B,r,y=function(){B&&(B.remove(),B=null);s&&
|
||||
(s.$destroy(),s=null);r&&(d.leave(r).then(function(){B=null}),B=r,r=null)};c.$watch(f,function(f){var m=function(){!w(h)||h&&!c.$eval(h)||b()},t=++q;f?(a(f,!0).then(function(a){if(!c.$$destroyed&&t===q){var b=c.$new();n.template=a;a=p(b,function(a){y();d.enter(a,null,e).then(m)});s=b;r=a;s.$emit("$includeContentLoaded",f);c.$eval(g)}},function(){c.$$destroyed||t!==q||(y(),c.$emit("$includeContentError",f))}),c.$emit("$includeContentRequested",f)):(y(),n.template=null)})}}}}],We=["$compile",function(a){return{restrict:"ECA",
|
||||
priority:-400,require:"ngInclude",link:function(b,d,c,e){ma.call(d[0]).match(/SVG/)?(d.empty(),a(Oc(e.template,C.document).childNodes)(b,function(a){d.append(a)},{futureParentElement:d})):(d.html(e.template),a(d.contents())(b))}}}],Ge=Ta({priority:450,compile:function(){return{pre:function(a,b,d){a.$eval(d.ngInit)}}}}),Se=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,b,d,c){var e=b.attr(d.$attr.ngList)||", ",f="false"!==d.ngTrim,g=f?W(e):e;c.$parsers.push(function(a){if(!y(a)){var b=
|
||||
[];a&&q(a.split(g),function(a){a&&b.push(f?W(a):a)});return b}});c.$formatters.push(function(a){if(L(a))return a.join(e)});c.$isEmpty=function(a){return!a||!a.length}}}},ob="ng-valid",Od="ng-invalid",Ua="ng-pristine",Mb="ng-dirty",Qd="ng-pending",nb=N("ngModel"),Pg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,b,d,c,e,f,g,h,k,l){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=void 0;this.$validators={};
|
||||
this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=void 0;this.$name=l(d.name||"",!1)(a);this.$$parentForm=Lb;var m=e(d.ngModel),n=m.assign,p=m,u=n,s=null,B,r=this;this.$$setOptions=function(a){if((r.$options=a)&&a.getterSetter){var b=e(d.ngModel+"()"),f=e(d.ngModel+"($$$p)");p=function(a){var c=m(a);z(c)&&(c=b(a));
|
||||
return c};u=function(a,b){z(m(a))?f(a,{$$$p:b}):n(a,b)}}else if(!m.assign)throw nb("nonassign",d.ngModel,ya(c));};this.$render=A;this.$isEmpty=function(a){return y(a)||""===a||null===a||a!==a};this.$$updateEmptyClasses=function(a){r.$isEmpty(a)?(f.removeClass(c,"ng-not-empty"),f.addClass(c,"ng-empty")):(f.removeClass(c,"ng-empty"),f.addClass(c,"ng-not-empty"))};var J=0;Kd({ctrl:this,$element:c,set:function(a,b){a[b]=!0},unset:function(a,b){delete a[b]},$animate:f});this.$setPristine=function(){r.$dirty=
|
||||
!1;r.$pristine=!0;f.removeClass(c,Mb);f.addClass(c,Ua)};this.$setDirty=function(){r.$dirty=!0;r.$pristine=!1;f.removeClass(c,Ua);f.addClass(c,Mb);r.$$parentForm.$setDirty()};this.$setUntouched=function(){r.$touched=!1;r.$untouched=!0;f.setClass(c,"ng-untouched","ng-touched")};this.$setTouched=function(){r.$touched=!0;r.$untouched=!1;f.setClass(c,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){g.cancel(s);r.$viewValue=r.$$lastCommittedViewValue;r.$render()};this.$validate=function(){if(!T(r.$modelValue)||
|
||||
!isNaN(r.$modelValue)){var a=r.$$rawModelValue,b=r.$valid,c=r.$modelValue,d=r.$options&&r.$options.allowInvalid;r.$$runValidators(a,r.$$lastCommittedViewValue,function(e){d||b===e||(r.$modelValue=e?a:void 0,r.$modelValue!==c&&r.$$writeModelToScope())})}};this.$$runValidators=function(a,b,c){function d(){var c=!0;q(r.$validators,function(d,e){var g=d(a,b);c=c&&g;f(e,g)});return c?!0:(q(r.$asyncValidators,function(a,b){f(b,null)}),!1)}function e(){var c=[],d=!0;q(r.$asyncValidators,function(e,g){var h=
|
||||
e(a,b);if(!h||!z(h.then))throw nb("nopromise",h);f(g,void 0);c.push(h.then(function(){f(g,!0)},function(){d=!1;f(g,!1)}))});c.length?k.all(c).then(function(){g(d)},A):g(!0)}function f(a,b){h===J&&r.$setValidity(a,b)}function g(a){h===J&&c(a)}J++;var h=J;(function(){var a=r.$$parserName||"parse";if(y(B))f(a,null);else return B||(q(r.$validators,function(a,b){f(b,null)}),q(r.$asyncValidators,function(a,b){f(b,null)})),f(a,B),B;return!0})()?d()?e():g(!1):g(!1)};this.$commitViewValue=function(){var a=
|
||||
r.$viewValue;g.cancel(s);if(r.$$lastCommittedViewValue!==a||""===a&&r.$$hasNativeValidators)r.$$updateEmptyClasses(a),r.$$lastCommittedViewValue=a,r.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var b=r.$$lastCommittedViewValue;if(B=y(b)?void 0:!0)for(var c=0;c<r.$parsers.length;c++)if(b=r.$parsers[c](b),y(b)){B=!1;break}T(r.$modelValue)&&isNaN(r.$modelValue)&&(r.$modelValue=p(a));var d=r.$modelValue,e=r.$options&&r.$options.allowInvalid;r.$$rawModelValue=
|
||||
b;e&&(r.$modelValue=b,r.$modelValue!==d&&r.$$writeModelToScope());r.$$runValidators(b,r.$$lastCommittedViewValue,function(a){e||(r.$modelValue=a?b:void 0,r.$modelValue!==d&&r.$$writeModelToScope())})};this.$$writeModelToScope=function(){u(a,r.$modelValue);q(r.$viewChangeListeners,function(a){try{a()}catch(c){b(c)}})};this.$setViewValue=function(a,b){r.$viewValue=a;r.$options&&!r.$options.updateOnDefault||r.$$debounceViewValueCommit(b)};this.$$debounceViewValueCommit=function(b){var c=0,d=r.$options;
|
||||
d&&w(d.debounce)&&(d=d.debounce,T(d)?c=d:T(d[b])?c=d[b]:T(d["default"])&&(c=d["default"]));g.cancel(s);c?s=g(function(){r.$commitViewValue()},c):h.$$phase?r.$commitViewValue():a.$apply(function(){r.$commitViewValue()})};a.$watch(function(){var b=p(a);if(b!==r.$modelValue&&(r.$modelValue===r.$modelValue||b===b)){r.$modelValue=r.$$rawModelValue=b;B=void 0;for(var c=r.$formatters,d=c.length,e=b;d--;)e=c[d](e);r.$viewValue!==e&&(r.$$updateEmptyClasses(e),r.$viewValue=r.$$lastCommittedViewValue=e,r.$render(),
|
||||
r.$$runValidators(b,e,A))}return b})}],Re=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:Pg,priority:1,compile:function(b){b.addClass(Ua).addClass("ng-untouched").addClass(ob);return{pre:function(a,b,e,f){var g=f[0];b=f[1]||g.$$parentForm;g.$$setOptions(f[2]&&f[2].$options);b.$addControl(g);e.$observe("name",function(a){g.$name!==a&&g.$$parentForm.$$renameControl(g,a)});a.$on("$destroy",function(){g.$$parentForm.$removeControl(g)})},post:function(b,
|
||||
c,e,f){var g=f[0];if(g.$options&&g.$options.updateOn)c.on(g.$options.updateOn,function(a){g.$$debounceViewValueCommit(a&&a.type)});c.on("blur",function(){g.$touched||(a.$$phase?b.$evalAsync(g.$setTouched):b.$apply(g.$setTouched))})}}}}}],Qg=/(\s+|^)default(\s+|$)/,Ve=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,b){var d=this;this.$options=pa(a.$eval(b.ngModelOptions));w(this.$options.updateOn)?(this.$options.updateOnDefault=!1,this.$options.updateOn=W(this.$options.updateOn.replace(Qg,
|
||||
function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},He=Ta({terminal:!0,priority:1E3}),Rg=N("ngOptions"),Sg=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,Pe=["$compile","$document","$parse",function(a,b,d){function c(a,b,c){function e(a,b,c,d,f){this.selectValue=a;this.viewValue=
|
||||
b;this.label=c;this.group=d;this.disabled=f}function f(a){var b;if(!q&&ta(a))b=a;else{b=[];for(var c in a)a.hasOwnProperty(c)&&"$"!==c.charAt(0)&&b.push(c)}return b}var n=a.match(Sg);if(!n)throw Rg("iexp",a,ya(b));var p=n[5]||n[7],q=n[6];a=/ as /.test(n[0])&&n[1];var s=n[9];b=d(n[2]?n[1]:p);var w=a&&d(a)||b,r=s&&d(s),y=s?function(a,b){return r(c,b)}:function(a){return Ca(a)},v=function(a,b){return y(a,E(a,b))},A=d(n[2]||n[1]),t=d(n[3]||""),K=d(n[4]||""),z=d(n[8]),H={},E=q?function(a,b){H[q]=b;H[p]=
|
||||
a;return H}:function(a){H[p]=a;return H};return{trackBy:s,getTrackByValue:v,getWatchables:d(z,function(a){var b=[];a=a||[];for(var d=f(a),e=d.length,g=0;g<e;g++){var h=a===d?g:d[g],l=a[h],h=E(l,h),l=y(l,h);b.push(l);if(n[2]||n[1])l=A(c,h),b.push(l);n[4]&&(h=K(c,h),b.push(h))}return b}),getOptions:function(){for(var a=[],b={},d=z(c)||[],g=f(d),h=g.length,n=0;n<h;n++){var p=d===g?n:g[n],q=E(d[p],p),r=w(c,q),p=y(r,q),u=A(c,q),H=t(c,q),q=K(c,q),r=new e(p,r,u,H,q);a.push(r);b[p]=r}return{items:a,selectValueMap:b,
|
||||
getOptionFromViewValue:function(a){return b[v(a)]},getViewValueFromOption:function(a){return s?ca.copy(a.viewValue):a.viewValue}}}}}var e=C.document.createElement("option"),f=C.document.createElement("optgroup");return{restrict:"A",terminal:!0,require:["select","ngModel"],link:{pre:function(a,b,c,d){d[0].registerOption=A},post:function(d,h,k,l){function m(a,b){a.element=b;b.disabled=a.disabled;a.label!==b.label&&(b.label=a.label,b.textContent=a.label);a.value!==b.value&&(b.value=a.selectValue)}function n(){var a=
|
||||
t&&p.readValue();if(t)for(var b=t.items.length-1;0<=b;b--){var c=t.items[b];w(c.group)?Db(c.element.parentNode):Db(c.element)}t=K.getOptions();var d={};v&&h.prepend(B);t.items.forEach(function(a){var b;if(w(a.group)){b=d[a.group];b||(b=f.cloneNode(!1),C.appendChild(b),b.label=null===a.group?"null":a.group,d[a.group]=b);var c=e.cloneNode(!1)}else b=C,c=e.cloneNode(!1);b.appendChild(c);m(a,c)});h[0].appendChild(C);s.$render();s.$isEmpty(a)||(b=p.readValue(),(K.trackBy||y?na(a,b):a===b)||(s.$setViewValue(b),
|
||||
s.$render()))}var p=l[0],s=l[1],y=k.multiple,B;l=0;for(var r=h.children(),A=r.length;l<A;l++)if(""===r[l].value){B=r.eq(l);break}var v=!!B,z=F(e.cloneNode(!1));z.val("?");var t,K=c(k.ngOptions,h,d),C=b[0].createDocumentFragment();y?(s.$isEmpty=function(a){return!a||0===a.length},p.writeValue=function(a){t.items.forEach(function(a){a.element.selected=!1});a&&a.forEach(function(a){if(a=t.getOptionFromViewValue(a))a.element.selected=!0})},p.readValue=function(){var a=h.val()||[],b=[];q(a,function(a){(a=
|
||||
t.selectValueMap[a])&&!a.disabled&&b.push(t.getViewValueFromOption(a))});return b},K.trackBy&&d.$watchCollection(function(){if(L(s.$viewValue))return s.$viewValue.map(function(a){return K.getTrackByValue(a)})},function(){s.$render()})):(p.writeValue=function(a){var b=t.getOptionFromViewValue(a);b?(h[0].value!==b.selectValue&&(z.remove(),v||B.remove(),h[0].value=b.selectValue,b.element.selected=!0),b.element.setAttribute("selected","selected")):null===a||v?(z.remove(),v||h.prepend(B),h.val(""),B.prop("selected",
|
||||
!0),B.attr("selected",!0)):(v||B.remove(),h.prepend(z),h.val("?"),z.prop("selected",!0),z.attr("selected",!0))},p.readValue=function(){var a=t.selectValueMap[h.val()];return a&&!a.disabled?(v||B.remove(),z.remove(),t.getViewValueFromOption(a)):null},K.trackBy&&d.$watch(function(){return K.getTrackByValue(s.$viewValue)},function(){s.$render()}));v?(B.remove(),a(B)(d),B.removeClass("ng-scope")):B=F(e.cloneNode(!1));h.empty();n();d.$watchCollection(K.getWatchables,n)}}}}],Ie=["$locale","$interpolate",
|
||||
"$log",function(a,b,d){var c=/{}/g,e=/^when(Minus)?(.+)$/;return{link:function(f,g,h){function k(a){g.text(a||"")}var l=h.count,m=h.$attr.when&&g.attr(h.$attr.when),n=h.offset||0,p=f.$eval(m)||{},s={},w=b.startSymbol(),B=b.endSymbol(),r=w+l+"-"+n+B,z=ca.noop,v;q(h,function(a,b){var c=e.exec(b);c&&(c=(c[1]?"-":"")+Q(c[2]),p[c]=g.attr(h.$attr[b]))});q(p,function(a,d){s[d]=b(a.replace(c,r))});f.$watch(l,function(b){var c=parseFloat(b),e=isNaN(c);e||c in p||(c=a.pluralCat(c-n));c===v||e&&T(v)&&isNaN(v)||
|
||||
(z(),e=s[c],y(e)?(null!=b&&d.debug("ngPluralize: no rule defined for '"+c+"' in "+m),z=A,k()):z=f.$watch(e,k),v=c)})}}}],Je=["$parse","$animate","$compile",function(a,b,d){var c=N("ngRepeat"),e=function(a,b,c,d,e,m,n){a[c]=d;e&&(a[e]=m);a.$index=b;a.$first=0===b;a.$last=b===n-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(b&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,k=d.$$createComment("end ngRepeat",
|
||||
h),l=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!l)throw c("iexp",h);var m=l[1],n=l[2],p=l[3],s=l[4],l=m.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);if(!l)throw c("iidexp",m);var w=l[3]||l[1],y=l[2];if(p&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(p)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(p)))throw c("badident",p);var r,z,v,A,t={$id:Ca};s?r=a(s):(v=function(a,b){return Ca(b)},
|
||||
A=function(a){return a});return function(a,d,f,g,l){r&&(z=function(b,c,d){y&&(t[y]=b);t[w]=c;t.$index=d;return r(a,t)});var m=U();a.$watchCollection(n,function(f){var g,n,r=d[0],s,u=U(),t,C,F,E,G,D,H;p&&(a[p]=f);if(ta(f))G=f,n=z||v;else for(H in n=z||A,G=[],f)ua.call(f,H)&&"$"!==H.charAt(0)&&G.push(H);t=G.length;H=Array(t);for(g=0;g<t;g++)if(C=f===G?g:G[g],F=f[C],E=n(C,F,g),m[E])D=m[E],delete m[E],u[E]=D,H[g]=D;else{if(u[E])throw q(H,function(a){a&&a.scope&&(m[a.id]=a)}),c("dupes",h,E,F);H[g]={id:E,
|
||||
scope:void 0,clone:void 0};u[E]=!0}for(s in m){D=m[s];E=tb(D.clone);b.leave(E);if(E[0].parentNode)for(g=0,n=E.length;g<n;g++)E[g].$$NG_REMOVED=!0;D.scope.$destroy()}for(g=0;g<t;g++)if(C=f===G?g:G[g],F=f[C],D=H[g],D.scope){s=r;do s=s.nextSibling;while(s&&s.$$NG_REMOVED);D.clone[0]!=s&&b.move(tb(D.clone),null,r);r=D.clone[D.clone.length-1];e(D.scope,g,w,F,y,C,t)}else l(function(a,c){D.scope=c;var d=k.cloneNode(!1);a[a.length++]=d;b.enter(a,null,r);r=d;D.clone=a;u[D.id]=D;e(D.scope,g,w,F,y,C,t)});m=
|
||||
u})}}}}],Ke=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(b,d,c){b.$watch(c.ngShow,function(b){a[b?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],De=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(b,d,c){b.$watch(c.ngHide,function(b){a[b?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Le=Ta(function(a,b,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&q(d,function(a,c){b.css(c,"")});a&&b.css(a)},
|
||||
!0)}),Me=["$animate","$compile",function(a,b){return{require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(d,c,e,f){var g=[],h=[],k=[],l=[],m=function(a,b){return function(){a.splice(b,1)}};d.$watch(e.ngSwitch||e.on,function(c){var d,e;d=0;for(e=k.length;d<e;++d)a.cancel(k[d]);d=k.length=0;for(e=l.length;d<e;++d){var s=tb(h[d].clone);l[d].$destroy();(k[d]=a.leave(s)).then(m(k,d))}h.length=0;l.length=0;(g=f.cases["!"+c]||f.cases["?"])&&q(g,function(c){c.transclude(function(d,
|
||||
e){l.push(e);var f=c.element;d[d.length++]=b.$$createComment("end ngSwitchWhen");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],Ne=Ta({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,b,d,c,e){c.cases["!"+d.ngSwitchWhen]=c.cases["!"+d.ngSwitchWhen]||[];c.cases["!"+d.ngSwitchWhen].push({transclude:e,element:b})}}),Oe=Ta({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,b,d,c,e){c.cases["?"]=c.cases["?"]||[];c.cases["?"].push({transclude:e,
|
||||
element:b})}}),Tg=N("ngTransclude"),Qe=["$compile",function(a){return{restrict:"EAC",terminal:!0,compile:function(b){var d=a(b.contents());b.empty();return function(a,b,f,g,h){function k(){d(a,function(a){b.append(a)})}if(!h)throw Tg("orphan",ya(b));f.ngTransclude===f.$attr.ngTransclude&&(f.ngTransclude="");f=f.ngTransclude||f.ngTranscludeSlot;h(function(a,c){a.length?b.append(a):(k(),c.$destroy())},null,f);f&&!h.isSlotFilled(f)&&k()}}}}],qe=["$templateCache",function(a){return{restrict:"E",terminal:!0,
|
||||
compile:function(b,d){"text/ng-template"==d.type&&a.put(d.id,b[0].text)}}}],Ug={$setViewValue:A,$render:A},Vg=["$element","$scope",function(a,b){var d=this,c=new Ra;d.ngModelCtrl=Ug;d.unknownOption=F(C.document.createElement("option"));d.renderUnknownOption=function(b){b="? "+Ca(b)+" ?";d.unknownOption.val(b);a.prepend(d.unknownOption);a.val(b)};b.$on("$destroy",function(){d.renderUnknownOption=A});d.removeUnknownOption=function(){d.unknownOption.parent()&&d.unknownOption.remove()};d.readValue=function(){d.removeUnknownOption();
|
||||
return a.val()};d.writeValue=function(b){d.hasOption(b)?(d.removeUnknownOption(),a.val(b),""===b&&d.emptyOption.prop("selected",!0)):null==b&&d.emptyOption?(d.removeUnknownOption(),a.val("")):d.renderUnknownOption(b)};d.addOption=function(a,b){if(8!==b[0].nodeType){Qa(a,'"option value"');""===a&&(d.emptyOption=b);var g=c.get(a)||0;c.put(a,g+1);d.ngModelCtrl.$render();b[0].hasAttribute("selected")&&(b[0].selected=!0)}};d.removeOption=function(a){var b=c.get(a);b&&(1===b?(c.remove(a),""===a&&(d.emptyOption=
|
||||
void 0)):c.put(a,b-1))};d.hasOption=function(a){return!!c.get(a)};d.registerOption=function(a,b,c,h,k){if(h){var l;c.$observe("value",function(a){w(l)&&d.removeOption(l);l=a;d.addOption(a,b)})}else k?a.$watch(k,function(a,e){c.$set("value",a);e!==a&&d.removeOption(e);d.addOption(a,b)}):d.addOption(c.value,b);b.on("$destroy",function(){d.removeOption(c.value);d.ngModelCtrl.$render()})}}],re=function(){return{restrict:"E",require:["select","?ngModel"],controller:Vg,priority:1,link:{pre:function(a,b,
|
||||
d,c){var e=c[1];if(e){var f=c[0];f.ngModelCtrl=e;b.on("change",function(){a.$apply(function(){e.$setViewValue(f.readValue())})});if(d.multiple){f.readValue=function(){var a=[];q(b.find("option"),function(b){b.selected&&a.push(b.value)});return a};f.writeValue=function(a){var c=new Ra(a);q(b.find("option"),function(a){a.selected=w(c.get(a.value))})};var g,h=NaN;a.$watch(function(){h!==e.$viewValue||na(g,e.$viewValue)||(g=ia(e.$viewValue),e.$render());h=e.$viewValue});e.$isEmpty=function(a){return!a||
|
||||
0===a.length}}}},post:function(a,b,d,c){var e=c[1];if(e){var f=c[0];e.$render=function(){f.writeValue(e.$viewValue)}}}}}},te=["$interpolate",function(a){return{restrict:"E",priority:100,compile:function(b,d){if(w(d.value))var c=a(d.value,!0);else{var e=a(b.text(),!0);e||d.$set("value",b.text())}return function(a,b,d){var k=b.parent();(k=k.data("$selectController")||k.parent().data("$selectController"))&&k.registerOption(a,b,d,c,e)}}}}],se=ha({restrict:"E",terminal:!1}),Ic=function(){return{restrict:"A",
|
||||
require:"?ngModel",link:function(a,b,d,c){c&&(d.required=!0,c.$validators.required=function(a,b){return!d.required||!c.$isEmpty(b)},d.$observe("required",function(){c.$validate()}))}}},Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e,f=d.ngPattern||d.pattern;d.$observe("pattern",function(a){G(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw N("ngPattern")("noregexp",f,a,ya(b));e=a||void 0;c.$validate()});c.$validators.pattern=function(a,b){return c.$isEmpty(b)||
|
||||
y(e)||e.test(b)}}}}},Kc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=-1;d.$observe("maxlength",function(a){a=Z(a);e=isNaN(a)?-1:a;c.$validate()});c.$validators.maxlength=function(a,b){return 0>e||c.$isEmpty(b)||b.length<=e}}}}},Jc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=0;d.$observe("minlength",function(a){e=Z(a)||0;c.$validate()});c.$validators.minlength=function(a,b){return c.$isEmpty(b)||b.length>=e}}}}};C.angular.bootstrap?
|
||||
C.console&&console.log("WARNING: Tried to load angular more than once."):(je(),le(ca),ca.module("ngLocale",[],["$provide",function(a){function b(a){a+="";var b=a.indexOf(".");return-1==b?0:a.length-b-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),
|
||||
SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",
|
||||
PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-\u00a4",negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(a,c){var e=a|0,f=c;void 0===f&&(f=Math.min(b(a),3));Math.pow(10,f);return 1==e&&0==f?"one":"other"}})}]),F(C.document).ready(function(){fe(C.document,Bc)}))})(window);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
|
||||
//# sourceMappingURL=angular.min.js.map
|
||||
1
dashboard/public/js/async-3.2.0.min.js
vendored
7
dashboard/public/js/clipboard.min.js
vendored
@@ -1,854 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/* global $, async, angular, redirectIfNeeded */
|
||||
/* global ERROR,ISTATES,HSTATES,RSTATES,APP_TYPES,NOTIFICATION_TYPES */
|
||||
|
||||
// deal with accessToken in the query, this is passed for example on password reset and account setup upon invite
|
||||
var search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.split('='); }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {});
|
||||
if (search.accessToken) {
|
||||
localStorage.token = search.accessToken;
|
||||
|
||||
// strip the accessToken and expiresAt, then preserve the rest
|
||||
delete search.accessToken;
|
||||
delete search.expiresAt;
|
||||
|
||||
// this will reload the page as this is not a hash change
|
||||
window.location.search = encodeURIComponent(Object.keys(search).map(function (key) { return key + '=' + search[key]; }).join('&'));
|
||||
}
|
||||
|
||||
// create main application module
|
||||
var app = angular.module('Application', ['pascalprecht.translate', 'ngCookies', 'ngFitText', 'ngRoute', 'ngAnimate', 'ngSanitize', 'angular-md5', 'base64', 'slick', 'ui-notification', 'ui.bootstrap', 'ui.multiselect']);
|
||||
|
||||
app.config(['NotificationProvider', function (NotificationProvider) {
|
||||
NotificationProvider.setOptions({
|
||||
delay: 5000,
|
||||
startTop: 60,
|
||||
positionX: 'left',
|
||||
templateUrl: 'notification.html'
|
||||
});
|
||||
}]);
|
||||
|
||||
// configure resourceUrlWhitelist https://code.angularjs.org/1.5.8/docs/api/ng/provider/$sceDelegateProvider#resourceUrlWhitelist
|
||||
app.config(function ($sceDelegateProvider) {
|
||||
$sceDelegateProvider.resourceUrlWhitelist([
|
||||
// Allow same origin resource loads.
|
||||
'self',
|
||||
// Allow loading from our assets domain.
|
||||
'https://cloudron.io/**',
|
||||
'https://staging.cloudron.io/**',
|
||||
'https://dev.cloudron.io/**',
|
||||
// Allow local development against the appstore pages
|
||||
'http://localhost:5000/**'
|
||||
]);
|
||||
});
|
||||
|
||||
// setup all major application routes
|
||||
app.config(['$routeProvider', function ($routeProvider) {
|
||||
$routeProvider.when('/', {
|
||||
redirectTo: '/apps'
|
||||
}).when('/users', {
|
||||
controller: 'UsersController',
|
||||
templateUrl: 'views/users.html?' + window.VITE_CACHE_ID
|
||||
}).when('/user-directory', {
|
||||
controller: 'UserSettingsController',
|
||||
templateUrl: 'views/user-directory.html?' + window.VITE_CACHE_ID
|
||||
}).when('/app/:appId/:view?', {
|
||||
controller: 'AppController',
|
||||
templateUrl: 'views/app.html?' + window.VITE_CACHE_ID
|
||||
}).when('/appstore', {
|
||||
controller: 'AppStoreController',
|
||||
templateUrl: 'views/appstore.html?' + window.VITE_CACHE_ID
|
||||
}).when('/appstore/:appId', {
|
||||
controller: 'AppStoreController',
|
||||
templateUrl: 'views/appstore.html?' + window.VITE_CACHE_ID
|
||||
}).when('/apps', {
|
||||
controller: 'AppsController',
|
||||
templateUrl: 'views/apps.html?' + window.VITE_CACHE_ID
|
||||
}).when('/profile', {
|
||||
controller: 'ProfileController',
|
||||
templateUrl: 'views/profile.html?' + window.VITE_CACHE_ID
|
||||
}).when('/backups', {
|
||||
controller: 'BackupsController',
|
||||
templateUrl: 'views/backups.html?' + window.VITE_CACHE_ID
|
||||
}).when('/branding', {
|
||||
controller: 'BrandingController',
|
||||
templateUrl: 'views/branding.html?' + window.VITE_CACHE_ID
|
||||
}).when('/network', {
|
||||
controller: 'NetworkController',
|
||||
templateUrl: 'views/network.html?' + window.VITE_CACHE_ID
|
||||
}).when('/domains', {
|
||||
controller: 'DomainsController',
|
||||
templateUrl: 'views/domains.html?' + window.VITE_CACHE_ID
|
||||
}).when('/email', {
|
||||
controller: 'EmailsController',
|
||||
templateUrl: 'views/emails.html?' + window.VITE_CACHE_ID
|
||||
}).when('/emails-eventlog', {
|
||||
controller: 'EmailsEventlogController',
|
||||
templateUrl: 'views/emails-eventlog.html?' + window.VITE_CACHE_ID
|
||||
}).when('/emails-queue', {
|
||||
controller: 'EmailsQueueController',
|
||||
templateUrl: 'views/emails-queue.html?' + window.VITE_CACHE_ID
|
||||
}).when('/email/:domain/:view?', {
|
||||
controller: 'EmailController',
|
||||
templateUrl: 'views/email.html?' + window.VITE_CACHE_ID
|
||||
}).when('/notifications', {
|
||||
controller: 'NotificationsController',
|
||||
templateUrl: 'views/notifications.html?' + window.VITE_CACHE_ID
|
||||
}).when('/oidc', {
|
||||
redirectTo: '/user-directory'
|
||||
}).when('/settings', {
|
||||
controller: 'SettingsController',
|
||||
templateUrl: 'views/settings.html?' + window.VITE_CACHE_ID
|
||||
}).when('/eventlog', {
|
||||
controller: 'EventLogController',
|
||||
templateUrl: 'views/eventlog.html?' + window.VITE_CACHE_ID
|
||||
}).when('/support', {
|
||||
controller: 'SupportController',
|
||||
templateUrl: 'views/support.html?' + window.VITE_CACHE_ID
|
||||
}).when('/system', {
|
||||
controller: 'SystemController',
|
||||
templateUrl: 'views/system.html?' + window.VITE_CACHE_ID
|
||||
}).when('/services', {
|
||||
controller: 'ServicesController',
|
||||
templateUrl: 'views/services.html?' + window.VITE_CACHE_ID
|
||||
}).when('/volumes', {
|
||||
controller: 'VolumesController',
|
||||
templateUrl: 'views/volumes.html?' + window.VITE_CACHE_ID
|
||||
}).otherwise({ redirectTo: '/'});
|
||||
}]);
|
||||
|
||||
app.filter('notificationTypeToColor', function () {
|
||||
return function (n) {
|
||||
switch (n.type) {
|
||||
case NOTIFICATION_TYPES.REBOOT:
|
||||
case NOTIFICATION_TYPES.APP_OOM:
|
||||
case NOTIFICATION_TYPES.MAIL_STATUS:
|
||||
case NOTIFICATION_TYPES.CERTIFICATE_RENEWAL_FAILED:
|
||||
case NOTIFICATION_TYPES.DISK_SPACE:
|
||||
case NOTIFICATION_TYPES.BACKUP_CONFIG:
|
||||
case NOTIFICATION_TYPES.BACKUP_FAILED:
|
||||
return '#ff4c4c';
|
||||
case NOTIFICATION_TYPES.BOX_UPDATE:
|
||||
case NOTIFICATION_TYPES.MANUAL_APP_UPDATE:
|
||||
return '#f0ad4e';
|
||||
default:
|
||||
return '#2196f3';
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('capitalize', function () {
|
||||
return function (s) {
|
||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('activeTask', function () {
|
||||
return function (app) {
|
||||
if (!app) return false;
|
||||
return app.taskId !== null;
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('installSuccess', function () {
|
||||
return function (app) {
|
||||
if (!app) return false;
|
||||
return app.installationState === ISTATES.INSTALLED;
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('appIsInstalledAndHealthy', function () {
|
||||
return function (app) {
|
||||
if (!app) return false;
|
||||
return (app.installationState === ISTATES.INSTALLED && app.health === HSTATES.HEALTHY && app.runState === RSTATES.RUNNING);
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('applicationLink', function () {
|
||||
return function(app) {
|
||||
if (!app) return '';
|
||||
|
||||
// app links have http already in the fqdn
|
||||
if (app.fqdn.indexOf('http') !== 0) return 'https://' + app.fqdn;
|
||||
|
||||
return app.fqdn;
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('userManagementFilter', function () {
|
||||
return function(apps, option) {
|
||||
return apps.filter(function (app) {
|
||||
if (option.id === '') return true;
|
||||
if (option.id === 'sso') return !!(app.manifest.optionalSso || app.manifest.addons.ldap || app.manifest.addons.proxyAuth);
|
||||
if (option.id === 'nosso') return app.manifest.optionalSso || (!app.manifest.addons.ldap && !app.manifest.addons.proxyAuth);
|
||||
if (option.id === 'email') return !!app.manifest.addons.email;
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
// this appears when an item in app grid is clicked
|
||||
app.filter('prettyAppErrorMessage', function () {
|
||||
return function (app) {
|
||||
if (!app) return '';
|
||||
|
||||
if (app.installationState === ISTATES.INSTALLED) {
|
||||
// app.health can also be null to indicate insufficient data
|
||||
if (app.health === HSTATES.UNHEALTHY) return 'The app is not responding to health checks. Check the logs for any error messages.';
|
||||
}
|
||||
|
||||
if (app.error.reason === 'Access Denied') {
|
||||
if (app.error.domain) return 'The DNS record for this location is not setup correctly. Please verify your DNS settings and repair this app.';
|
||||
} else if (app.error.reason === 'Already Exists') {
|
||||
if (app.error.domain) return 'The DNS record for this location already exists. Cloudron does not remove existing DNS records. Manually remove the DNS record and then click on repair.';
|
||||
}
|
||||
|
||||
return app.error.message;
|
||||
};
|
||||
});
|
||||
|
||||
// this appears as tool tip in app grid
|
||||
app.filter('appProgressMessage', function () {
|
||||
return function (app) {
|
||||
var message = app.message || (app.error ? app.error.message : '');
|
||||
return message;
|
||||
};
|
||||
});
|
||||
|
||||
// see apps.js $scope.states
|
||||
app.filter('selectedStateFilter', ['Client', function (Client) {
|
||||
return function selectedStateFilter(apps, selectedState) {
|
||||
return apps.filter(function (app) {
|
||||
if (!selectedState || !selectedState.state) return true;
|
||||
|
||||
if (selectedState.state === 'running') return app.runState === RSTATES.RUNNING && app.health === HSTATES.HEALTHY && app.installationState === ISTATES.INSTALLED;
|
||||
if (selectedState.state === 'stopped') return app.runState === RSTATES.STOPPED;
|
||||
if (selectedState.state === 'update_available') return !!(Client.getConfig().update[app.id] && Client.getConfig().update[app.id].manifest.version && Client.getConfig().update[app.id].manifest.version !== app.manifest.version);
|
||||
|
||||
return app.runState === RSTATES.RUNNING && (app.health !== HSTATES.HEALTHY || app.installationState !== ISTATES.INSTALLED); // not responding
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
||||
app.filter('selectedGroupAccessFilter', function () {
|
||||
return function selectedGroupAccessFilter(apps, group) {
|
||||
return apps.filter(function (app) {
|
||||
if (!group.id) return true; // case for no filter entry
|
||||
if (!app.accessRestriction) return true;
|
||||
|
||||
if (!app.accessRestriction.groups) return false;
|
||||
|
||||
if (app.accessRestriction.groups.indexOf(group.id) !== -1) return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('selectedTagFilter', function () {
|
||||
return function selectedTagFilter(apps, selectedTags) {
|
||||
return apps.filter(function (app) {
|
||||
if (selectedTags.length === 0) return true;
|
||||
if (!app.tags) return false;
|
||||
|
||||
for (var i = 0; i < selectedTags.length; i++) {
|
||||
if (app.tags.indexOf(selectedTags[i]) === -1) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('selectedDomainFilter', function () {
|
||||
return function selectedDomainFilter(apps, selectedDomain) {
|
||||
return apps.filter(function (app) {
|
||||
if (selectedDomain._alldomains) return true; // magic domain for single select, see apps.js ALL_DOMAINS_DOMAIN
|
||||
if (app.type === APP_TYPES.LINK) return false;
|
||||
|
||||
if (selectedDomain.domain === app.domain) return true;
|
||||
if (app.aliasDomains.find(function (ad) { return ad.domain === selectedDomain.domain; })) return true;
|
||||
if (app.redirectDomains.find(function (ad) { return ad.domain === selectedDomain.domain; })) return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('appSearchFilter', function () {
|
||||
return function appSearchFilter(apps, appSearch) {
|
||||
return apps.filter(function (app) {
|
||||
if (!appSearch) return true;
|
||||
appSearch = appSearch.toLowerCase();
|
||||
return app.fqdn.indexOf(appSearch) !== -1
|
||||
|| (app.label && app.label.toLowerCase().indexOf(appSearch) !== -1)
|
||||
|| (app.manifest.title && app.manifest.title.toLowerCase().indexOf(appSearch) !== -1)
|
||||
|| (appSearch.length >=6 && app.id.indexOf(appSearch) !== -1);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('prettyDomains', function () {
|
||||
return function prettyDomains(domains) {
|
||||
return domains.map(function (d) { return d.domain; }).join(', ');
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('installationActive', function () {
|
||||
return function (app) {
|
||||
if (app.installationState === ISTATES.ERROR) return false;
|
||||
if (app.installationState === ISTATES.INSTALLED) return false;
|
||||
return true;
|
||||
};
|
||||
});
|
||||
|
||||
// color indicator in app list
|
||||
app.filter('installationStateClass', function () {
|
||||
const ERROR_CLASS = 'status-error';
|
||||
const BUSY_CLASS = 'status-starting fa-beat-fade';
|
||||
const INACTIVE_CLASS = 'status-inactive';
|
||||
const ACTIVE_CLASS = 'status-active';
|
||||
|
||||
return function(app) {
|
||||
if (!app) return '';
|
||||
|
||||
switch (app.installationState) {
|
||||
case ISTATES.ERROR: return ERROR_CLASS;
|
||||
case ISTATES.INSTALLED: {
|
||||
if (app.debugMode) {
|
||||
return INACTIVE_CLASS;
|
||||
} else {
|
||||
if (app.runState === RSTATES.RUNNING) {
|
||||
if (!app.health) return BUSY_CLASS; // no data yet
|
||||
if (app.type === APP_TYPES.LINK || app.health === HSTATES.HEALTHY) return ACTIVE_CLASS;
|
||||
return ERROR_CLASS; // dead/exit/unhealthy
|
||||
} else {
|
||||
return INACTIVE_CLASS;
|
||||
}
|
||||
}
|
||||
}
|
||||
default: return BUSY_CLASS;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// this appears in the app grid
|
||||
app.filter('installationStateLabel', function () {
|
||||
return function(app) {
|
||||
if (!app) return '';
|
||||
|
||||
var waiting = app.progress === 0 ? ' (Queued)' : '';
|
||||
|
||||
switch (app.installationState) {
|
||||
case ISTATES.PENDING_INSTALL:
|
||||
return 'Installing' + waiting;
|
||||
case ISTATES.PENDING_CLONE:
|
||||
return 'Cloning' + waiting;
|
||||
case ISTATES.PENDING_LOCATION_CHANGE:
|
||||
case ISTATES.PENDING_CONFIGURE:
|
||||
case ISTATES.PENDING_RECREATE_CONTAINER:
|
||||
case ISTATES.PENDING_SERVICES_CHANGE:
|
||||
case ISTATES.PENDING_DEBUG:
|
||||
return 'Configuring' + waiting;
|
||||
case ISTATES.PENDING_RESIZE:
|
||||
return 'Resizing' + waiting;
|
||||
case ISTATES.PENDING_DATA_DIR_MIGRATION:
|
||||
return 'Migrating data' + waiting;
|
||||
case ISTATES.PENDING_UNINSTALL: return 'Uninstalling' + waiting;
|
||||
case ISTATES.PENDING_RESTORE: return 'Restoring' + waiting;
|
||||
case ISTATES.PENDING_IMPORT: return 'Importing' + waiting;
|
||||
case ISTATES.PENDING_UPDATE: return 'Updating' + waiting;
|
||||
case ISTATES.PENDING_BACKUP: return 'Backing up' + waiting;
|
||||
case ISTATES.PENDING_START: return 'Starting' + waiting;
|
||||
case ISTATES.PENDING_STOP: return 'Stopping' + waiting;
|
||||
case ISTATES.PENDING_RESTART: return 'Restarting' + waiting;
|
||||
case ISTATES.ERROR: {
|
||||
if (app.error && app.error.message === 'ETRYAGAIN') return 'DNS Error';
|
||||
return 'Error';
|
||||
}
|
||||
case ISTATES.INSTALLED: {
|
||||
if (app.debugMode) {
|
||||
return 'Recovery Mode';
|
||||
} else if (app.runState === RSTATES.RUNNING) {
|
||||
if (!app.health) return 'Starting...'; // no data yet
|
||||
if (app.type === APP_TYPES.LINK) return '';
|
||||
if (app.health === HSTATES.HEALTHY) return 'Running';
|
||||
return 'Not responding'; // dead/exit/unhealthy
|
||||
} else if (app.runState === RSTATES.STOPPED) return 'Stopped';
|
||||
else return app.runState;
|
||||
}
|
||||
default: return app.installationState;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('taskName', function () {
|
||||
return function(installationState) {
|
||||
switch (installationState) {
|
||||
case ISTATES.PENDING_INSTALL: return 'install';
|
||||
case ISTATES.PENDING_CLONE: return 'clone';
|
||||
case ISTATES.PENDING_LOCATION_CHANGE: return 'location change';
|
||||
case ISTATES.PENDING_CONFIGURE: return 'configure';
|
||||
case ISTATES.PENDING_RECREATE_CONTAINER: return 'create container';
|
||||
case ISTATES.PENDING_DEBUG: return 'debug';
|
||||
case ISTATES.PENDING_RESIZE: return 'resize';
|
||||
case ISTATES.PENDING_DATA_DIR_MIGRATION: return 'data migration';
|
||||
case ISTATES.PENDING_UNINSTALL: return 'uninstall';
|
||||
case ISTATES.PENDING_RESTORE: return 'restore';
|
||||
case ISTATES.PENDING_IMPORT: return 'import';
|
||||
case ISTATES.PENDING_UPDATE: return 'update';
|
||||
case ISTATES.PENDING_BACKUP: return 'backup';
|
||||
case ISTATES.PENDING_START: return 'start app';
|
||||
case ISTATES.PENDING_STOP: return 'stop app';
|
||||
case ISTATES.PENDING_RESTART: return 'restart app';
|
||||
default: return installationState || '';
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('errorSuggestion', function () {
|
||||
return function (error) {
|
||||
if (!error) return '';
|
||||
|
||||
switch (error.reason) {
|
||||
case ERROR.ACCESS_DENIED:
|
||||
if (error.domain) return 'Check the DNS credentials of ' + error.domain.domain + ' in the Domains & Certs view';
|
||||
return '';
|
||||
case ERROR.COLLECTD_ERROR: return 'Check if collectd is running on the server';
|
||||
case ERROR.DATABASE_ERROR: return 'Check if MySQL database is running on the server';
|
||||
case ERROR.DOCKER_ERROR: return 'Check if docker is running on the server';
|
||||
case ERROR.DNS_ERROR: return 'Check if the DNS service of the domain is running';
|
||||
case ERROR.LOGROTATE_ERROR: return 'Check if logrotate is running on the server';
|
||||
case ERROR.NETWORK_ERROR: return 'Check if there are any network issues on the server';
|
||||
case ERROR.REVERSEPROXY_ERROR: return 'Check if nginx is running on the server';
|
||||
default: return '';
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('canUpdate', function () {
|
||||
return function (apps) {
|
||||
return apps.every(function (app) {
|
||||
return (app.installationState === ISTATES.ERROR) || (app.installationState === ISTATES.INSTALLED);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('inProgressApps', function () {
|
||||
return function (apps) {
|
||||
return apps.filter(function (app) {
|
||||
return app.installationState !== ISTATES.ERROR && app.installationState !== ISTATES.INSTALLED;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('prettyHref', function () {
|
||||
return function (input) {
|
||||
if (!input) return input;
|
||||
if (input.indexOf('http://') === 0) return input.slice('http://'.length);
|
||||
if (input.indexOf('https://') === 0) return input.slice('https://'.length);
|
||||
return input;
|
||||
};
|
||||
});
|
||||
|
||||
app.filter('prettyEmailAddresses', function () {
|
||||
return function prettyEmailAddresses(addresses) {
|
||||
if (!addresses) return '';
|
||||
if (addresses === '<>') return '<>';
|
||||
if (Array.isArray(addresses)) return addresses.map(function (a) { return a.slice(1, -1); }).join(', ');
|
||||
return addresses.slice(1, -1);
|
||||
};
|
||||
});
|
||||
|
||||
// custom directive for dynamic names in forms
|
||||
// See http://stackoverflow.com/questions/23616578/issue-registering-form-control-with-interpolated-name#answer-23617401
|
||||
app.directive('laterName', function () { // (2)
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: ['?ngModel', '^?form'], // (3)
|
||||
link: function postLink(scope, elem, attrs, ctrls) {
|
||||
attrs.$set('name', attrs.laterName);
|
||||
|
||||
var modelCtrl = ctrls[0]; // (3)
|
||||
var formCtrl = ctrls[1]; // (3)
|
||||
if (modelCtrl && formCtrl) {
|
||||
modelCtrl.$name = attrs.name; // (4)
|
||||
formCtrl.$addControl(modelCtrl); // (2)
|
||||
scope.$on('$destroy', function () {
|
||||
formCtrl.$removeControl(modelCtrl); // (5)
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.run(['$route', '$rootScope', '$location', function ($route, $rootScope, $location) {
|
||||
var original = $location.path;
|
||||
$location.path = function (path, reload) {
|
||||
if (reload === false) {
|
||||
var lastRoute = $route.current;
|
||||
var un = $rootScope.$on('$locationChangeSuccess', function () {
|
||||
$route.current = lastRoute;
|
||||
un();
|
||||
});
|
||||
}
|
||||
return original.apply($location, [path]);
|
||||
};
|
||||
}]);
|
||||
|
||||
app.directive('ngClickSelect', function () {
|
||||
return {
|
||||
restrict: 'AC',
|
||||
link: function (scope, element/*, attrs */) {
|
||||
element.bind('click', function () {
|
||||
var selection = window.getSelection();
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(this);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// handles various states and triggers a href or configure/repair view
|
||||
// used by attaching to controller $scope
|
||||
// if $scope.appPostInstallConfirm.show(app); exists it will be called if not yet confirmed
|
||||
function onAppClick(app, $event, isOperator, $scope) {
|
||||
function stopEvent() {
|
||||
$event.originalEvent.stopPropagation();
|
||||
$event.originalEvent.preventDefault();
|
||||
}
|
||||
|
||||
if (app.installationState !== ISTATES.INSTALLED) {
|
||||
if (app.installationState === ISTATES.ERROR && isOperator) $scope.showAppConfigure(app, 'repair');
|
||||
return stopEvent();
|
||||
}
|
||||
|
||||
// app.health can also be null to indicate insufficient data
|
||||
if (!app.health) return stopEvent();
|
||||
if (app.runState === RSTATES.STOPPED) return stopEvent();
|
||||
if (app.runState === RSTATES.STOPPED) return stopEvent();
|
||||
|
||||
if (app.health === HSTATES.UNHEALTHY || app.health === HSTATES.ERROR || app.health === HSTATES.DEAD) {
|
||||
if (isOperator) $scope.showAppConfigure(app, 'repair');
|
||||
return stopEvent();
|
||||
}
|
||||
|
||||
if (app.pendingPostInstallConfirmation && $scope.appPostInstallConfirm) {
|
||||
$scope.appPostInstallConfirm.show(app);
|
||||
return stopEvent();
|
||||
}
|
||||
}
|
||||
|
||||
app.directive('ngClickReveal', function () {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function (scope, element, attrs) {
|
||||
element.addClass('hand');
|
||||
|
||||
var value = '';
|
||||
|
||||
scope.$watch(attrs.ngClickReveal, function (newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
element.html('<i>hidden</i>');
|
||||
value = newValue;
|
||||
}
|
||||
});
|
||||
|
||||
element.bind('click', function () {
|
||||
element.text(value);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// https://codepen.io/webmatze/pen/isuHh
|
||||
app.directive('tagInput', function () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
inputTags: '=taglist'
|
||||
},
|
||||
require: '^form',
|
||||
link: function ($scope, element, attrs, formCtrl) {
|
||||
$scope.defaultWidth = 200;
|
||||
$scope.tagText = ''; // current tag being edited
|
||||
$scope.placeholder = attrs.placeholder;
|
||||
$scope.tagArray = function () {
|
||||
if ($scope.inputTags === undefined) {
|
||||
return [];
|
||||
}
|
||||
return $scope.inputTags.split(' ').filter(function (tag) {
|
||||
return tag !== '';
|
||||
});
|
||||
};
|
||||
$scope.addTag = function () {
|
||||
var tagArray = $scope.tagArray();
|
||||
|
||||
// prevent adding empty or existing items
|
||||
if ($scope.tagText.length === 0 || tagArray.indexOf($scope.tagText) !== -1) {
|
||||
return $scope.tagText = '';
|
||||
}
|
||||
|
||||
tagArray.push($scope.tagText);
|
||||
$scope.inputTags = tagArray.join(' ');
|
||||
return $scope.tagText = '';
|
||||
};
|
||||
$scope.deleteTag = function (key) {
|
||||
var tagArray;
|
||||
tagArray = $scope.tagArray();
|
||||
if (tagArray.length > 0 && $scope.tagText.length === 0 && key === undefined) {
|
||||
tagArray.pop();
|
||||
} else {
|
||||
if (key !== undefined) {
|
||||
tagArray.splice(key, 1);
|
||||
}
|
||||
}
|
||||
formCtrl.$setDirty();
|
||||
return $scope.inputTags = tagArray.join(' ');
|
||||
};
|
||||
$scope.$watch('tagText', function (newVal, oldVal) {
|
||||
var tempEl;
|
||||
if (!(newVal === oldVal && newVal === undefined)) {
|
||||
tempEl = $('<span>' + newVal + '</span>').appendTo('body');
|
||||
$scope.inputWidth = tempEl.width() + 5;
|
||||
if ($scope.inputWidth < $scope.defaultWidth) {
|
||||
$scope.inputWidth = $scope.defaultWidth;
|
||||
}
|
||||
return tempEl.remove();
|
||||
}
|
||||
});
|
||||
element.bind('click', function () {
|
||||
element[0].firstChild.lastChild.focus();
|
||||
});
|
||||
element.bind('keydown', function (e) {
|
||||
var key = e.which;
|
||||
if (key === 9 || key === 13) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (key === 8) {
|
||||
return $scope.$apply('deleteTag()');
|
||||
}
|
||||
});
|
||||
element.bind('keyup', function (e) {
|
||||
var key = e.which;
|
||||
if (key === 9 || key === 13 || key === 32) {
|
||||
e.preventDefault();
|
||||
return $scope.$apply('addTag()');
|
||||
}
|
||||
});
|
||||
},
|
||||
template:
|
||||
'<div class="tag-input-container">' +
|
||||
'<div class="btn-group input-tag" data-ng-repeat="tag in tagArray()">' +
|
||||
'<button type="button" class="btn btn-xs btn-primary" disabled>{{ tag }}</button>' +
|
||||
'<button type="button" class="btn btn-xs btn-primary" data-ng-click="deleteTag($index)">×</button>' +
|
||||
'</div>' +
|
||||
'<input type="text" data-ng-model="tagText" ng-blur="addTag()" placeholder="{{placeholder}}"/>' +
|
||||
'</div>'
|
||||
};
|
||||
});
|
||||
|
||||
app.config(['fitTextConfigProvider', function (fitTextConfigProvider) {
|
||||
fitTextConfigProvider.config = {
|
||||
loadDelay: 250,
|
||||
compressor: 0.9,
|
||||
min: 8,
|
||||
max: 24
|
||||
};
|
||||
}]);
|
||||
|
||||
app.controller('MainController', ['$scope', '$route', '$timeout', '$location', '$interval', 'Notification', 'Client', function ($scope, $route, $timeout, $location, $interval, Notification, Client) {
|
||||
$scope.initialized = false; // used to animate the UI
|
||||
$scope.user = Client.getUserInfo();
|
||||
$scope.installedApps = Client.getInstalledApps();
|
||||
$scope.config = {};
|
||||
$scope.client = Client;
|
||||
$scope.subscription = {};
|
||||
$scope.notificationCount = 0;
|
||||
$scope.hideNavBarActions = $location.path() === '/logs';
|
||||
$scope.backgroundImageUrl = '';
|
||||
|
||||
$scope.closeNavbar = function () {
|
||||
$('.navbar-collapse').collapse('hide');
|
||||
};
|
||||
|
||||
$scope.reboot = {
|
||||
busy: false,
|
||||
|
||||
show: function () {
|
||||
$scope.reboot.busy = false;
|
||||
$('#rebootModal').modal('show');
|
||||
},
|
||||
|
||||
submit: function () {
|
||||
$scope.reboot.busy = true;
|
||||
|
||||
Client.reboot(function (error) {
|
||||
if (error) return Client.error(error);
|
||||
|
||||
$('#rebootModal').modal('hide');
|
||||
|
||||
// trigger refetch to show offline banner
|
||||
$timeout(function () { Client.getStatus(function () {}); }, 5000);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.isActive = function (url) {
|
||||
if (!$route.current) return false;
|
||||
return $route.current.$$route.originalPath.indexOf(url) === 0;
|
||||
};
|
||||
|
||||
$scope.logout = function (event) {
|
||||
event.stopPropagation();
|
||||
$scope.initialized = false;
|
||||
Client.logout();
|
||||
};
|
||||
|
||||
$scope.openSubscriptionSetup = function () {
|
||||
Client.openSubscriptionSetup($scope.subscription);
|
||||
};
|
||||
|
||||
// NOTE: this function is exported and called from the appstore.js
|
||||
$scope.updateSubscriptionStatus = function () {
|
||||
Client.getSubscription(function (error, subscription) {
|
||||
if (error && error.statusCode === 412) return; // not yet registered
|
||||
if (error && error.statusCode === 402) return; // invalid appstore token
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.subscription = subscription;
|
||||
});
|
||||
};
|
||||
|
||||
function refreshNotifications() {
|
||||
if (!Client.getUserInfo().isAtLeastAdmin) return;
|
||||
|
||||
Client.getNotifications({ acknowledged: false }, 1, 100, function (error, results) { // counter maxes out at 100
|
||||
if (error) console.error(error);
|
||||
else $scope.notificationCount = results.length;
|
||||
});
|
||||
}
|
||||
|
||||
// update state of acknowledged notification
|
||||
$scope.notificationAcknowledged = function () {
|
||||
refreshNotifications();
|
||||
};
|
||||
|
||||
function redirectOnMandatory2FA() {
|
||||
if (Client.getConfig().mandatory2FA) {
|
||||
if (Client.getUserInfo().twoFactorAuthenticationEnabled) return; // user already has 2fa
|
||||
if (Client.getUserInfo().source && $scope.config.external2FA) return; // 2fa is external
|
||||
|
||||
$location.path('/profile').search({ setup2fa: true });
|
||||
}
|
||||
}
|
||||
|
||||
// Make it redirect if the browser URL is changed directly - https://forum.cloudron.io/topic/7510/bug-in-2fa-force
|
||||
$scope.$on('$routeChangeStart', function (/* event */) {
|
||||
if ($scope.initialized) redirectOnMandatory2FA();
|
||||
});
|
||||
|
||||
var gPlatformStatusNotification = null;
|
||||
function trackPlatformStatus() {
|
||||
Client.getPlatformStatus(function (error, result) {
|
||||
if (error) return console.error('Failed to get platform status.', error);
|
||||
|
||||
// see box/src/platform.js
|
||||
if (result.message === 'Ready') {
|
||||
if (gPlatformStatusNotification) {
|
||||
gPlatformStatusNotification.kill();
|
||||
gPlatformStatusNotification = null;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gPlatformStatusNotification) {
|
||||
var options = { title: 'Platform status', message: result.message, delay: 'notimeout', replaceMessage: true, closeOnClick: false };
|
||||
|
||||
Notification.primary(options).then(function (result) {
|
||||
gPlatformStatusNotification = result;
|
||||
$timeout(trackPlatformStatus, 5000);
|
||||
});
|
||||
} else {
|
||||
gPlatformStatusNotification.message = result.message;
|
||||
$timeout(trackPlatformStatus, 5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// this loads the very first thing when accessing via IP or domain
|
||||
function init() {
|
||||
Client.getProvisionStatus(function (error, status) {
|
||||
if (error) return Client.initError(error, init);
|
||||
|
||||
if (redirectIfNeeded(status, 'dashboard')) return; // we got redirected...
|
||||
|
||||
// check version and force reload if needed
|
||||
if (!localStorage.version) {
|
||||
localStorage.version = status.version;
|
||||
} else if (localStorage.version !== status.version) {
|
||||
localStorage.version = status.version;
|
||||
window.location.reload(true);
|
||||
}
|
||||
|
||||
console.log('Running dashboard version ', localStorage.version);
|
||||
|
||||
// get user profile as the first thing. this populates the "scope" and affects subsequent API calls
|
||||
async.series([
|
||||
Client.refreshProfile.bind(Client),
|
||||
Client.refreshConfig.bind(Client),
|
||||
Client.refreshAvailableLanguages.bind(Client),
|
||||
Client.refreshInstalledApps.bind(Client)
|
||||
], function (error) {
|
||||
if (error) return Client.initError(error, init);
|
||||
|
||||
// now mark the Client to be ready
|
||||
Client.setReady();
|
||||
|
||||
$scope.config = Client.getConfig();
|
||||
|
||||
if (Client.getUserInfo().hasBackgroundImage) {
|
||||
document.getElementById('mainContentContainer').style.backgroundImage = 'url("' + Client.getBackgroundImageUrl() + '")';
|
||||
document.getElementById('mainContentContainer').classList.add('has-background');
|
||||
}
|
||||
|
||||
$scope.initialized = true;
|
||||
|
||||
redirectOnMandatory2FA();
|
||||
|
||||
$interval(refreshNotifications, 60 * 1000);
|
||||
refreshNotifications();
|
||||
|
||||
Client.getSubscription(function (error, subscription) {
|
||||
if (error && error.statusCode === 412) return; // not yet registered
|
||||
if (error && error.statusCode === 402) return; // invalid appstore token
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.subscription = subscription;
|
||||
|
||||
// only track platform status if we are registered
|
||||
trackPlatformStatus();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Client.onConfig(function (config) {
|
||||
if (config.cloudronName) {
|
||||
document.title = config.cloudronName;
|
||||
}
|
||||
});
|
||||
|
||||
init();
|
||||
|
||||
// setup all the dialog focus handling
|
||||
['updateModal'].forEach(function (id) {
|
||||
$('#' + id).on('shown.bs.modal', function () {
|
||||
$(this).find('[autofocus]:first').focus();
|
||||
});
|
||||
});
|
||||
}]);
|
||||
4
dashboard/public/js/jquery.min.js
vendored
@@ -1,160 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/* global angular, $, showdown */
|
||||
|
||||
// create main application module
|
||||
var app = angular.module('Application', ['pascalprecht.translate', 'ngCookies']);
|
||||
|
||||
app.filter('markdown2html', function () {
|
||||
var converter = new showdown.Converter({
|
||||
simplifiedAutoLink: true,
|
||||
strikethrough: true,
|
||||
tables: true,
|
||||
openLinksInNewWindow: true
|
||||
});
|
||||
|
||||
return function (text) {
|
||||
return converter.makeHtml(text);
|
||||
};
|
||||
});
|
||||
|
||||
// disable sce for footer https://code.angularjs.org/1.5.8/docs/api/ng/service/$sce
|
||||
app.config(function ($sceProvider) {
|
||||
$sceProvider.enabled(false);
|
||||
});
|
||||
|
||||
app.config(['$translateProvider', function ($translateProvider) {
|
||||
$translateProvider.useStaticFilesLoader({
|
||||
prefix: 'translation/',
|
||||
suffix: '.json'
|
||||
});
|
||||
$translateProvider.preferredLanguage('en');
|
||||
$translateProvider.fallbackLanguage('en');
|
||||
}]);
|
||||
|
||||
// Add shorthand "tr" filter to avoid having ot use "translate"
|
||||
// This is a copy of the code at https://github.com/angular-translate/angular-translate/blob/master/src/filter/translate.js
|
||||
// If we find out how to get that function handle somehow dynamically we can use that, otherwise the copy is required
|
||||
function translateFilterFactory($parse, $translate) {
|
||||
var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {
|
||||
if (!angular.isObject(interpolateParams)) {
|
||||
var ctx = this || {
|
||||
'__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'
|
||||
};
|
||||
interpolateParams = $parse(interpolateParams)(ctx);
|
||||
}
|
||||
|
||||
return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);
|
||||
};
|
||||
|
||||
if ($translate.statefulFilter()) {
|
||||
translateFilter.$stateful = true;
|
||||
}
|
||||
|
||||
return translateFilter;
|
||||
}
|
||||
translateFilterFactory.displayName = 'translateFilterFactory';
|
||||
app.filter('tr', translateFilterFactory);
|
||||
|
||||
|
||||
app.controller('PasswordResetController', ['$scope', '$translate', '$http', function ($scope, $translate, $http) {
|
||||
// Stupid angular location provider either wants html5 location mode or not, do the query parsing on my own
|
||||
const search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.indexOf('=') === -1 ? [item, true] : [item.slice(0, item.indexOf('=')), item.slice(item.indexOf('=')+1)]; }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {});
|
||||
|
||||
$scope.initialized = false;
|
||||
$scope.mode = '';
|
||||
$scope.busy = false;
|
||||
$scope.error = false;
|
||||
$scope.branding = null;
|
||||
$scope.username = '';
|
||||
$scope.password = '';
|
||||
$scope.totpToken = '';
|
||||
$scope.passwordResetIdentifier = '';
|
||||
$scope.newPassword = '';
|
||||
$scope.newPasswordRepeat = '';
|
||||
|
||||
const API_ORIGIN = window.cloudronApiOrigin || window.location.origin;
|
||||
|
||||
$scope.onPasswordReset = function () {
|
||||
$scope.busy = true;
|
||||
|
||||
var data = {
|
||||
identifier: $scope.passwordResetIdentifier
|
||||
};
|
||||
|
||||
function done(error) {
|
||||
if (error) $scope.error = error.message;
|
||||
$scope.busy = false;
|
||||
$scope.mode = 'passwordResetDone';
|
||||
}
|
||||
|
||||
$http.post(API_ORIGIN + '/api/v1/auth/password_reset_request', data).success(done).error(done);
|
||||
};
|
||||
|
||||
$scope.onNewPassword = function () {
|
||||
$scope.busy = true;
|
||||
|
||||
var data = {
|
||||
resetToken: search.resetToken,
|
||||
password: $scope.newPassword,
|
||||
totpToken: $scope.totpToken
|
||||
};
|
||||
|
||||
function error(data, status) {
|
||||
console.log('error', status);
|
||||
$scope.busy = false;
|
||||
|
||||
if (status === 401) $scope.error = data.message;
|
||||
else if (status === 409) $scope.error = 'Ask your admin for an invite link first';
|
||||
else $scope.error = 'Unknown error';
|
||||
}
|
||||
|
||||
$http.post(API_ORIGIN + '/api/v1/auth/password_reset', data).success(function (data, status) {
|
||||
if (status !== 202) return error(data, status);
|
||||
|
||||
// set token to autologin
|
||||
localStorage.token = data.accessToken;
|
||||
|
||||
$scope.mode = 'newPasswordDone';
|
||||
}).error(function (data, status) {
|
||||
error(data, status);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.showPasswordReset = function () {
|
||||
window.document.title = 'Password Reset Request';
|
||||
$scope.mode = 'passwordReset';
|
||||
$scope.passwordResetIdentifier = '';
|
||||
setTimeout(function () { $('#inputPasswordResetIdentifier').focus(); }, 200);
|
||||
};
|
||||
|
||||
$scope.showNewPassword = function () {
|
||||
window.document.title = 'Set New Password';
|
||||
$scope.mode = 'newPassword';
|
||||
setTimeout(function () { $('#inputNewPassword').focus(); }, 200);
|
||||
};
|
||||
|
||||
$http.get(API_ORIGIN + '/api/v1/auth/branding').success(function (data, status) {
|
||||
$scope.initialized = true;
|
||||
|
||||
if (status !== 200) return;
|
||||
|
||||
if (data.language) $translate.use(data.language);
|
||||
|
||||
$scope.branding = data;
|
||||
}).error(function () {
|
||||
$scope.initialized = false;
|
||||
});
|
||||
|
||||
// Init into the correct view
|
||||
if (search.passwordReset) {
|
||||
$scope.showPasswordReset();
|
||||
} else if (search.resetToken) {
|
||||
$scope.showNewPassword();
|
||||
} else if (search.accessToken || search.access_token) { // auto-login feature
|
||||
localStorage.token = search.accessToken || search.access_token;
|
||||
window.location.href = '/';
|
||||
} else {
|
||||
$scope.showPasswordReset();
|
||||
}
|
||||
}]);
|
||||
@@ -1,397 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/* global $, angular, SECRET_PLACEHOLDER, STORAGE_PROVIDERS, BACKUP_FORMATS, redirectIfNeeded */
|
||||
/* global REGIONS_S3, REGIONS_WASABI, REGIONS_DIGITALOCEAN, REGIONS_EXOSCALE, REGIONS_SCALEWAY, REGIONS_LINODE, REGIONS_OVH, REGIONS_IONOS, REGIONS_UPCLOUD, REGIONS_VULTR, REGIONS_CONTABO, REGIONS_HETZNER */
|
||||
|
||||
// create main application module
|
||||
var app = angular.module('Application', ['pascalprecht.translate', 'ngCookies', 'angular-md5', 'ui-notification', 'ui.bootstrap']);
|
||||
|
||||
app.controller('RestoreController', ['$scope', 'Client', function ($scope, Client) {
|
||||
var search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.split('='); }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {});
|
||||
|
||||
$scope.client = Client;
|
||||
$scope.busy = false;
|
||||
$scope.error = {};
|
||||
$scope.message = ''; // progress
|
||||
|
||||
// variables here have to match the import config logic!
|
||||
$scope.provider = '';
|
||||
$scope.bucket = '';
|
||||
$scope.prefix = '';
|
||||
$scope.mountPoint = '';
|
||||
$scope.accessKeyId = '';
|
||||
$scope.secretAccessKey = '';
|
||||
$scope.gcsKey = { keyFileName: '', content: '' };
|
||||
$scope.region = '';
|
||||
$scope.endpoint = '';
|
||||
$scope.backupFolder = '';
|
||||
$scope.remotePath = '';
|
||||
$scope.instanceId = '';
|
||||
$scope.acceptSelfSignedCerts = false;
|
||||
$scope.format = 'tgz';
|
||||
$scope.advancedVisible = false;
|
||||
$scope.password = '';
|
||||
$scope.encryptedFilenames = true;
|
||||
$scope.encrypted = false; // only used if a backup config contains that flag
|
||||
$scope.setupToken = '';
|
||||
$scope.skipDnsSetup = false;
|
||||
$scope.disk = null;
|
||||
$scope.blockDevices = [];
|
||||
|
||||
$scope.mountOptions = {
|
||||
host: '',
|
||||
remoteDir: '',
|
||||
username: '',
|
||||
password: '',
|
||||
diskPath: '',
|
||||
user: '',
|
||||
seal: true,
|
||||
port: 22,
|
||||
privateKey: ''
|
||||
};
|
||||
|
||||
$scope.$watch('disk', function (newValue) {
|
||||
if (!newValue) return;
|
||||
$scope.mountOptions.diskPath = '/dev/disk/by-uuid/' + newValue.uuid;
|
||||
});
|
||||
|
||||
$scope.ipv4Config = {
|
||||
provider: 'generic',
|
||||
ip: '',
|
||||
ifname: ''
|
||||
};
|
||||
|
||||
$scope.ipv6Config = {
|
||||
provider: 'generic',
|
||||
ip: '',
|
||||
ifname: ''
|
||||
};
|
||||
|
||||
$scope.ipProviders = [
|
||||
{ name: 'Disabled', value: 'noop' },
|
||||
{ name: 'Public IP', value: 'generic' },
|
||||
{ name: 'Static IP Address', value: 'fixed' },
|
||||
{ name: 'Network Interface', value: 'network-interface' }
|
||||
];
|
||||
|
||||
$scope.s3Regions = REGIONS_S3;
|
||||
$scope.wasabiRegions = REGIONS_WASABI;
|
||||
$scope.doSpacesRegions = REGIONS_DIGITALOCEAN;
|
||||
$scope.hetznerRegions = REGIONS_HETZNER;
|
||||
$scope.exoscaleSosRegions = REGIONS_EXOSCALE;
|
||||
$scope.scalewayRegions = REGIONS_SCALEWAY;
|
||||
$scope.linodeRegions = REGIONS_LINODE;
|
||||
$scope.ovhRegions = REGIONS_OVH;
|
||||
$scope.ionosRegions = REGIONS_IONOS;
|
||||
$scope.upcloudRegions = REGIONS_UPCLOUD;
|
||||
$scope.vultrRegions = REGIONS_VULTR;
|
||||
$scope.contaboRegions = REGIONS_CONTABO;
|
||||
|
||||
$scope.storageProviders = STORAGE_PROVIDERS;
|
||||
|
||||
$scope.formats = BACKUP_FORMATS;
|
||||
|
||||
$scope.s3like = function (provider) {
|
||||
return provider === 's3' || provider === 'minio' || provider === 's3-v4-compat' || provider === 'exoscale-sos'
|
||||
|| provider === 'digitalocean-spaces' || provider === 'wasabi' || provider === 'scaleway-objectstorage' || provider === 'hetzner-objectstorage'
|
||||
|| provider === 'linode-objectstorage' || provider === 'ovh-objectstorage' || provider === 'backblaze-b2' || provider === 'cloudflare-r2'
|
||||
|| provider === 'ionos-objectstorage' || provider === 'vultr-objectstorage' || provider === 'upcloud-objectstorage' || provider === 'idrive-e2'
|
||||
|| provider === 'contabo-objectstorage';
|
||||
};
|
||||
|
||||
$scope.mountlike = function (provider) {
|
||||
return provider === 'disk' || provider === 'sshfs' || provider === 'cifs' || provider === 'nfs' || provider === 'mountpoint' || provider === 'ext4' || provider === 'xfs';
|
||||
};
|
||||
|
||||
$scope.restore = function () {
|
||||
$scope.error = {};
|
||||
$scope.busy = true;
|
||||
|
||||
var backupConfig = {
|
||||
provider: $scope.provider,
|
||||
format: $scope.format,
|
||||
};
|
||||
if ($scope.password) {
|
||||
backupConfig.password = $scope.password;
|
||||
backupConfig.encryptedFilenames = $scope.encryptedFilenames;
|
||||
}
|
||||
|
||||
// only set provider specific fields, this will clear them in the db
|
||||
if ($scope.s3like(backupConfig.provider)) {
|
||||
backupConfig.bucket = $scope.bucket;
|
||||
backupConfig.prefix = $scope.prefix;
|
||||
backupConfig.accessKeyId = $scope.accessKeyId;
|
||||
backupConfig.secretAccessKey = $scope.secretAccessKey;
|
||||
|
||||
if ($scope.endpoint) backupConfig.endpoint = $scope.endpoint;
|
||||
|
||||
if (backupConfig.provider === 's3') {
|
||||
if ($scope.region) backupConfig.region = $scope.region;
|
||||
delete backupConfig.endpoint;
|
||||
} else if (backupConfig.provider === 'minio' || backupConfig.provider === 's3-v4-compat') {
|
||||
backupConfig.region = backupConfig.region || 'us-east-1';
|
||||
backupConfig.acceptSelfSignedCerts = $scope.acceptSelfSignedCerts;
|
||||
backupConfig.s3ForcePathStyle = true; // might want to expose this in the UI
|
||||
} else if (backupConfig.provider === 'exoscale-sos') {
|
||||
backupConfig.region = 'us-east-1';
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
} else if (backupConfig.provider === 'wasabi') {
|
||||
backupConfig.region = $scope.wasabiRegions.find(function (x) { return x.value === $scope.endpoint; }).region;
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
} else if (backupConfig.provider === 'scaleway-objectstorage') {
|
||||
backupConfig.region = $scope.scalewayRegions.find(function (x) { return x.value === $scope.endpoint; }).region;
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
} else if (backupConfig.provider === 'linode-objectstorage') {
|
||||
backupConfig.region = $scope.linodeRegions.find(function (x) { return x.value === $scope.endpoint; }).region;
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
} else if (backupConfig.provider === 'ovh-objectstorage') {
|
||||
backupConfig.region = $scope.ovhRegions.find(function (x) { return x.value === $scope.endpoint; }).region;
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
} else if (backupConfig.provider === 'ionos-objectstorage') {
|
||||
backupConfig.region = $scope.ionosRegions.find(function (x) { return x.value === $scope.endpoint; }).region;
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
} else if (backupConfig.provider === 'vultr-objectstorage') {
|
||||
backupConfig.region = $scope.vultrRegions.find(function (x) { return x.value === $scope.endpoint; }).region;
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
} else if (backupConfig.provider === 'contabo-objectstorage') {
|
||||
backupConfig.region = $scope.contaboRegions.find(function (x) { return x.value === $scope.endpoint; }).region;
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
backupConfig.s3ForcePathStyle = true; // https://docs.contabo.com/docs/products/Object-Storage/technical-description (no virtual buckets)
|
||||
} else if (backupConfig.provider === 'upcloud-objectstorage') {
|
||||
var m = /^.*\.(.*)\.upcloudobjects.com$/.exec(backupConfig.endpoint);
|
||||
backupConfig.region = m ? m[1] : 'us-east-1'; // let it fail in validation phase if m is not valid
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
} else if (backupConfig.provider === 'digitalocean-spaces') {
|
||||
backupConfig.region = 'us-east-1';
|
||||
} else if (backupConfig.provider === 'hetzner-objectstorage') {
|
||||
backupConfig.region = 'us-east-1';
|
||||
backupConfig.signatureVersion = 'v4';
|
||||
}
|
||||
} else if (backupConfig.provider === 'gcs') {
|
||||
backupConfig.bucket = $scope.bucket;
|
||||
backupConfig.prefix = $scope.prefix;
|
||||
try {
|
||||
var serviceAccountKey = JSON.parse($scope.gcsKey.content);
|
||||
backupConfig.projectId = serviceAccountKey.project_id;
|
||||
backupConfig.credentials = {
|
||||
client_email: serviceAccountKey.client_email,
|
||||
private_key: serviceAccountKey.private_key
|
||||
};
|
||||
|
||||
if (!backupConfig.projectId || !backupConfig.credentials || !backupConfig.credentials.client_email || !backupConfig.credentials.private_key) {
|
||||
throw 'fields_missing';
|
||||
}
|
||||
} catch (e) {
|
||||
$scope.error.generic = 'Cannot parse Google Service Account Key: ' + e.message;
|
||||
$scope.error.gcsKeyInput = true;
|
||||
$scope.busy = false;
|
||||
return;
|
||||
}
|
||||
} else if ($scope.mountlike(backupConfig.provider)) {
|
||||
backupConfig.prefix = $scope.prefix;
|
||||
backupConfig.mountOptions = {};
|
||||
|
||||
if (backupConfig.provider === 'cifs' || backupConfig.provider === 'sshfs' || backupConfig.provider === 'nfs') {
|
||||
backupConfig.mountOptions.host = $scope.mountOptions.host;
|
||||
backupConfig.mountOptions.remoteDir = $scope.mountOptions.remoteDir;
|
||||
|
||||
if (backupConfig.provider === 'cifs') {
|
||||
backupConfig.mountOptions.username = $scope.mountOptions.username;
|
||||
backupConfig.mountOptions.password = $scope.mountOptions.password;
|
||||
backupConfig.mountOptions.seal = $scope.mountOptions.seal;
|
||||
} else if (backupConfig.provider === 'sshfs') {
|
||||
backupConfig.mountOptions.user = $scope.mountOptions.user;
|
||||
backupConfig.mountOptions.port = $scope.mountOptions.port;
|
||||
backupConfig.mountOptions.privateKey = $scope.mountOptions.privateKey;
|
||||
}
|
||||
} else if (backupConfig.provider === 'disk' || backupConfig.provider === 'ext4' || backupConfig.provider === 'xfs') {
|
||||
backupConfig.mountOptions.diskPath = $scope.mountOptions.diskPath;
|
||||
} else if (backupConfig.provider === 'mountpoint') {
|
||||
backupConfig.mountPoint = $scope.mountPoint;
|
||||
}
|
||||
} else if (backupConfig.provider === 'filesystem') {
|
||||
backupConfig.backupFolder = $scope.backupFolder;
|
||||
}
|
||||
|
||||
if ($scope.remotePath.indexOf('/') === -1) {
|
||||
$scope.error.generic = 'Backup id must include the directory path';
|
||||
$scope.error.remotePath = true;
|
||||
$scope.busy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if ($scope.remotePath.indexOf('box') === -1) {
|
||||
$scope.error.generic = 'Backup id must contain "box"';
|
||||
$scope.error.remotePath = true;
|
||||
$scope.busy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var version = $scope.remotePath.match(/_v(\d+.\d+.\d+)/);
|
||||
if (!version) {
|
||||
$scope.error.generic = 'Backup id is missing version information';
|
||||
$scope.error.remotePath = true;
|
||||
$scope.busy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var data = {
|
||||
backupConfig: backupConfig,
|
||||
remotePath: $scope.remotePath.replace(/\.tar\.gz(\.enc)?$/, ''),
|
||||
version: version ? version[1] : '',
|
||||
ipv4Config: $scope.ipv4Config,
|
||||
ipv6Config: $scope.ipv6Config,
|
||||
skipDnsSetup: $scope.skipDnsSetup,
|
||||
setupToken: $scope.setupToken
|
||||
};
|
||||
|
||||
Client.restore(data, function (error) {
|
||||
$scope.busy = false;
|
||||
|
||||
if (error) {
|
||||
if (error.statusCode === 424) {
|
||||
$scope.error.generic = error.message;
|
||||
|
||||
if (error.message.indexOf('AWS Access Key Id') !== -1) {
|
||||
$scope.error.accessKeyId = true;
|
||||
$scope.accessKeyId = '';
|
||||
$scope.configureBackupForm.accessKeyId.$setPristine();
|
||||
$('#inputConfigureBackupAccessKeyId').focus();
|
||||
} else if (error.message.indexOf('not match the signature') !== -1 ) {
|
||||
$scope.error.secretAccessKey = true;
|
||||
$scope.secretAccessKey = '';
|
||||
$scope.configureBackupForm.secretAccessKey.$setPristine();
|
||||
$('#inputConfigureBackupSecretAccessKey').focus();
|
||||
} else if (error.message.toLowerCase() === 'access denied') {
|
||||
$scope.error.bucket = true;
|
||||
$scope.bucket = '';
|
||||
$scope.configureBackupForm.bucket.$setPristine();
|
||||
$('#inputConfigureBackupBucket').focus();
|
||||
} else if (error.message.indexOf('ECONNREFUSED') !== -1) {
|
||||
$scope.error.generic = 'Unknown region';
|
||||
$scope.error.region = true;
|
||||
$scope.configureBackupForm.region.$setPristine();
|
||||
$('#inputConfigureBackupDORegion').focus();
|
||||
} else if (error.message.toLowerCase() === 'wrong region') {
|
||||
$scope.error.generic = 'Wrong S3 Region';
|
||||
$scope.error.region = true;
|
||||
$scope.configureBackupForm.region.$setPristine();
|
||||
$('#inputConfigureBackupS3Region').focus();
|
||||
} else {
|
||||
$('#inputConfigureBackupBucket').focus();
|
||||
}
|
||||
} else {
|
||||
$scope.error.generic = error.message;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
waitForRestore();
|
||||
});
|
||||
};
|
||||
|
||||
function waitForRestore() {
|
||||
$scope.busy = true;
|
||||
|
||||
Client.getProvisionStatus(function (error, status) {
|
||||
if (!error && !status.restore.active) { // restore finished
|
||||
if (status.restore.errorMessage) {
|
||||
$scope.busy = false;
|
||||
$scope.error.generic = status.restore.errorMessage;
|
||||
} else { // restore worked, redirect to admin page
|
||||
window.location.href = 'https://' + status.adminFqdn + '/';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!error) $scope.message = status.restore.message;
|
||||
|
||||
setTimeout(waitForRestore, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
function readFileLocally(obj, file, fileName) {
|
||||
return function (event) {
|
||||
$scope.$apply(function () {
|
||||
obj[file] = null;
|
||||
obj[fileName] = event.target.files[0].name;
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (result) {
|
||||
if (!result.target || !result.target.result) return console.error('Unable to read local file');
|
||||
obj[file] = result.target.result;
|
||||
};
|
||||
reader.readAsText(event.target.files[0]);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
document.getElementById('gcsKeyFileInput').onchange = readFileLocally($scope.gcsKey, 'content', 'keyFileName');
|
||||
|
||||
document.getElementById('backupConfigFileInput').onchange = function (event) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (result) {
|
||||
if (!result.target || !result.target.result) return console.error('Unable to read backup config');
|
||||
|
||||
var backupConfig;
|
||||
try {
|
||||
backupConfig = JSON.parse(result.target.result);
|
||||
} catch (e) {
|
||||
console.error('Unable to parse backup config');
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.$apply(function () {
|
||||
// we assume property names match here, this does not yet work for gcs keys
|
||||
Object.keys(backupConfig).forEach(function (k) {
|
||||
if (k in $scope) $scope[k] = backupConfig[k];
|
||||
});
|
||||
|
||||
// this allows the config to potentially have a raw password (though our UI sets it to placeholder)
|
||||
if ($scope.mountOptions.password === SECRET_PLACEHOLDER) $scope.mountOptions.password = '';
|
||||
});
|
||||
};
|
||||
reader.readAsText(event.target.files[0]);
|
||||
};
|
||||
|
||||
function init() {
|
||||
Client.getProvisionStatus(function (error, status) {
|
||||
if (error) return Client.initError(error, init);
|
||||
|
||||
if (redirectIfNeeded(status, 'restore')) return; // redirected to some other view...
|
||||
|
||||
if (status.restore.active) return waitForRestore();
|
||||
|
||||
if (status.restore.errorMessage) $scope.error.generic = status.restore.errorMessage; // any previous restore error
|
||||
|
||||
Client.getProvisionBlockDevices(function (error, result) {
|
||||
if (error) {
|
||||
console.error('Failed to list blockdevices:', error);
|
||||
} else {
|
||||
// only offer non /, /boot or /home disks
|
||||
result = result.filter(function (d) { return d.mountpoint !== '/' && d.mountpoint !== '/home' && d.mountpoint !== '/boot'; });
|
||||
// only offer xfs and ext4 disks
|
||||
result = result.filter(function (d) { return d.type === 'xfs' || d.type === 'ext4'; });
|
||||
|
||||
// amend label for UI
|
||||
result.forEach(function (d) { d.label = d.path; });
|
||||
}
|
||||
|
||||
$scope.blockDevices = result;
|
||||
|
||||
$scope.instanceId = search.instanceId;
|
||||
$scope.setupToken = search.setupToken;
|
||||
|
||||
Client.detectIp(function (error, ip) { // this is never supposed to error
|
||||
if (!error) $scope.ipv4Config.provider = ip.ipv4 ? 'generic' : 'noop';
|
||||
if (!error) $scope.ipv6Config.provider = ip.ipv6 ? 'generic' : 'noop';
|
||||
|
||||
$scope.initialized = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
}]);
|
||||
@@ -1,344 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/* global $, angular, Clipboard, ENDPOINTS_OVH, redirectIfNeeded */
|
||||
|
||||
// create main application module
|
||||
var app = angular.module('Application', ['pascalprecht.translate', 'ngCookies', 'angular-md5', 'ui-notification', 'ui.bootstrap']);
|
||||
|
||||
app.controller('SetupDNSController', ['$scope', '$http', '$timeout', 'Client', function ($scope, $http, $timeout, Client) {
|
||||
var search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.split('='); }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {});
|
||||
|
||||
$scope.state = null; // 'initialized', 'waitingForDnsSetup', 'waitingForBox'
|
||||
$scope.error = {};
|
||||
$scope.provider = '';
|
||||
$scope.showDNSSetup = false;
|
||||
$scope.instanceId = '';
|
||||
$scope.advancedVisible = false;
|
||||
$scope.clipboardDone = false;
|
||||
$scope.search = window.location.search;
|
||||
$scope.setupToken = '';
|
||||
$scope.taskMinutesActive = null;
|
||||
|
||||
$scope.tlsProvider = [
|
||||
{ name: 'Let\'s Encrypt Prod', value: 'letsencrypt-prod' },
|
||||
{ name: 'Let\'s Encrypt Prod - Wildcard', value: 'letsencrypt-prod-wildcard' },
|
||||
{ name: 'Let\'s Encrypt Staging', value: 'letsencrypt-staging' },
|
||||
{ name: 'Let\'s Encrypt Staging - Wildcard', value: 'letsencrypt-staging-wildcard' },
|
||||
{ name: 'Self-Signed', value: 'fallback' }, // this is not 'Custom' because we don't allow user to upload certs during setup phase
|
||||
];
|
||||
|
||||
$scope.ipv4Config = {
|
||||
provider: 'generic',
|
||||
ip: '',
|
||||
ifname: ''
|
||||
};
|
||||
|
||||
$scope.ipv6Config = {
|
||||
provider: 'generic',
|
||||
ip: '',
|
||||
ifname: ''
|
||||
};
|
||||
|
||||
$scope.ipProviders = [
|
||||
{ name: 'Disabled', value: 'noop' },
|
||||
{ name: 'Public IP', value: 'generic' },
|
||||
{ name: 'Static IP Address', value: 'fixed' },
|
||||
{ name: 'Network Interface', value: 'network-interface' }
|
||||
];
|
||||
|
||||
$scope.ovhEndpoints = ENDPOINTS_OVH;
|
||||
|
||||
$scope.needsPort80 = function (dnsProvider, tlsProvider) {
|
||||
return ((dnsProvider === 'manual' || dnsProvider === 'noop' || dnsProvider === 'wildcard') &&
|
||||
(tlsProvider === 'letsencrypt-prod' || tlsProvider === 'letsencrypt-staging'));
|
||||
};
|
||||
|
||||
// If we migrate the api origin we have to poll the new location
|
||||
if (search.admin_fqdn) Client.apiOrigin = 'https://' + search.admin_fqdn;
|
||||
|
||||
// keep in sync with domains.js
|
||||
$scope.dnsProvider = [
|
||||
{ name: 'AWS Route53', value: 'route53' },
|
||||
{ name: 'Bunny', value: 'bunny' },
|
||||
{ name: 'Cloudflare', value: 'cloudflare' },
|
||||
{ name: 'deSEC', value: 'desec' },
|
||||
{ name: 'DigitalOcean', value: 'digitalocean' },
|
||||
{ name: 'DNSimple', value: 'dnsimple' },
|
||||
{ name: 'Gandi LiveDNS', value: 'gandi' },
|
||||
{ name: 'GoDaddy', value: 'godaddy' },
|
||||
{ name: 'Google Cloud DNS', value: 'gcdns' },
|
||||
{ name: 'Hetzner', value: 'hetzner' },
|
||||
{ name: 'INWX', value: 'inwx' },
|
||||
{ name: 'Linode', value: 'linode' },
|
||||
{ name: 'Name.com', value: 'namecom' },
|
||||
{ name: 'Namecheap', value: 'namecheap' },
|
||||
{ name: 'Netcup', value: 'netcup' },
|
||||
{ name: 'OVH', value: 'ovh' },
|
||||
{ name: 'Porkbun', value: 'porkbun' },
|
||||
{ name: 'Vultr', value: 'vultr' },
|
||||
{ name: 'Wildcard', value: 'wildcard' },
|
||||
{ name: 'Manual (not recommended)', value: 'manual' },
|
||||
{ name: 'No-op (only for development)', value: 'noop' }
|
||||
];
|
||||
$scope.dnsCredentials = {
|
||||
busy: false,
|
||||
domain: '',
|
||||
accessKeyId: '',
|
||||
secretAccessKey: '',
|
||||
gcdnsKey: { keyFileName: '', content: '' },
|
||||
digitalOceanToken: '',
|
||||
gandiApiKey: '',
|
||||
gandiTokenType: 'PAT',
|
||||
cloudflareEmail: '',
|
||||
cloudflareToken: '',
|
||||
cloudflareTokenType: 'GlobalApiKey',
|
||||
cloudflareDefaultProxyStatus: false,
|
||||
godaddyApiKey: '',
|
||||
godaddyApiSecret: '',
|
||||
linodeToken: '',
|
||||
bunnyAccessKey: '',
|
||||
dnsimpleAccessToken: '',
|
||||
hetznerToken: '',
|
||||
inwxUsername: '',
|
||||
inwxPassword: '',
|
||||
vultrToken: '',
|
||||
deSecToken: '',
|
||||
nameComUsername: '',
|
||||
nameComToken: '',
|
||||
namecheapUsername: '',
|
||||
namecheapApiKey: '',
|
||||
netcupCustomerNumber: '',
|
||||
netcupApiKey: '',
|
||||
netcupApiPassword: '',
|
||||
ovhEndpoint: 'ovh-eu',
|
||||
ovhConsumerKey: '',
|
||||
ovhAppKey: '',
|
||||
ovhAppSecret: '',
|
||||
porkbunSecretapikey: '',
|
||||
porkbunApikey: '',
|
||||
|
||||
provider: 'route53',
|
||||
zoneName: '',
|
||||
tlsConfig: {
|
||||
provider: 'letsencrypt-prod-wildcard'
|
||||
}
|
||||
};
|
||||
|
||||
$scope.setDefaultTlsProvider = function () {
|
||||
var dnsProvider = $scope.dnsCredentials.provider;
|
||||
// wildcard LE won't work without automated DNS
|
||||
if (dnsProvider === 'manual' || dnsProvider === 'noop' || dnsProvider === 'wildcard') {
|
||||
$scope.dnsCredentials.tlsConfig.provider = 'letsencrypt-prod';
|
||||
} else {
|
||||
$scope.dnsCredentials.tlsConfig.provider = 'letsencrypt-prod-wildcard';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function readFileLocally(obj, file, fileName) {
|
||||
return function (event) {
|
||||
$scope.$apply(function () {
|
||||
obj[file] = null;
|
||||
obj[fileName] = event.target.files[0].name;
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (result) {
|
||||
if (!result.target || !result.target.result) return console.error('Unable to read local file');
|
||||
obj[file] = result.target.result;
|
||||
};
|
||||
reader.readAsText(event.target.files[0]);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
document.getElementById('gcdnsKeyFileInput').onchange = readFileLocally($scope.dnsCredentials.gcdnsKey, 'content', 'keyFileName');
|
||||
|
||||
$scope.setDnsCredentials = function () {
|
||||
$scope.dnsCredentials.busy = true;
|
||||
$scope.error = {};
|
||||
|
||||
var provider = $scope.dnsCredentials.provider;
|
||||
|
||||
var config = {};
|
||||
|
||||
if (provider === 'route53') {
|
||||
config.accessKeyId = $scope.dnsCredentials.accessKeyId;
|
||||
config.secretAccessKey = $scope.dnsCredentials.secretAccessKey;
|
||||
} else if (provider === 'gcdns') {
|
||||
try {
|
||||
var serviceAccountKey = JSON.parse($scope.dnsCredentials.gcdnsKey.content);
|
||||
config.projectId = serviceAccountKey.project_id;
|
||||
config.credentials = {
|
||||
client_email: serviceAccountKey.client_email,
|
||||
private_key: serviceAccountKey.private_key
|
||||
};
|
||||
|
||||
if (!config.projectId || !config.credentials || !config.credentials.client_email || !config.credentials.private_key) {
|
||||
throw new Error('One or more fields are missing in the JSON');
|
||||
}
|
||||
} catch (e) {
|
||||
$scope.error.dnsCredentials = 'Cannot parse Google Service Account Key: ' + e.message;
|
||||
$scope.dnsCredentials.busy = false;
|
||||
return;
|
||||
}
|
||||
} else if (provider === 'digitalocean') {
|
||||
config.token = $scope.dnsCredentials.digitalOceanToken;
|
||||
} else if (provider === 'gandi') {
|
||||
config.token = $scope.dnsCredentials.gandiApiKey;
|
||||
config.tokenType = $scope.dnsCredentials.gandiTokenType;
|
||||
} else if (provider === 'godaddy') {
|
||||
config.apiKey = $scope.dnsCredentials.godaddyApiKey;
|
||||
config.apiSecret = $scope.dnsCredentials.godaddyApiSecret;
|
||||
} else if (provider === 'cloudflare') {
|
||||
config.email = $scope.dnsCredentials.cloudflareEmail;
|
||||
config.token = $scope.dnsCredentials.cloudflareToken;
|
||||
config.tokenType = $scope.dnsCredentials.cloudflareTokenType;
|
||||
config.defaultProxyStatus = $scope.dnsCredentials.cloudflareDefaultProxyStatus;
|
||||
} else if (provider === 'linode') {
|
||||
config.token = $scope.dnsCredentials.linodeToken;
|
||||
} else if (provider === 'bunny') {
|
||||
config.accessKey = $scope.dnsCredentials.bunnyAccessKey;
|
||||
} else if (provider === 'dnsimple') {
|
||||
config.accessToken = $scope.dnsCredentials.dnsimpleAccessToken;
|
||||
} else if (provider === 'hetzner') {
|
||||
config.token = $scope.dnsCredentials.hetznerToken;
|
||||
} else if (provider === 'inwx') {
|
||||
config.username = $scope.dnsCredentials.inwxUsername;
|
||||
config.password = $scope.dnsCredentials.inwxPassword;
|
||||
} else if (provider === 'vultr') {
|
||||
config.token = $scope.dnsCredentials.vultrToken;
|
||||
} else if (provider === 'desec') {
|
||||
config.token = $scope.dnsCredentials.deSecToken;
|
||||
} else if (provider === 'namecom') {
|
||||
config.username = $scope.dnsCredentials.nameComUsername;
|
||||
config.token = $scope.dnsCredentials.nameComToken;
|
||||
} else if (provider === 'namecheap') {
|
||||
config.token = $scope.dnsCredentials.namecheapApiKey;
|
||||
config.username = $scope.dnsCredentials.namecheapUsername;
|
||||
} else if (provider === 'netcup') {
|
||||
config.customerNumber = $scope.dnsCredentials.netcupCustomerNumber;
|
||||
config.apiKey = $scope.dnsCredentials.netcupApiKey;
|
||||
config.apiPassword = $scope.dnsCredentials.netcupApiPassword;
|
||||
} else if (provider === 'ovh') {
|
||||
config.endpoint = $scope.dnsCredentials.ovhEndpoint;
|
||||
config.consumerKey = $scope.dnsCredentials.ovhConsumerKey;
|
||||
config.appKey = $scope.dnsCredentials.ovhAppKey;
|
||||
config.appSecret = $scope.dnsCredentials.ovhAppSecret;
|
||||
} else if (provider === 'porkbun') {
|
||||
config.apikey = $scope.dnsCredentials.porkbunApikey;
|
||||
config.secretapikey = $scope.dnsCredentials.porkbunSecretapikey;
|
||||
}
|
||||
|
||||
var tlsConfig = {
|
||||
provider: $scope.dnsCredentials.tlsConfig.provider,
|
||||
wildcard: false
|
||||
};
|
||||
if ($scope.dnsCredentials.tlsConfig.provider.indexOf('-wildcard') !== -1) {
|
||||
tlsConfig.provider = tlsConfig.provider.replace('-wildcard', '');
|
||||
tlsConfig.wildcard = true;
|
||||
}
|
||||
|
||||
var data = {
|
||||
domainConfig: {
|
||||
domain: $scope.dnsCredentials.domain,
|
||||
zoneName: $scope.dnsCredentials.zoneName,
|
||||
provider: provider,
|
||||
config: config,
|
||||
tlsConfig: tlsConfig
|
||||
},
|
||||
ipv4Config: $scope.ipv4Config,
|
||||
ipv6Config: $scope.ipv6Config,
|
||||
providerToken: $scope.instanceId,
|
||||
setupToken: $scope.setupToken
|
||||
};
|
||||
|
||||
Client.setup(data, function (error) {
|
||||
if (error) {
|
||||
$scope.dnsCredentials.busy = false;
|
||||
if (error.statusCode === 422) {
|
||||
if (provider === 'ami') {
|
||||
$scope.error.ami = error.message;
|
||||
} else {
|
||||
$scope.error.setup = error.message;
|
||||
}
|
||||
} else {
|
||||
$scope.error.dnsCredentials = error.message;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
waitForDnsSetup();
|
||||
});
|
||||
};
|
||||
|
||||
function waitForDnsSetup() {
|
||||
$scope.state = 'waitingForDnsSetup';
|
||||
|
||||
Client.getProvisionStatus(function (error, status) {
|
||||
if (!error && !status.setup.active) {
|
||||
if (!status.adminFqdn || status.setup.errorMessage) { // setup reset or errored. start over
|
||||
$scope.error.setup = status.setup.errorMessage;
|
||||
$scope.state = 'initialized';
|
||||
$scope.dnsCredentials.busy = false;
|
||||
} else { // proceed to activation
|
||||
window.location.href = 'https://' + status.adminFqdn + '/activation.html' + (window.location.search);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
$scope.message = status.setup.message;
|
||||
$scope.taskMinutesActive = (new Date() - new Date(status.setup.startTime)) / 60000;
|
||||
}
|
||||
|
||||
setTimeout(waitForDnsSetup, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
Client.getProvisionStatus(function (error, status) {
|
||||
$scope.state = 'waitingForBox';
|
||||
if (error) return Client.initError(error, init);
|
||||
|
||||
if (redirectIfNeeded(status, 'setup')) return; // redirected to some other view...
|
||||
|
||||
if (status.setup.active) return waitForDnsSetup();
|
||||
|
||||
$scope.error.setup = status.setup.errorMessage; // show any previous error
|
||||
|
||||
if (status.provider === 'digitalocean' || status.provider === 'digitalocean-mp') {
|
||||
$scope.dnsCredentials.provider = 'digitalocean';
|
||||
} else if (status.provider === 'linode' || status.provider === 'linode-oneclick' || status.provider === 'linode-stackscript') {
|
||||
$scope.dnsCredentials.provider = 'linode';
|
||||
} else if (status.provider === 'vultr' || status.provider === 'vultr-mp') {
|
||||
$scope.dnsCredentials.provider = 'vultr';
|
||||
} else if (status.provider === 'gce') {
|
||||
$scope.dnsCredentials.provider = 'gcdns';
|
||||
} else if (status.provider === 'ami') {
|
||||
// aws marketplace made a policy change that they one cannot provide route53 IAM credentials
|
||||
$scope.dnsCredentials.provider = 'wildcard';
|
||||
}
|
||||
|
||||
$scope.instanceId = search.instanceId;
|
||||
$scope.setupToken = search.setupToken;
|
||||
$scope.provider = status.provider;
|
||||
|
||||
Client.detectIp(function (error, ip) { // this is never supposed to error
|
||||
if (!error) $scope.ipv4Config.provider = ip.ipv4 ? 'generic' : 'noop';
|
||||
if (!error) $scope.ipv6Config.provider = ip.ipv6 ? 'generic' : 'noop';
|
||||
|
||||
$scope.state = 'initialized';
|
||||
|
||||
setTimeout(function () { $("[autofocus]:first").focus(); }, 100);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var clipboard = new Clipboard('.clipboard');
|
||||
clipboard.on('success', function () {
|
||||
$scope.$apply(function () { $scope.clipboardDone = true; });
|
||||
$timeout(function () { $scope.clipboardDone = false; }, 5000);
|
||||
});
|
||||
|
||||
init();
|
||||
}]);
|
||||
@@ -1,151 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/* global angular, $, showdown */
|
||||
|
||||
// create main application module
|
||||
var app = angular.module('Application', ['pascalprecht.translate', 'ngCookies']);
|
||||
|
||||
app.filter('markdown2html', function () {
|
||||
var converter = new showdown.Converter({
|
||||
simplifiedAutoLink: true,
|
||||
strikethrough: true,
|
||||
tables: true,
|
||||
openLinksInNewWindow: true
|
||||
});
|
||||
|
||||
return function (text) {
|
||||
return converter.makeHtml(text);
|
||||
};
|
||||
});
|
||||
|
||||
// disable sce for footer https://code.angularjs.org/1.5.8/docs/api/ng/service/$sce
|
||||
app.config(function ($sceProvider) {
|
||||
$sceProvider.enabled(false);
|
||||
});
|
||||
|
||||
app.config(['$translateProvider', function ($translateProvider) {
|
||||
$translateProvider.useStaticFilesLoader({
|
||||
prefix: 'translation/',
|
||||
suffix: '.json'
|
||||
});
|
||||
$translateProvider.useLocalStorage();
|
||||
$translateProvider.preferredLanguage('en');
|
||||
$translateProvider.fallbackLanguage('en');
|
||||
}]);
|
||||
|
||||
// Add shorthand "tr" filter to avoid having ot use "translate"
|
||||
// This is a copy of the code at https://github.com/angular-translate/angular-translate/blob/master/src/filter/translate.js
|
||||
// If we find out how to get that function handle somehow dynamically we can use that, otherwise the copy is required
|
||||
function translateFilterFactory($parse, $translate) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var translateFilter = function (translationId, interpolateParams, interpolation, forceLanguage) {
|
||||
if (!angular.isObject(interpolateParams)) {
|
||||
var ctx = this || {
|
||||
'__SCOPE_IS_NOT_AVAILABLE': 'More info at https://github.com/angular/angular.js/commit/8863b9d04c722b278fa93c5d66ad1e578ad6eb1f'
|
||||
};
|
||||
interpolateParams = $parse(interpolateParams)(ctx);
|
||||
}
|
||||
|
||||
return $translate.instant(translationId, interpolateParams, interpolation, forceLanguage);
|
||||
};
|
||||
|
||||
if ($translate.statefulFilter()) {
|
||||
translateFilter.$stateful = true;
|
||||
}
|
||||
|
||||
return translateFilter;
|
||||
}
|
||||
translateFilterFactory.displayName = 'translateFilterFactory';
|
||||
app.filter('tr', translateFilterFactory);
|
||||
|
||||
app.controller('SetupAccountController', ['$scope', '$translate', '$http', function ($scope, $translate, $http) {
|
||||
// Stupid angular location provider either wants html5 location mode or not, do the query parsing on my own
|
||||
const search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.indexOf('=') === -1 ? [item, true] : [item.slice(0, item.indexOf('=')), item.slice(item.indexOf('=')+1)]; }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {});
|
||||
|
||||
const API_ORIGIN = window.cloudronApiOrigin || window.location.origin;
|
||||
|
||||
$scope.initialized = false;
|
||||
$scope.busy = false;
|
||||
$scope.error = null;
|
||||
$scope.view = 'setup';
|
||||
$scope.branding = null;
|
||||
$scope.dashboardUrl = '';
|
||||
|
||||
$scope.profileLocked = !!search.profileLocked;
|
||||
$scope.existingUsername = !!search.username;
|
||||
$scope.username = search.username || '';
|
||||
$scope.displayName = search.displayName || '';
|
||||
$scope.password = '';
|
||||
$scope.passwordRepeat = '';
|
||||
|
||||
$scope.onSubmit = function () {
|
||||
$scope.busy = true;
|
||||
$scope.error = null;
|
||||
|
||||
var data = {
|
||||
inviteToken: search.inviteToken,
|
||||
password: $scope.password
|
||||
};
|
||||
|
||||
if (!$scope.profileLocked) {
|
||||
if (!$scope.existingUsername) data.username = $scope.username;
|
||||
data.displayName = $scope.displayName;
|
||||
}
|
||||
|
||||
function error(data, status) {
|
||||
$scope.busy = false;
|
||||
|
||||
if (status === 401) {
|
||||
$scope.view = 'invalidToken';
|
||||
} else if (status === 409) {
|
||||
$scope.error = {
|
||||
username: true,
|
||||
message: 'Username already taken'
|
||||
};
|
||||
$scope.setupAccountForm.username.$setPristine();
|
||||
setTimeout(function () { $('#inputUsername').focus(); }, 200);
|
||||
} else if (status === 400) {
|
||||
$scope.error = {
|
||||
message: data.message
|
||||
};
|
||||
if (data.message.indexOf('Username') === 0) {
|
||||
$scope.setupAccountForm.username.$setPristine();
|
||||
$scope.error.username = true;
|
||||
}
|
||||
} else {
|
||||
$scope.error = { message: 'Unknown error. Please try again later.' };
|
||||
console.error(status, data);
|
||||
}
|
||||
}
|
||||
|
||||
$http.post(API_ORIGIN + '/api/v1/auth/setup_account', data).success(function (data, status) {
|
||||
if (status !== 201) return error(data, status);
|
||||
|
||||
// set token to autologin on first oidc flow
|
||||
localStorage.cloudronFirstTimeToken = data.accessToken;
|
||||
|
||||
$scope.dashboardUrl = '/openid/auth?client_id=cid-webadmin&scope=openid email profile&response_type=code token&redirect_uri=' + window.location.origin + '/authcallback.html';
|
||||
|
||||
$scope.view = 'done';
|
||||
}).error(error);
|
||||
};
|
||||
|
||||
if (!$scope.existingUsername && $scope.profileLocked) {
|
||||
$scope.view = 'noUsername';
|
||||
$scope.initialized = true;
|
||||
} else {
|
||||
$http.get(API_ORIGIN + '/api/v1/auth/branding').success(function (data, status) {
|
||||
$scope.initialized = true;
|
||||
|
||||
if (status !== 200) return;
|
||||
|
||||
if (data.language) $translate.use(data.language);
|
||||
|
||||
$scope.branding = data;
|
||||
}).error(function () {
|
||||
$scope.initialized = false;
|
||||
});
|
||||
}
|
||||
}]);
|
||||
3
dashboard/public/js/showdown-1.9.1.min.js
vendored
@@ -1,42 +0,0 @@
|
||||
/* This file contains helpers which should not be part of client.js */
|
||||
|
||||
/* global angular */
|
||||
|
||||
angular.module('Application').directive('passwordReveal', function () {
|
||||
var svgEye = '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="eye" class="svg-inline--fa fa-eye fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M572.52 241.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400a144 144 0 1 1 144-144 143.93 143.93 0 0 1-144 144zm0-240a95.31 95.31 0 0 0-25.31 3.79 47.85 47.85 0 0 1-66.9 66.9A95.78 95.78 0 1 0 288 160z"></path></svg>';
|
||||
var svgEyeSlash = '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="eye-slash" class="svg-inline--fa fa-eye-slash fa-w-20" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M320 400c-75.85 0-137.25-58.71-142.9-133.11L72.2 185.82c-13.79 17.3-26.48 35.59-36.72 55.59a32.35 32.35 0 0 0 0 29.19C89.71 376.41 197.07 448 320 448c26.91 0 52.87-4 77.89-10.46L346 397.39a144.13 144.13 0 0 1-26 2.61zm313.82 58.1l-110.55-85.44a331.25 331.25 0 0 0 81.25-102.07 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64a308.15 308.15 0 0 0-147.32 37.7L45.46 3.37A16 16 0 0 0 23 6.18L3.37 31.45A16 16 0 0 0 6.18 53.9l588.36 454.73a16 16 0 0 0 22.46-2.81l19.64-25.27a16 16 0 0 0-2.82-22.45zm-183.72-142l-39.3-30.38A94.75 94.75 0 0 0 416 256a94.76 94.76 0 0 0-121.31-92.21A47.65 47.65 0 0 1 304 192a46.64 46.64 0 0 1-1.54 10l-73.61-56.89A142.31 142.31 0 0 1 320 112a143.92 143.92 0 0 1 144 144c0 21.63-5.29 41.79-13.9 60.11z"></path></svg>';
|
||||
|
||||
return {
|
||||
link: function (scope, elements) {
|
||||
var element = elements[0];
|
||||
|
||||
if (!element.parentNode) {
|
||||
console.error('Wrong password-reveal directive usage. Element has no parent.');
|
||||
return;
|
||||
}
|
||||
|
||||
var eye = document.createElement('i');
|
||||
eye.innerHTML = svgEyeSlash;
|
||||
eye.style.width = '18px';
|
||||
eye.style.height = '18px';
|
||||
eye.style.position = 'relative';
|
||||
eye.style.float = 'right';
|
||||
eye.style.marginTop = '-24px';
|
||||
eye.style.marginRight = '10px';
|
||||
eye.style.cursor = 'pointer';
|
||||
|
||||
eye.addEventListener('click', function () {
|
||||
if (element.type === 'password') {
|
||||
element.type = 'text';
|
||||
eye.innerHTML = svgEye;
|
||||
} else {
|
||||
element.type = 'password';
|
||||
eye.innerHTML = svgEyeSlash;
|
||||
}
|
||||
});
|
||||
|
||||
element.parentNode.style.position = 'relative';
|
||||
element.parentNode.insertBefore(eye, element.nextSibling);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,57 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
/* Slider */
|
||||
.slick-slider { position: relative; display: block; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -ms-touch-action: pan-y; touch-action: pan-y; -webkit-tap-highlight-color: transparent; }
|
||||
|
||||
.slick-list { position: relative; overflow: hidden; display: block; margin: 0; padding: 0; }
|
||||
.slick-list:focus { outline: none; }
|
||||
.slick-loading .slick-list { background: #fff url("./ajax-loader.gif") center center no-repeat; }
|
||||
.slick-list.dragging { cursor: pointer; cursor: hand; }
|
||||
|
||||
.slick-slider .slick-track { -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); -o-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); }
|
||||
|
||||
.slick-track { position: relative; left: 0; top: 0; display: block; }
|
||||
.slick-track:before, .slick-track:after { content: ""; display: table; }
|
||||
.slick-track:after { clear: both; }
|
||||
.slick-loading .slick-track { visibility: hidden; }
|
||||
|
||||
.slick-slide { float: left; height: 100%; min-height: 1px; display: none; }
|
||||
[dir="rtl"] .slick-slide { float: right; }
|
||||
.slick-slide img { display: block; }
|
||||
.slick-slide.slick-loading img { display: none; }
|
||||
.slick-slide.dragging img { pointer-events: none; }
|
||||
.slick-initialized .slick-slide { display: block; }
|
||||
.slick-loading .slick-slide { visibility: hidden; }
|
||||
.slick-vertical .slick-slide { display: block; height: auto; border: 1px solid transparent; }
|
||||
|
||||
/* Icons */
|
||||
@font-face { font-family: "slick"; src: url("./fonts/slick.eot"); src: url("./fonts/slick.eot?#iefix") format("embedded-opentype"), url("./fonts/slick.woff") format("woff"), url("./fonts/slick.ttf") format("truetype"), url("./fonts/slick.svg#slick") format("svg"); font-weight: normal; font-style: normal; }
|
||||
/* Arrows */
|
||||
.slick-prev, .slick-next { position: absolute; display: block; height: 20px; width: 20px; line-height: 0; font-size: 0; cursor: pointer; background: transparent; color: transparent; top: 50%; margin-top: -10px; padding: 0; border: none; outline: none; }
|
||||
.slick-prev:hover, .slick-prev:focus, .slick-next:hover, .slick-next:focus { outline: none; background: transparent; color: transparent; }
|
||||
.slick-prev:hover:before, .slick-prev:focus:before, .slick-next:hover:before, .slick-next:focus:before { opacity: 1; }
|
||||
.slick-prev.slick-disabled:before, .slick-next.slick-disabled:before { opacity: 0.25; }
|
||||
|
||||
.slick-prev:before, .slick-next:before { font-family: "slick"; font-size: 20px; line-height: 1; color: white; opacity: 0.75; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
|
||||
|
||||
.slick-prev { left: -25px; }
|
||||
[dir="rtl"] .slick-prev { left: auto; right: -25px; }
|
||||
.slick-prev:before { content: "←"; }
|
||||
[dir="rtl"] .slick-prev:before { content: "→"; }
|
||||
|
||||
.slick-next { right: -25px; }
|
||||
[dir="rtl"] .slick-next { left: -25px; right: auto; }
|
||||
.slick-next:before { content: "→"; }
|
||||
[dir="rtl"] .slick-next:before { content: "←"; }
|
||||
|
||||
/* Dots */
|
||||
.slick-slider { margin-bottom: 30px; }
|
||||
|
||||
.slick-dots { position: absolute; bottom: -45px; list-style: none; display: block; text-align: center; padding: 0; width: 100%; }
|
||||
.slick-dots li { position: relative; display: inline-block; height: 20px; width: 20px; margin: 0 5px; padding: 0; cursor: pointer; }
|
||||
.slick-dots li button { border: 0; background: transparent; display: block; height: 20px; width: 20px; outline: none; line-height: 0; font-size: 0; color: transparent; padding: 5px; cursor: pointer; }
|
||||
.slick-dots li button:hover, .slick-dots li button:focus { outline: none; }
|
||||
.slick-dots li button:hover:before, .slick-dots li button:focus:before { opacity: 1; }
|
||||
.slick-dots li button:before { position: absolute; top: 0; left: 0; content: "•"; width: 20px; height: 20px; font-family: "slick"; font-size: 6px; line-height: 20px; text-align: center; color: black; opacity: 0.25; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
|
||||
.slick-dots li.slick-active button:before { color: black; opacity: 0.75; }
|
||||
|
||||
/*# sourceMappingURL=slick.css.map */
|
||||
1750
dashboard/public/translation/cs.json
Normal file
@@ -3,22 +3,10 @@
|
||||
"rebootDialog": {
|
||||
"title": "本当にサーバーを再起動しますか?"
|
||||
},
|
||||
"clipboard": {
|
||||
"clickToCopyBackupId": "バックアップIDをクリックしてコピー",
|
||||
"clickToCopy": "クリックしてコピー",
|
||||
"copied": "クリップボードにコピーしました"
|
||||
},
|
||||
"action": {
|
||||
"logs": "ログ",
|
||||
"reboot": "再起動"
|
||||
},
|
||||
"table": {
|
||||
"date": "日付"
|
||||
},
|
||||
"pagination": {
|
||||
"next": "次",
|
||||
"prev": "前"
|
||||
},
|
||||
"displayName": "表示名",
|
||||
"username": "ユーザー名",
|
||||
"dialog": {
|
||||
@@ -32,14 +20,7 @@
|
||||
"offline": "Cloudronはオフラインです。再接続中…"
|
||||
},
|
||||
"apps": {
|
||||
"tagsFilterHeaderAll": "タグ一覧",
|
||||
"domainsFilterHeader": "ドメイン一覧",
|
||||
"tagsFilterHeader": "タグ: {{ tags }}",
|
||||
"searchPlaceholder": "アプリを探す",
|
||||
"adminPageActionTooltip": "管理者ページ",
|
||||
"infoActionTooltip": "情報",
|
||||
"logsActionTooltip": "ログ",
|
||||
"configActionTooltip": "設定",
|
||||
"noAccess": {
|
||||
"description": "アクセス権のあるアプリは、ここにに表示されます。",
|
||||
"title": "アプリへのアクセス権がありません。"
|
||||
|
||||
@@ -15,33 +15,11 @@
|
||||
"userManagementNone": "Ta aplikacja posiada własne zarządzanie użytkownikami.",
|
||||
"userManagement": "Zarządanie użytkownikami",
|
||||
"manualWarning": "Manualnie dodaj rekord A dla <b>{{ location }}</b> do publicznego IP tego Cloudrona",
|
||||
"configuredForCloudronEmail": "Ta aplikacja jest przygotowana aby używała <a href=\"{{ emailDocsLink }}\" target=\"_blank\">Email Cloudrona</a>.",
|
||||
"lowOnResources": "Ten Cloudron jest blisko wyczerpania dostępnych zasobów."
|
||||
"configuredForCloudronEmail": "Ta aplikacja jest przygotowana aby używała <a href=\"{{ emailDocsLink }}\" target=\"_blank\">Email Cloudrona</a>."
|
||||
},
|
||||
"unstable": "Niestabilne",
|
||||
"appMissing": "Szukasz innej aplikacji? Daj nam znać.",
|
||||
"noAppsFound": "Nie znaleziono żadnych aplikacji.",
|
||||
"searchPlaceholder": "Szukaj alternatyw jak Github, Dropbox, Slack, Trello, ...",
|
||||
"category": {
|
||||
"vpn": "VPN",
|
||||
"wiki": "Wiki",
|
||||
"project": "Zarządzanie projetkami",
|
||||
"sync": "Synchronizacja plików",
|
||||
"learning": "Nauka",
|
||||
"notes": "Notatki",
|
||||
"media": "Media",
|
||||
"git": "Hostowanie kodu",
|
||||
"hosting": "Web Hosting",
|
||||
"game": "Gry",
|
||||
"email": "Email",
|
||||
"finance": "Finanse",
|
||||
"gallery": "Galeria",
|
||||
"forum": "Forum",
|
||||
"crm": "CRM",
|
||||
"document": "Dokumenty",
|
||||
"blog": "Blog",
|
||||
"chat": "Czat",
|
||||
"analytics": "Analityka",
|
||||
"newApps": "Nowe aplikacje",
|
||||
"popular": "Popularne",
|
||||
"all": "Wszystko"
|
||||
@@ -52,26 +30,12 @@
|
||||
"rebootDialog": {
|
||||
"rebootAction": "Zrestartuj teraz",
|
||||
"description": "Restartuj serwer by sfinalizowac instalacje aktualizacji bezpieczeństwa lub w przypadku nieoczekiwanych zachowań. Wszytskie usługi i aplikacje aktywne na tym Cloudronie zostaną automatycznie uruchomione ponownie po restarcie.",
|
||||
"warning": "Restart serwera spowoduje tymczasową niedostepność wszystkich aplikacji zainstalowanych na tym Cloudronie!",
|
||||
"title": "Na pewno zrestartować serwer?"
|
||||
},
|
||||
"clipboard": {
|
||||
"clickToCopyBackupId": "Kliknij by skopiowac Backup ID",
|
||||
"clickToCopy": "Kliknij by skopiować",
|
||||
"copied": "Skopiowano do schowka"
|
||||
},
|
||||
"action": {
|
||||
"logs": "Logi",
|
||||
"reboot": "Restart"
|
||||
},
|
||||
"pagination": {
|
||||
"perPageSelector": "Pokazuj {{ n }} na stronie",
|
||||
"prev": "Poprzednia",
|
||||
"next": "Następna"
|
||||
},
|
||||
"table": {
|
||||
"date": "Data"
|
||||
},
|
||||
"actions": "Akcje",
|
||||
"displayName": "Wyświetlana nazwa",
|
||||
"username": "Użytkownik",
|
||||
@@ -86,15 +50,7 @@
|
||||
"offline": "Cloudron jest niedostępny. Odnawiam połączenie…"
|
||||
},
|
||||
"apps": {
|
||||
"domainsFilterHeader": "Wszytskie domeny",
|
||||
"tagsFilterHeaderAll": "Wszystkie tagi",
|
||||
"tagsFilterHeader": "Tagi: {{ tags }}",
|
||||
"stateFilterHeader": "Wszytskie stany",
|
||||
"searchPlaceholder": "Szukaj Aplikacji",
|
||||
"adminPageActionTooltip": "Panel Administratora",
|
||||
"infoActionTooltip": "Informacje",
|
||||
"logsActionTooltip": "Logi",
|
||||
"configActionTooltip": "Konfiguracja",
|
||||
"noAccess": {
|
||||
"description": "Po uzyskaniu dostępu będą one widoczne tutaj.",
|
||||
"title": "Nie masz obecnie dostępu do żadnych aplikacji."
|
||||
|
||||
@@ -2,12 +2,6 @@
|
||||
"main": {
|
||||
"logout": "නික්මෙන්න",
|
||||
"actions": "ක්රියාමාර්ග",
|
||||
"prettyDate": {
|
||||
"minutesAgo": "විනාඩි {{ m }} ට පෙර",
|
||||
"hoursAgo": "හෝරා {{ h }} ට පෙර",
|
||||
"justNow": "මේ දැන්",
|
||||
"yeserday": "ඊයේ"
|
||||
},
|
||||
"dialog": {
|
||||
"cancel": "අවලංගු",
|
||||
"save": "සුරකින්න",
|
||||
@@ -16,13 +10,6 @@
|
||||
"yes": "ඔව්"
|
||||
},
|
||||
"username": "පරිශීලක නාමය",
|
||||
"table": {
|
||||
"date": "දිනය"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "පෙර",
|
||||
"next": "ඊළඟ"
|
||||
},
|
||||
"searchPlaceholder": "සොයන්න",
|
||||
"multiselect": {
|
||||
"select": "තෝරන්න"
|
||||
@@ -30,35 +17,18 @@
|
||||
},
|
||||
"appstore": {
|
||||
"category": {
|
||||
"chat": "සම්භාෂණය",
|
||||
"learning": "ඉගෙනීම",
|
||||
"project": "ව්යාපෘති කළමනාකරණය",
|
||||
"all": "සියල්ල",
|
||||
"popular": "ජනප්රිය",
|
||||
"newApps": "නව යෙදුම්",
|
||||
"analytics": "විශ්ලේෂ",
|
||||
"document": "ලේඛන",
|
||||
"crm": "පා.ස.ක. (CRM)",
|
||||
"finance": "මූල්ය",
|
||||
"email": "වි-තැපෑල",
|
||||
"game": "ක්රීඩා",
|
||||
"media": "මාධ්ය",
|
||||
"notes": "සටහන්"
|
||||
"newApps": "නව යෙදුම්"
|
||||
},
|
||||
"title": "යෙදුම් ගබඩාව",
|
||||
"installDialog": {
|
||||
"location": "ස්ථානය",
|
||||
"groups": "සමූහ"
|
||||
},
|
||||
"accountDialog": {
|
||||
"password": "මුරපදය",
|
||||
"email": "වි-තැපෑල"
|
||||
}
|
||||
},
|
||||
"apps": {
|
||||
"title": "මාගේ යෙදුම්",
|
||||
"infoActionTooltip": "තොරතුරු",
|
||||
"searchPlaceholder": "යෙදුම් සොයන්න",
|
||||
"domainsFilterHeader": "සියලුම වසම්"
|
||||
"searchPlaceholder": "යෙදුම් සොයන්න"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,279 +0,0 @@
|
||||
<!-- Modal postinstall confirm -->
|
||||
<div class="modal fade" id="appsPostInstallConfirmModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<img ng-src="{{appPostInstallConfirm.app.iconUrl}}" onerror="this.onerror=null;this.src='img/appicon_fallback.png'" class="app-info-icon"/>
|
||||
<div class="app-info-title">
|
||||
{{ appPostInstallConfirm.app.manifest.title }}<br/>
|
||||
<span class="text-muted text-small">{{ 'app.appInfo.package' | tr }} <a ng-href="/#/appstore/{{appPostInstallConfirm.app.manifest.id}}?version={{appPostInstallConfirm.app.manifest.version}}">v{{ appPostInstallConfirm.app.manifest.version }}</a> </span>
|
||||
<br/>
|
||||
<span ng-show="appPostInstallConfirm.app.manifest.documentationUrl" class="text-small"><a target="_blank" ng-href="{{appPostInstallConfirm.app.manifest.documentationUrl}}">{{ 'app.docsAction' | tr }}</a> </span>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!--
|
||||
<p ng-show="appPostInstallConfirm.app.manifest.addons.email">{{ 'app.appInfo.ssoEmail' | tr }}</p>
|
||||
<p ng-show="appPostInstallConfirm.app.sso && !appPostInstallConfirm.app.manifest.addons.email">{{ 'app.appInfo.sso' | tr }}</p>
|
||||
-->
|
||||
<div ng-bind-html="appPostInstallConfirm.message | markdown2html"></div>
|
||||
<div ng-show="appPostInstallConfirm.app.manifest.documentationUrl" ng-bind-html="'app.appInfo.appDocsUrl' | tr:{ docsUrl: appPostInstallConfirm.app.manifest.documentationUrl, title: appPostInstallConfirm.app.manifest.title, forumUrl: (appPostInstallConfirm.app.manifest.forumUrl || 'https://forum.cloudron.io') }"></div>
|
||||
|
||||
<div style="margin-top: 10px; margin-bottom: 5px;" ng-show="pendingChecklistItems(appPostInstallConfirm.app)">
|
||||
<label class="control-label">{{ 'app.appInfo.checklist' | tr }}</label>
|
||||
</div>
|
||||
<div ng-repeat="item in appPostInstallConfirm.app.checklist">
|
||||
<div class="checklist-item" ng-hide="item.acknowledged">
|
||||
<span ng-bind-html="item.message | markdown2html"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
|
||||
<a class="btn btn-success" ng-href="{{ 'https://' + appPostInstallConfirm.app.fqdn }}" target="_blank" ng-click="appPostInstallConfirm.submit()">{{ 'app.appInfo.openAction' | tr:{ app: appPostInstallConfirm.app.manifest.title } }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal applinks edit -->
|
||||
<div class="modal fade" id="applinksEditModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'app.editApplinkDialog.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="applinksEditForm" role="form" ng-submit="applinksEdit.submit()" autocomplete="off">
|
||||
<div class="form-group" ng-class="{ 'has-error': (applinksEditForm.upstreamUri.$dirty && applinksEditForm.upstreamUri.$invalid) || (!applinksEditForm.upstreamUri.$dirty && applinksEdit.error.upstreamUri) }">
|
||||
<label class="control-label">{{ 'app.applinks.upstreamUri' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="applinksEdit.upstreamUri" name="upstreamUri" id="inputUpstreamUri" autofocus autocomplete="off" required>
|
||||
<span class="text-danger" ng-show="applinksEdit.error.upstreamUri">{{ applinksEdit.error.upstreamUri }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">{{ 'app.applinks.label' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="applinksEdit.label" name="label" id="inputLabel" autocomplete="off">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<label class="control-label">{{ 'app.display.icon' | tr }}</label>
|
||||
</div>
|
||||
<div id="previewIcon" class="app-custom-icon" ng-click="applinksEdit.showCustomIconSelector()">
|
||||
<img ng-src="{{ applinksEdit.iconUrl() || 'img/appicon_fallback.png' }}" fallback-icon="img/appicon_fallback.png" onerror="imageErrorHandler(this)"/>
|
||||
<i class="picture-edit-indicator fa fa-pencil-alt"></i>
|
||||
</div>
|
||||
<a href="" style="font-weight: normal;" ng-click="applinksEdit.resetCustomIcon()">{{ 'app.applinks.clearIconAction' | tr }}</a> - <span class="text-small">{{ 'app.applinks.clearIconDescription' | tr }}</span>
|
||||
<input type="file" id="applinksEditIconFileInput" style="display: none" accept="image/png"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">{{ 'app.display.tags' | tr }}</label>
|
||||
<tag-input class="form-control" placeholder="{{ 'app.display.tagsPlaceholder' | tr }}" taglist="applinksEdit.tags" name="tags" uib-tooltip="{{ 'app.display.tagsTooltip' | tr }}"></tag-input>
|
||||
</div>
|
||||
|
||||
<label class="control-label">{{ 'app.accessControl.userManagement.dashboardVisibility' | tr }} <sup><a ng-href="https://docs.cloudron.io/apps/#dashboard-visibility" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
||||
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" ng-model="applinksEdit.accessRestrictionOption" value="any">
|
||||
<span>{{ 'app.accessControl.userManagement.visibleForAllUsers' | tr }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" ng-model="applinksEdit.accessRestrictionOption" value="groups">
|
||||
<span>{{ 'app.accessControl.userManagement.visibleForSelected' | tr }}</span>
|
||||
<span class="label label-danger" ng-show="applinksEdit.accessRestrictionOption === 'groups' && !applinksEdit.isAccessRestrictionValid()">{{ 'appstore.installDialog.errorUserManagementSelectAtLeastOne' | tr }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<div style="margin-left: 20px; display: flex;">
|
||||
<div>
|
||||
{{ 'appstore.installDialog.users' | tr }}: <multiselect name="accessUsersSelect" class="input-sm stretch" ng-model="applinksEdit.accessRestriction.users" ng-disabled="applinksEdit.accessRestrictionOption !== 'groups'" options="(user.username || user.email) for user in allUsers" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{ 'appstore.installDialog.groups' | tr }}: <multiselect name="accessGroupsSelect" class="input-sm stretch" ng-model="applinksEdit.accessRestriction.groups" ng-disabled="applinksEdit.accessRestrictionOption !== 'groups'" options="group.name for group in allGroups" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input class="ng-hide" type="submit" ng-disabled="applinksEditForm.$invalid || applinksEdit.busyEdit || applinks.busyRemove"/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger pull-left" ng-click="applinksEdit.remove()" ng-disabled="applinksEdit.busyRemove || applinksEdit.busyEdit"><i class="fa fa-circle-notch fa-spin" ng-show="applinksEdit.busyRemove"></i> {{ 'app.editApplinkDialog.deleteAction' | tr }}</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
|
||||
<button type="button" class="btn btn-success" ng-click="applinksEdit.submit()" ng-disabled="applinksEditForm.$invalid || applinksEdit.busyRemove || applinksEdit.busyEdit"><i class="fa fa-circle-notch fa-spin" ng-show="applinksEdit.busyEdit"></i> {{ 'main.dialog.save' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content content-large">
|
||||
|
||||
<!-- Workaround for select-all issue, see commit message -->
|
||||
<div style="font-size: 1px;"> </div>
|
||||
|
||||
<div class="animateMeOpacity ng-hide" ng-show="installedApps.length === 0 && user.isAtLeastAdmin">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
<br/><br/><br/><br/>
|
||||
<h1><i class="fa fa-cloud-download fa-fw"></i> {{ 'apps.noApps.title' | tr }}</h1>
|
||||
<br/></br>
|
||||
<h3 ng-bind-html="'apps.noApps.description' | tr:{ appStoreLink: '#/appstore' }"></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="animateMeOpacity ng-hide" ng-show="installedApps.length === 0 && !user.isAtLeastAdmin">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
<br/><br/><br/><br/>
|
||||
<h1>{{ 'apps.noAccess.title' | tr }}</h1>
|
||||
<br/></br>
|
||||
<h3>{{ 'apps.noAccess.description' | tr }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 class="view-header" ng-show="installedApps.length > 0">
|
||||
{{ 'apps.title' | tr }}
|
||||
<div class="view-header-search-bar">
|
||||
<form class="form-inline">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="{{ 'apps.searchPlaceholder' | tr }} ( / )" id="appSearch" ng-model="appSearch"/>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button" ng-class="{ 'active': showFilter }" ng-click="toggleFilter()"><i class="fas fa-filter"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
<button class="btn btn-default" style="margin-left: 10px;" type="button" ng-click="toggleView()"><i class="fas" ng-class="{ 'fa-list': view === VIEWS.GRID, 'fa-grip': view === VIEWS.LIST }"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
<div ng-show="showFilter" class="view-header-filter-bar">
|
||||
<form class="form-inline">
|
||||
<multiselect ng-model="selectedGroup" ng-show="user.isAtLeastAdmin && groups.length > 1" ms-header="{{ selectedGroup.name }}" options="group.name for group in groups" data-multiple="false" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
||||
<multiselect ng-model="selectedState" ng-show="user.isAtLeastAdmin" ms-header="{{ 'apps.stateFilterHeader' | tr }}" ms-selected="{{ selectedState }}" options="state.label for state in states" data-multiple="false"></multiselect>
|
||||
<multiselect ng-model="selectedTags" ng-show="user.isAtLeastAdmin && tags.length > 0" ms-header="{{ 'apps.tagsFilterHeaderAll' | tr }}" ms-selected="{{ 'apps.tagsFilterHeader' | tr:{ tags: selectedTags.join(', ') } }}" options="tag for tag in tags" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
||||
<multiselect ng-model="selectedDomain" data-compare-by="domain" ms-selected="{{ selectedDomain.domain }}" options="domain.domain for domain in filterDomains" data-multiple="false" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
||||
<!-- <button class="btn btn-primary" ng-disabled="!selectedTags.length && !selectedState.state && selectedGroup._unset && selectedDomain._alldomains" ng-click="clearAllFilter()">{{ 'apps.filter.clearAll' | tr }}</button> -->
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="animateMeOpacity ng-hide" ng-show="installedApps.length > 0">
|
||||
<div class="app-grid" ng-show="view === VIEWS.GRID">
|
||||
<div class="grid-item" ng-class="{ 'stopped': app.runState === 'stopped' }" ng-repeat="app in installedApps | selectedGroupAccessFilter:selectedGroup | selectedStateFilter:selectedState | selectedTagFilter:selectedTags | selectedDomainFilter:selectedDomain | appSearchFilter:appSearch | orderBy:orderByFilter">
|
||||
<div class="grid-item-content" uib-tooltip="{{ app.fqdn }}" tooltip-append-to-body="true">
|
||||
<a ng-show="app.type !== APP_TYPES.LINK && isOperator(app)" ng-href="#/app/{{ app.id}}/info" class="btn btn-lg btn-default grid-item-action"><i class="fas fa-cog"></i></a>
|
||||
<div ng-show="app.type === APP_TYPES.LINK && isOperator(app)" ng-click="applinksEdit.show(app)" class="btn btn-lg btn-default grid-item-action"><i class="fas fa-cog"></i></div>
|
||||
<a ng-href="{{ app | applicationLink }}" ng-click="onAppClick(app, $event)" target="_blank">
|
||||
<div class="grid-item-top">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 text-center" style="padding-left: 5px; padding-right: 5px;">
|
||||
<img ng-src="{{ app.iconUrl || 'img/appicon_fallback.png' }}" fallback-icon="img/appicon_fallback.png" onerror="imageErrorHandler(this)" class="app-icon"/>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 text-center">
|
||||
<div class="grid-item-top-title" data-fittext>{{ app.label || app.subdomain || app.fqdn }}</div>
|
||||
<div class="text-muted status" style="text-overflow: ellipsis; white-space: nowrap; overflow: hidden" uib-tooltip="{{ app | appProgressMessage }}">
|
||||
{{ app | installationStateLabel }}
|
||||
</div>
|
||||
<div class="status" ng-style="{ 'visibility': isOperator(app) && (app | installationActive) ? 'visible' : 'hidden' }">
|
||||
<div class="progress progress-striped active">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ app.progress }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="usermanagement-indicator" ng-show="app.type !== APP_TYPES.LINK">
|
||||
<i class="fa-brands fa-openid" ng-show="app.ssoAuth && app.manifest.addons.oidc" uib-tooltip="{{ 'apps.auth.openid' | tr }}" tooltip-placement="right"></i>
|
||||
<i class="fas fa-user" ng-show="app.ssoAuth && (!app.manifest.addons.oidc && !app.manifest.addons.email)" uib-tooltip="{{ 'apps.auth.sso' | tr }}" tooltip-placement="right"></i>
|
||||
<i class="far fa-user" ng-show="!app.ssoAuth && !app.manifest.addons.email" uib-tooltip="{{ 'apps.auth.nosso' | tr }}" tooltip-placement="right"></i>
|
||||
<i class="fas fa-envelope" ng-show="app.manifest.addons.email" uib-tooltip="{{ 'apps.auth.email' | tr }}" tooltip-placement="right"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- we check the version here because the box updater does not know when an app gets updated -->
|
||||
<!-- update info is available to app users. but we should show update indicator only for operators since normal users cannot update -->
|
||||
<div class="app-update-badge" ng-click="showAppConfigure(app, 'updates')" ng-show="isOperator(app) && config.update[app.id].manifest.version && config.update[app.id].manifest.version !== app.manifest.version && (app | installSuccess) && !(app.error || app.runState === 'stopped')" uib-tooltip="Update Available">
|
||||
<i class="fa fa-arrow-up fa-inverse"></i>
|
||||
</div>
|
||||
|
||||
<div class="app-checklist-badge" ng-click="showAppConfigure(app, 'info')" ng-show="pendingChecklistItems(app)">
|
||||
{{ pendingChecklistItems(app) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="app-list card card-large" ng-show="view === VIEWS.LIST">
|
||||
<table class="table table-hover" style="margin: 0;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 32px" class="hand" ng-click="setOrderBy('status')"><i ng-show="orderBy === 'status'" class="fas fa-arrow-{{ orderByReverse ? 'up' : 'down' }}-long"></i></th>
|
||||
<th style="width: 32px"> </th>
|
||||
<th style="width: 35%" class="hand" ng-click="setOrderBy('location')">{{ 'app.display.label' | tr }} <i ng-show="orderBy === 'location'" class="fas fa-arrow-{{ orderByReverse ? 'up' : 'down' }}-long"></i></th>
|
||||
<th style="width: 30%" class="hand hide-mobile" ng-click="setOrderBy('app')">App Title<i ng-show="orderBy === 'app'" class="fas fa-arrow-{{ orderByReverse ? 'up' : 'down' }}-long"></i></th>
|
||||
<th style="width: 32px" class="hide-mobile"> </th>
|
||||
<th style="width: 32px" class="hand hide-mobile text-center" ng-click="setOrderBy('sso')"><i class="fas fa-user-lock"></i> <i ng-show="orderBy === 'sso'" class="fas fa-arrow-{{ orderByReverse ? 'up' : 'down' }}-long"></i></th>
|
||||
<th style="width:160px" class="text-right">{{ 'main.actions' | tr }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="app-list-item" ng-repeat="app in installedApps | selectedGroupAccessFilter:selectedGroup | selectedStateFilter:selectedState | selectedTagFilter:selectedTags | selectedDomainFilter:selectedDomain | appSearchFilter:appSearch | orderBy:orderByFilter:orderByReverse" uib-tooltip="{{ app | appProgressMessage }}">
|
||||
<td class="elide-table-cell">
|
||||
<i class="fa fa-circle" ng-class="app | installationStateClass" uib-tooltip="{{ app | installationStateLabel }}"></i>
|
||||
</td>
|
||||
<td class="elide-table-cell app-list-app-link-cell">
|
||||
<a ng-href="{{ app | applicationLink }}" ng-click="onAppClick(app, $event)" target="_blank" class="app-list-app-link">
|
||||
<img ng-src="{{ app.iconUrl || 'img/appicon_fallback.png' }}" fallback-icon="img/appicon_fallback.png" onerror="imageErrorHandler(this)" class="app-list-item-icon"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="elide-table-cell app-list-app-link-cell">
|
||||
<a ng-href="{{ app | applicationLink }}" ng-click="onAppClick(app, $event)" target="_blank" class="app-list-app-link">
|
||||
<span style="font-size: 16px;">{{ app.label || app.subdomain || app.fqdn }}</span><br/>
|
||||
<span class="text-muted text-small">{{ app.fqdn.indexOf('http') === 0 ? app.fqdn : 'https://'+app.fqdn }}</span>
|
||||
</a>
|
||||
</td>
|
||||
<td class="elide-table-cell hide-mobile">{{ app.manifest.title || 'App Link' }}</td>
|
||||
<td class="elide-table-cell hide-mobile text-center">
|
||||
<a class="badge badge-danger" ng-show="pendingChecklistItems(app)" ng-href="#/app/{{ app.id}}/info">{{ pendingChecklistItems(app) }}</a>
|
||||
</td>
|
||||
<td class="elide-table-cell hide-mobile text-center">
|
||||
<div ng-show="app.type !== APP_TYPES.LINK">
|
||||
<i class="fa-brands fa-openid" ng-show="app.ssoAuth && app.manifest.addons.oidc" uib-tooltip="{{ 'apps.auth.openid' | tr }}"></i>
|
||||
<i class="fas fa-user" ng-show="app.ssoAuth && (!app.manifest.addons.oidc && !app.manifest.addons.email)" uib-tooltip="{{ 'apps.auth.sso' | tr }}"></i>
|
||||
<i class="far fa-user" ng-show="!app.ssoAuth && !app.manifest.addons.email" uib-tooltip="{{ 'apps.auth.nosso' | tr }}"></i>
|
||||
<i class="fas fa-envelope" ng-show="app.manifest.addons.email" uib-tooltip="{{ 'apps.auth.email' | tr }}"></i>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-right" style="vertical-align: middle; white-space: nowrap;">
|
||||
<span ng-show="isOperator(app)">
|
||||
<a class="btn btn-xs btn-success" style="padding: 1px 7px;" ng-show="config.update[app.id].manifest.version && config.update[app.id].manifest.version !== app.manifest.version && (app | installSuccess) && !(app.error || app.runState === 'stopped')" ng-href="#/app/{{ app.id}}/updates" uib-tooltip="Update Available"><i class="fa fa-arrow-up"></i></a>
|
||||
|
||||
<div class="btn-group btn-group-xs" role="group">
|
||||
<a class="btn btn-xs btn-default" ng-show="app.type !== APP_TYPES.LINK" ng-href="{{ '/logs.html?appId=' + app.id }}" target="_blank" tooltip-append-to-body="true" uib-tooltip="{{ 'app.logsActionTooltip' | tr }}"><i class="fas fa-align-left"></i></a>
|
||||
<a class="btn btn-xs btn-default" ng-show="app.type !== APP_TYPES.PROXIED && app.type !== APP_TYPES.LINK" ng-href="{{ '/terminal.html?id=' + app.id }}" target="_blank" tooltip-append-to-body="true" uib-tooltip="{{ 'app.terminalActionTooltip' | tr }}"><i class="fa fa-terminal"></i></a>
|
||||
<a class="btn btn-xs btn-default" ng-show="app.manifest.addons.localstorage" ng-href="{{ '/filemanager.html#/home/app/' + app.id }}" target="_blank" tooltip-append-to-body="true" uib-tooltip="{{ 'app.filemanagerActionTooltip' | tr }}"><i class="fas fa-folder"></i></a>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-xs btn-default" ng-show="app.type === APP_TYPES.LINK" ng-click="applinksEdit.show(app)" uib-tooltip="Configure Applink"><i class="fa fa-cog"></i></button>
|
||||
<a class="btn btn-xs btn-default" ng-show="app.type !== APP_TYPES.LINK" ng-href="#/app/{{ app.id}}/info" uib-tooltip="Configure App"><i class="fa fa-cog"></i></a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br/>
|
||||
<div>
|
||||
{{ 'apps.apps.count' | tr:{ count: (installedApps | selectedGroupAccessFilter:selectedGroup | selectedStateFilter:selectedState | selectedTagFilter:selectedTags | selectedDomainFilter:selectedDomain | appSearchFilter:appSearch).length } }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,389 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/* global angular:false */
|
||||
/* global $:false */
|
||||
/* global APP_TYPES */
|
||||
/* global onAppClick */
|
||||
|
||||
angular.module('Application').controller('AppsController', ['$scope', '$translate', '$interval', '$location', 'Client', function ($scope, $translate, $interval, $location, Client) {
|
||||
var ALL_DOMAINS_DOMAIN = { _alldomains: true, domain: 'All Domains' }; // dummy record for the single select filter
|
||||
var GROUP_ACCESS_UNSET = { _unset: true, name: 'Select Group' }; // dummy record for the single select filter
|
||||
|
||||
$scope.installedApps = Client.getInstalledApps();
|
||||
$scope.tags = Client.getAppTags();
|
||||
$scope.states = [
|
||||
{ state: '', label: 'All States' },
|
||||
{ state: 'running', label: 'Running' },
|
||||
{ state: 'stopped', label: 'Stopped' },
|
||||
{ state: 'update_available', label: 'Update Available' },
|
||||
{ state: 'not_responding', label: 'Not Responding' }
|
||||
];
|
||||
$scope.selectedState = $scope.states[0];
|
||||
$scope.selectedTags = [];
|
||||
$scope.selectedGroup = GROUP_ACCESS_UNSET;
|
||||
$scope.selectedDomain = ALL_DOMAINS_DOMAIN;
|
||||
$scope.filterDomains = [ ALL_DOMAINS_DOMAIN ];
|
||||
$scope.config = Client.getConfig();
|
||||
$scope.user = Client.getUserInfo();
|
||||
$scope.domains = [];
|
||||
$scope.appSearch = '';
|
||||
$scope.groups = [ GROUP_ACCESS_UNSET ];
|
||||
$scope.APP_TYPES = APP_TYPES;
|
||||
$scope.showFilter = false;
|
||||
$scope.filterActive = false;
|
||||
|
||||
$scope.VIEWS = {
|
||||
GRID: 'grid',
|
||||
LIST: 'list'
|
||||
};
|
||||
$scope.view = $scope.VIEWS.GRID;
|
||||
|
||||
$scope.orderBy = 'location'; // or app, status, sso
|
||||
$scope.orderByReverse = false;
|
||||
|
||||
$scope.allUsers = [];
|
||||
$scope.allGroups = [];
|
||||
|
||||
$translate(['apps.stateFilterHeader', 'apps.domainsFilterHeader', 'apps.groupsFilterHeader', 'app.states.running', 'app.states.stopped', 'app.states.notResponding', 'app.states.updateAvailable']).then(function (tr) {
|
||||
if (tr['apps.domainsFilterHeader']) ALL_DOMAINS_DOMAIN.domain = tr['apps.domainsFilterHeader'];
|
||||
if (tr['apps.groupsFilterHeader']) GROUP_ACCESS_UNSET.name = tr['apps.groupsFilterHeader'];
|
||||
if (tr['apps.stateFilterHeader']) $scope.states[0].label = tr['apps.stateFilterHeader'];
|
||||
if (tr['app.states.running']) $scope.states[1].label = tr['app.states.running'];
|
||||
if (tr['app.states.stopped']) $scope.states[2].label = tr['app.states.stopped'];
|
||||
if (tr['app.states.notResponding']) $scope.states[4].label = tr['app.states.notResponding'];
|
||||
if (tr['app.states.updateAvailable']) $scope.states[3].label = tr['app.states.updateAvailable'];
|
||||
});
|
||||
|
||||
$scope.pendingChecklistItems = function (app) {
|
||||
if (!app.checklist) return 0;
|
||||
return Object.keys(app.checklist).filter(function (key) { return !app.checklist[key].acknowledged; }).length;
|
||||
};
|
||||
|
||||
$scope.setOrderBy = function (by) {
|
||||
if (by === $scope.orderBy) {
|
||||
$scope.orderByReverse = !$scope.orderByReverse;
|
||||
} else {
|
||||
$scope.orderBy = by;
|
||||
$scope.orderByReverse = false;
|
||||
}
|
||||
|
||||
localStorage.appsOrderBy = by;
|
||||
if ($scope.orderByReverse) localStorage.appsOrderByReverse = true;
|
||||
else localStorage.removeItem('appsOrderByReverse');
|
||||
};
|
||||
|
||||
// for sorting/grouping
|
||||
$scope.orderByFilter = function (item) {
|
||||
if ($scope.orderBy === 'app') return item.manifest.title || 'App Link';
|
||||
if ($scope.orderBy === 'status') return item.installationState + '-' + item.runState;
|
||||
if ($scope.orderBy === 'sso') {
|
||||
if (item.ssoAuth && item.manifest.addons.oidc) return 'oidc';
|
||||
if (item.ssoAuth && (!item.manifest.addons.oidc && !item.manifest.addons.email)) return 'sso';
|
||||
if (item.manifest.addons.email) return 'email';
|
||||
return '';
|
||||
}
|
||||
return item.label || item.fqdn;
|
||||
};
|
||||
|
||||
$scope.setView = function (view) {
|
||||
if (view !== $scope.VIEWS.LIST && view !== $scope.VIEWS.GRID) return;
|
||||
|
||||
$scope.view = view;
|
||||
localStorage.appsView = view;
|
||||
};
|
||||
|
||||
$scope.toggleView = function () {
|
||||
$scope.view = $scope.view === $scope.VIEWS.GRID ? $scope.VIEWS.LIST : $scope.VIEWS.GRID;
|
||||
localStorage.appsView = $scope.view;
|
||||
};
|
||||
|
||||
$scope.toggleFilter = function () {
|
||||
$scope.showFilter = !$scope.showFilter;
|
||||
|
||||
if ($scope.showFilter) localStorage.appsShowFilter = true;
|
||||
else localStorage.removeItem('appsShowFilter');
|
||||
|
||||
// clear on hide
|
||||
if (!$scope.showFilter) {
|
||||
$scope.selectedState = $scope.states[0];
|
||||
$scope.selectedTags = [];
|
||||
$scope.selectedGroup = GROUP_ACCESS_UNSET;
|
||||
$scope.selectedDomain = ALL_DOMAINS_DOMAIN;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watch('selectedTags', function (newVal, oldVal) {
|
||||
if (newVal === oldVal) return;
|
||||
|
||||
localStorage.selectedTags = newVal.join(',');
|
||||
});
|
||||
|
||||
$scope.$watch('selectedState', function (newVal, oldVal) {
|
||||
if (newVal === oldVal) return;
|
||||
|
||||
if (newVal === $scope.states[0]) localStorage.removeItem('selectedState');
|
||||
else localStorage.selectedState = newVal.state;
|
||||
});
|
||||
|
||||
$scope.$watch('selectedGroup', function (newVal, oldVal) {
|
||||
if (newVal === oldVal) return;
|
||||
|
||||
if (newVal === GROUP_ACCESS_UNSET) localStorage.removeItem('selectedGroup');
|
||||
else localStorage.selectedGroup = newVal.id;
|
||||
});
|
||||
|
||||
$scope.$watch('selectedDomain', function (newVal, oldVal) {
|
||||
if (newVal === oldVal) return;
|
||||
|
||||
if (newVal._alldomains) localStorage.removeItem('selectedDomain');
|
||||
else localStorage.selectedDomain = newVal.domain;
|
||||
});
|
||||
|
||||
$scope.onAppClick = function (app, $event) { onAppClick(app, $event, $scope.isOperator(app), $scope); };
|
||||
|
||||
$scope.appPostInstallConfirm = {
|
||||
app: {},
|
||||
message: '',
|
||||
|
||||
show: function (app) {
|
||||
$scope.appPostInstallConfirm.app = app;
|
||||
$scope.appPostInstallConfirm.message = app.manifest.postInstallMessage;
|
||||
|
||||
$('#appsPostInstallConfirmModal').modal('show');
|
||||
|
||||
return false; // prevent propagation and default
|
||||
},
|
||||
|
||||
submit: function () {
|
||||
$scope.appPostInstallConfirm.app.pendingPostInstallConfirmation = false;
|
||||
delete localStorage['confirmPostInstall_' + $scope.appPostInstallConfirm.app.id];
|
||||
|
||||
$('#appsPostInstallConfirmModal').modal('hide');
|
||||
}
|
||||
};
|
||||
|
||||
$scope.applinksEdit = {
|
||||
error: {},
|
||||
busyEdit: false,
|
||||
busyRemove: false,
|
||||
applink: {},
|
||||
id: '',
|
||||
upstreamUri: '',
|
||||
label: '',
|
||||
tags: '',
|
||||
accessRestrictionOption: '',
|
||||
accessRestriction: { users: [], groups: [] },
|
||||
icon: { data: null },
|
||||
|
||||
iconUrl: function () {
|
||||
if ($scope.applinksEdit.icon.data === '__original__') { // user clicked reset
|
||||
// https://png-pixel.com/ white pixel placeholder
|
||||
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=';
|
||||
} else if ($scope.applinksEdit.icon.data) { // user uploaded icon
|
||||
return $scope.applinksEdit.icon.data;
|
||||
} else { // current icon
|
||||
return $scope.applinksEdit.applink.iconUrl;
|
||||
}
|
||||
},
|
||||
|
||||
resetCustomIcon: function () {
|
||||
$scope.applinksEdit.icon.data = '__original__';
|
||||
},
|
||||
|
||||
showCustomIconSelector: function () {
|
||||
$('#applinksEditIconFileInput').click();
|
||||
},
|
||||
|
||||
isAccessRestrictionValid: function () {
|
||||
return !!($scope.applinksEdit.accessRestriction.users.length || $scope.applinksEdit.accessRestriction.groups.length);
|
||||
},
|
||||
|
||||
show: function (applink) {
|
||||
$scope.applinksEdit.error = {};
|
||||
$scope.applinksEdit.busyEdit = false;
|
||||
$scope.applinksEdit.busyRemove = false;
|
||||
$scope.applinksEdit.applink = applink;
|
||||
$scope.applinksEdit.id = applink.id;
|
||||
$scope.applinksEdit.upstreamUri = applink.upstreamUri;
|
||||
$scope.applinksEdit.label = applink.label;
|
||||
$scope.applinksEdit.accessRestrictionOption = applink.accessRestriction ? 'groups' : 'any';
|
||||
$scope.applinksEdit.accessRestriction = { users: [], groups: [] };
|
||||
$scope.applinksEdit.icon = { data: null };
|
||||
|
||||
var userSet, groupSet;
|
||||
if (applink.accessRestriction) {
|
||||
userSet = {};
|
||||
applink.accessRestriction.users.forEach(function (uid) { userSet[uid] = true; });
|
||||
$scope.allUsers.forEach(function (u) { if (userSet[u.id] === true) $scope.applinksEdit.accessRestriction.users.push(u); });
|
||||
|
||||
groupSet = {};
|
||||
if (applink.accessRestriction.groups) applink.accessRestriction.groups.forEach(function (gid) { groupSet[gid] = true; });
|
||||
$scope.allGroups.forEach(function (g) { if (groupSet[g.id] === true) $scope.applinksEdit.accessRestriction.groups.push(g); });
|
||||
}
|
||||
|
||||
// translate for tag-input
|
||||
$scope.applinksEdit.tags = applink.tags ? applink.tags.join(' ') : '';
|
||||
|
||||
$scope.applinksEditForm.$setUntouched();
|
||||
$scope.applinksEditForm.$setPristine();
|
||||
|
||||
$('#applinksEditModal').modal('show');
|
||||
|
||||
return false; // prevent propagation and default
|
||||
},
|
||||
|
||||
submit: function () {
|
||||
$scope.applinksEdit.busyEdit = true;
|
||||
$scope.applinksEdit.error = {};
|
||||
|
||||
var accessRestriction = null;
|
||||
if ($scope.applinksEdit.accessRestrictionOption === 'groups') {
|
||||
accessRestriction = { users: [], groups: [] };
|
||||
accessRestriction.users = $scope.applinksEdit.accessRestriction.users.map(function (u) { return u.id; });
|
||||
accessRestriction.groups = $scope.applinksEdit.accessRestriction.groups.map(function (g) { return g.id; });
|
||||
}
|
||||
|
||||
var data = {
|
||||
upstreamUri: $scope.applinksEdit.upstreamUri,
|
||||
label: $scope.applinksEdit.label,
|
||||
accessRestriction: accessRestriction,
|
||||
tags: $scope.applinksEdit.tags.split(' ').map(function (t) { return t.trim(); }).filter(function (t) { return !!t; })
|
||||
};
|
||||
|
||||
if ($scope.applinksEdit.icon.data === '__original__') { // user reset the icon
|
||||
data.icon = '';
|
||||
} else if ($scope.applinksEdit.icon.data) { // user loaded custom icon
|
||||
data.icon = $scope.applinksEdit.icon.data.replace(/^data:image\/[a-z]+;base64,/, '');
|
||||
}
|
||||
|
||||
Client.updateApplink($scope.applinksEdit.id, data, function (error) {
|
||||
$scope.applinksEdit.busyEdit = false;
|
||||
|
||||
if (error && error.statusCode === 400 && error.message.includes('upstreamUri')) {
|
||||
$scope.applinksEdit.error.upstreamUri = error.message;
|
||||
$scope.applinksEditForm.$setUntouched();
|
||||
$scope.applinksEditForm.$setPristine();
|
||||
return;
|
||||
}
|
||||
if (error) return console.error('Failed to update applink', error);
|
||||
|
||||
Client.refreshInstalledApps();
|
||||
|
||||
$('#applinksEditModal').modal('hide');
|
||||
});
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
$scope.applinksEdit.busyRemove = true;
|
||||
|
||||
Client.removeApplink($scope.applinksEdit.id, function (error) {
|
||||
$scope.applinksEdit.busyRemove = false;
|
||||
|
||||
if (error) return console.error('Failed to remove applink', error);
|
||||
|
||||
Client.refreshInstalledApps();
|
||||
|
||||
$('#applinksEditModal').modal('hide');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.showAppConfigure = function (app, view) {
|
||||
$location.path('/app/' + app.id + '/' + view);
|
||||
};
|
||||
|
||||
$scope.isOperator = function (app) {
|
||||
return app.accessLevel === 'operator' || app.accessLevel === 'admin';
|
||||
};
|
||||
|
||||
Client.onReady(function () {
|
||||
setTimeout(function () { $('#appSearch').focus(); }, 1);
|
||||
|
||||
// refresh the new list immediately when switching from another view (appstore)
|
||||
Client.refreshInstalledApps(function () {
|
||||
var refreshAppsTimer = $interval(Client.refreshInstalledApps.bind(Client, function () {}), 5000);
|
||||
$scope.$on('$destroy', function () {
|
||||
$interval.cancel(refreshAppsTimer);
|
||||
});
|
||||
});
|
||||
|
||||
$scope.setView(localStorage.appsView);
|
||||
|
||||
$scope.orderBy = localStorage.appsOrderBy || 'location';
|
||||
$scope.orderByReverse = !!localStorage.appsOrderByReverse;
|
||||
$scope.showFilter = !!localStorage.appsShowFilter;
|
||||
|
||||
if (!$scope.user.isAtLeastAdmin) return;
|
||||
|
||||
// load local settings and apply tag filter
|
||||
if (localStorage.selectedTags) {
|
||||
if (!$scope.tags.length) localStorage.removeItem('selectedTags');
|
||||
else $scope.selectedTags = localStorage.selectedTags.split(',');
|
||||
}
|
||||
|
||||
if (localStorage.selectedState) $scope.selectedState = $scope.states.find(function (s) { return s.state === localStorage.selectedState; }) || $scope.states[0];
|
||||
|
||||
Client.getGroups(function (error, result) {
|
||||
if (error) Client.error(error);
|
||||
|
||||
$scope.groups = [ GROUP_ACCESS_UNSET ].concat(result);
|
||||
$scope.allGroups = result;
|
||||
|
||||
if (localStorage.selectedGroup) $scope.selectedGroup = $scope.groups.find(function (g) { return g.id === localStorage.selectedGroup; }) || GROUP_ACCESS_UNSET;
|
||||
});
|
||||
|
||||
Client.getDomains(function (error, result) {
|
||||
if (error) Client.error(error);
|
||||
|
||||
$scope.domains = result;
|
||||
$scope.filterDomains = [ALL_DOMAINS_DOMAIN].concat(result);
|
||||
|
||||
if (localStorage.selectedDomain) $scope.selectedDomain = $scope.filterDomains.find(function (d) { return d.domain === localStorage.selectedDomain; }) || ALL_DOMAINS_DOMAIN;
|
||||
});
|
||||
|
||||
Client.getAllUsers(function (error, users) {
|
||||
if (error) Client.error(error);
|
||||
|
||||
$scope.allUsers = users;
|
||||
});
|
||||
});
|
||||
|
||||
$('#applinksEditIconFileInput').get(0).onchange = function (event) {
|
||||
var fr = new FileReader();
|
||||
fr.onload = function () {
|
||||
$scope.$apply(function () {
|
||||
// var file = event.target.files[0];
|
||||
$scope.applinksEdit.icon.data = fr.result;
|
||||
});
|
||||
};
|
||||
fr.readAsDataURL(event.target.files[0]);
|
||||
};
|
||||
|
||||
// setup all the dialog focus handling
|
||||
['applinksAddModal', 'applinksEditModal'].forEach(function (id) {
|
||||
$('#' + id).on('shown.bs.modal', function () {
|
||||
$(this).find('autofocus]:first').focus();
|
||||
});
|
||||
});
|
||||
|
||||
$('.collapse').on('shown.bs.collapse', function(){
|
||||
$(this).parent().find('.fa-angle-right').removeClass('fa-angle-right').addClass('fa-angle-down');
|
||||
}).on('hidden.bs.collapse', function(){
|
||||
$(this).parent().find('.fa-angle-down').removeClass('fa-angle-down').addClass('fa-angle-right');
|
||||
});
|
||||
|
||||
$('.modal-backdrop').remove();
|
||||
|
||||
function keyboardHandler(event) {
|
||||
if (event.key === '/') {
|
||||
document.getElementById('appSearch').focus();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', keyboardHandler);
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
document.removeEventListener('keydown', keyboardHandler);
|
||||
});
|
||||
}]);
|
||||
@@ -1,481 +0,0 @@
|
||||
|
||||
<!-- Modal install app -->
|
||||
<div class="modal fade appstore-install" id="appInstallModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<img ng-src="{{appInstall.app.iconUrl}}" onerror="this.onerror=null; this.src='img/appicon_fallback.png'" class="app-icon"/>
|
||||
<h3 class="appstore-install-title">{{ appInstall.app.manifest.title }}</h3>
|
||||
<br/>
|
||||
<span class="appstore-install-meta"><a href="{{ appInstall.app.manifest.website }}" target="_blank">{{ appInstall.app.manifest.author }}</a></span>
|
||||
<br/>
|
||||
<span class="appstore-install-meta">{{ 'appstore.installDialog.lastUpdated' | tr:{ date: (appInstall.app.creationDate | prettyDate) } }}</span>
|
||||
<br/>
|
||||
<span class="appstore-install-meta">{{ 'appstore.installDialog.memoryRequirement' | tr:{ size: (appInstall.app.manifest.memoryLimit | prettyBinarySize:'256 MB') } }}</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="collapse" id="collapseInstallForm" data-toggle="false">
|
||||
<form role="form" name="appInstallForm" ng-submit="appInstall.submit()" autocomplete="off">
|
||||
<div class="has-error text-center" ng-show="appInstall.error.other" ng-bind-html="appInstall.error.other"></div>
|
||||
<div class="form-group" ng-class="{ 'has-error': (appInstallForm.location.$dirty && appInstallForm.location.$invalid) || (!appInstallForm.location.$dirty && appInstall.error.location) }">
|
||||
<label class="control-label" for="appInstallLocationInput">{{ 'appstore.installDialog.location' | tr }}</label>
|
||||
<div class="input-group form-inline">
|
||||
<input type="text" class="form-control" ng-model="appInstall.subdomain" id="appInstallLocationInput" name="location" placeholder="{{ 'appstore.installDialog.locationPlaceholder' | tr }}" autofocus>
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span>{{ '.' + appInstall.domain.domain }}</span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<li ng-repeat="domain in domains">
|
||||
<a href="" ng-click="appInstall.domain = domain">{{ domain.domain }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="appInstall.error.location" class="text-small">{{ appInstall.error.location }}</div>
|
||||
</div>
|
||||
|
||||
<p class="text-small text-warning" ng-show="appInstall.domain.provider === 'noop' || appInstall.domain.provider === 'manual'" ng-bind-html="'appstore.installDialog.manualWarning' | tr:{ location: ((appInstall.subdomain ? appInstall.subdomain + '.' : '') + appInstall.domain.domain) }"></p>
|
||||
|
||||
<div class="has-error text-center" ng-show="appInstall.error.secondaryDomain">{{ appInstall.error.secondaryDomain }}</div>
|
||||
<div ng-repeat="(env, info) in appInstall.app.manifest.httpPorts">
|
||||
<ng-form name="secondaryDomainInfo_form">
|
||||
<div class="form-group" ng-class="{ 'has-error': (!secondaryDomainInfo_form.itemName{{$index}}.$dirty && appInstall.error.secondaryDomain) || (secondaryDomainInfo_form.itemName{{$index}}.$dirty && secondaryDomainInfo_form.itemName{{$index}}.$invalid) }">
|
||||
<label class="control-label" for="secondaryDomainInput{{env}}">
|
||||
{{ info.title }}
|
||||
<sup>
|
||||
<a popover-placement="top-right" popover-trigger="outsideClick" uib-popover="{{info.description}}"><i class="fa fa-question-circle"></i></a>
|
||||
</sup>
|
||||
</label>
|
||||
|
||||
<div class="input-group form-inline">
|
||||
<input type="text" class="form-control" ng-model="appInstall.secondaryDomains[env].subdomain" name="location{{$index}}" placeholder="{{ 'appstore.installDialog.locationPlaceholder' | tr }}" autofocus>
|
||||
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span>.{{ appInstall.secondaryDomains[env].domain.domain }}</span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<li ng-repeat="domain in domains">
|
||||
<a href="" ng-click="appInstall.secondaryDomains[env].domain = domain">{{ domain.domain }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
<div class="has-error text-center" ng-show="appInstall.error.port">{{ appInstall.error.port }}</div>
|
||||
<div ng-repeat="(env, info) in appInstall.portInfo">
|
||||
<ng-form name="portInfo_form">
|
||||
<div class="form-group" ng-class="{ 'has-error': (!appInstallForm.itemName{{$index}}.$dirty && appInstall.error.port) || (portInfo_form.itemName{{$index}}.$dirty && portInfo_form.itemName{{$index}}.$invalid) }">
|
||||
<label class="control-label" for="inputPortInfo{{env}}"><input type="checkbox" ng-model="appInstall.portsEnabled[env]">
|
||||
{{ info.title }}
|
||||
<sup>
|
||||
<a popover-placement="top-right" popover-trigger="outsideClick" uib-popover="{{info.description}}. {{info.portCount >=1 ? (info.portCount + ' ports. ') : ''}}"><i class="fa fa-question-circle"></i></a>
|
||||
</sup>
|
||||
<small style="padding-left: 5px;" ng-show="info.readOnly">{{ 'appstore.installDialog.portReadOnly' | tr }}</small>
|
||||
</label>
|
||||
<input type="number" class="form-control" ng-model="appInstall.ports[env]" ng-disabled="!appInstall.portsEnabled[env]" ng-readonly="info.readOnly" id="inputPortInfo{{env}}" later-name="itemName{{$index}}" min="{{hostPortMin}}" max="{{hostPortMax}}" required>
|
||||
<p class="text-small text-warning text-bold" ng-show="appInstall.domain.provider === 'cloudflare'">{{ 'appstore.installDialog.cloudflarePortWarning' | tr }} </p>
|
||||
</div>
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="isProxyApp(appInstall.app)">
|
||||
<label class="control-label" for="appInstallUpstreamUriInput">Upstream URI</label>
|
||||
<input type="text" class="form-control" ng-model="appInstall.upstreamUri" id="appInstallUpstreamUriInput" name="upstreamUri" ng-required="isProxyApp(appInstall.app)">
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="appInstall.app.manifest.addons.email">
|
||||
<label class="control-label">{{ 'appstore.installDialog.userManagement' | tr }}</label>
|
||||
<p>{{ 'appstore.installDialog.userManagementMailbox' | tr }}
|
||||
<span ng-bind-html="'appstore.installDialog.configuredForCloudronEmail' | tr:{ emailDocsLink: 'https://docs.cloudron.io/email/' }">
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" ng-show="!appInstall.customAuth && !appInstall.app.manifest.addons.email">{{ 'appstore.installDialog.userManagement' | tr }} <sup><a ng-href="https://docs.cloudron.io/apps/#access-restriction" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
||||
<label class="control-label" ng-show="appInstall.customAuth || appInstall.app.manifest.addons.email">{{ 'app.accessControl.userManagement.dashboardVisibility' | tr }} <sup><a ng-href="https://docs.cloudron.io/apps/#dashboard-visibility" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
||||
|
||||
<p ng-show="appInstall.customAuth || appInstall.app.manifest.addons.email">{{ 'appstore.installDialog.userManagementNone' | tr }}</p>
|
||||
<div class="radio" ng-show="appInstall.optionalSso">
|
||||
<label>
|
||||
<input type="radio" ng-model="appInstall.accessRestrictionOption" value="nosso"> {{ 'appstore.installDialog.userManagementLeaveToApp' | tr }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" ng-model="appInstall.accessRestrictionOption" value="any">
|
||||
<span ng-show="!appInstall.customAuth">{{ 'appstore.installDialog.userManagementAllUsers' | tr }}</span>
|
||||
<span ng-show="appInstall.customAuth">{{ 'app.accessControl.userManagement.visibleForAllUsers' | tr }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" ng-model="appInstall.accessRestrictionOption" value="groups">
|
||||
<span ng-show="!appInstall.customAuth">{{ 'appstore.installDialog.userManagementSelectUsers' | tr }}</span>
|
||||
<span ng-show="appInstall.customAuth">{{ 'app.accessControl.userManagement.visibleForSelected' | tr }}</span>
|
||||
<span class="label label-danger" ng-show="appInstall.accessRestrictionOption === 'groups' && !appInstall.isAccessRestrictionValid()">{{ 'appstore.installDialog.errorUserManagementSelectAtLeastOne' | tr }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<div style="margin-left: 20px;">
|
||||
<div class="col-md-5">
|
||||
{{ 'appstore.installDialog.users' | tr }}:
|
||||
<multiselect ng-model="appInstall.accessRestriction.users" ng-disabled="appInstall.accessRestrictionOption !== 'groups'" options="(user.username || user.email) for user in users" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5">
|
||||
{{ 'appstore.installDialog.groups' | tr }}:
|
||||
<multiselect ng-model="appInstall.accessRestriction.groups" ng-disabled="appInstall.accessRestrictionOption !== 'groups'" options="group.name for group in groups" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<input class="ng-hide" type="submit" ng-disabled="(appInstall.accessRestrictionOption === 'groups' && !appInstall.isAccessRestrictionValid()) || !appInstall.accessRestrictionOption || appInstallForm.$invalid || busy"/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="collapse" id="collapseMediaLinksCarousel" data-toggle="false">
|
||||
<div ng-repeat="mediaLink in appInstall.mediaLinks" class="slick-item" style="background-image: url('{{mediaLink}}');" ng-show="appInstall.mediaLinks.length == 1"></div>
|
||||
<slick init-onload="true" current-index="0" autoplay="true" arrows="false" autoplay-speed="2000" data="appInstall.mediaLinks" ng-show="appInstall.mediaLinks.length > 1">
|
||||
<div ng-repeat="mediaLink in appInstall.mediaLinks" class="slick-item" style="background-image: url('{{mediaLink}}');"></div>
|
||||
</slick>
|
||||
<br/>
|
||||
<div class="appstore-install-description">
|
||||
<p ng-show="appInstall.app.manifest.upstreamVersion">{{ 'appstore.installDialog.titleAndVersion' | tr:{ title: appInstall.app.manifest.title, version: appInstall.app.manifest.upstreamVersion } }}</p>
|
||||
<div ng-bind-html="appInstall.app.manifest.description | markdown2html"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse" id="collapseResourceConstraint" data-toggle="false">
|
||||
<h4 class="text-danger">{{ 'appstore.installDialog.lowOnResources' | tr }}<sup><a ng-href="https://docs.cloudron.io/apps/#low-resource-warning" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></h4>
|
||||
<p>{{ 'appstore.installDialog.pleaseUpgradeServer' | tr }}</p>
|
||||
</div>
|
||||
<div class="collapse" id="collapseSubscriptionRequired" data-toggle="false">
|
||||
<p>{{ 'appstore.installDialog.subscriptionRequired' | tr }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
|
||||
<button type="button" class="btn btn-success" ng-click="openSubscriptionSetup()" ng-show="appInstall.state === 'subscriptionRequired'">{{ 'appstore.installDialog.setupSubscriptionAction' | tr }}</button>
|
||||
<button type="button" class="btn btn-danger" ng-show="appInstall.state === 'resourceConstraint'" ng-click="appInstall.showForm(true)">{{ 'appstore.installDialog.installAnywayAction' | tr }}</button>
|
||||
<button type="button" class="btn btn-success" ng-show="appInstall.state === 'appInfo'" ng-click="appInstall.showForm()">{{ 'appstore.installDialog.installAction' | tr }}</button>
|
||||
<button type="button" class="btn btn-success" ng-show="appInstall.state === 'installForm'" ng-click="appInstall.submit()" ng-disabled="(appInstall.accessRestrictionOption === 'groups' && !appInstall.isAccessRestrictionValid()) || !appInstall.accessRestrictionOption || appInstallForm.$invalid || appInstall.busy"><i class="fa fa-circle-notch fa-spin" ng-show="appInstall.busy"></i> {{ 'appstore.installDialog.doInstallAction' | tr:{ dnsOverwrite: appInstall.needsOverwrite } }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal app not found -->
|
||||
<div class="modal fade" id="appNotFoundModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'appstore.appNotFoundDialog.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body" ng-bind-html="'appstore.appNotFoundDialog.description' | tr:{ appId: appNotFound.appId, version: appNotFound.version }"></div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal applinks add -->
|
||||
<div class="modal fade" id="applinksAddModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'app.addApplinkDialog.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="applinksAddForm" role="form" ng-submit="applinksAdd.submit()" autocomplete="off">
|
||||
<div class="form-group" ng-class="{ 'has-error': (applinksAddForm.upstreamUri.$dirty && applinksAddForm.upstreamUri.$invalid) || (!applinksAddForm.upstreamUri.$dirty && applinksAdd.error.upstreamUri) }">
|
||||
<label class="control-label">{{ 'app.applinks.upstreamUri' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="applinksAdd.upstreamUri" name="upstreamUri" id="inputUpstreamUri" autofocus autocomplete="off" required>
|
||||
<span class="text-danger" ng-show="applinksAdd.error.upstreamUri">{{ applinksAdd.error.upstreamUri }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">{{ 'app.applinks.label' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="applinksAdd.label" name="label" id="inputLabel" autocomplete="off" placeholder="Leave empty for autodetection">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">{{ 'app.display.tags' | tr }}</label>
|
||||
<tag-input class="form-control" placeholder="{{ 'app.display.tagsPlaceholder' | tr }}" taglist="applinksAdd.tags" name="tags" uib-tooltip="{{ 'app.display.tagsTooltip' | tr }}"></tag-input>
|
||||
</div>
|
||||
|
||||
<label class="control-label">{{ 'app.accessControl.userManagement.dashboardVisibility' | tr }} <sup><a ng-href="https://docs.cloudron.io/apps/#dashboard-visibility" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
||||
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" ng-model="applinksAdd.accessRestrictionOption" value="any">
|
||||
<span>{{ 'app.accessControl.userManagement.visibleForAllUsers' | tr }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" ng-model="applinksAdd.accessRestrictionOption" value="groups">
|
||||
<span>{{ 'app.accessControl.userManagement.visibleForSelected' | tr }}</span>
|
||||
<span class="label label-danger" ng-show="applinksAdd.accessRestrictionOption === 'groups' && !applinksAdd.isAccessRestrictionValid()">{{ 'appstore.installDialog.errorUserManagementSelectAtLeastOne' | tr }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<div style="margin-left: 20px; display: flex;">
|
||||
<div>
|
||||
{{ 'appstore.installDialog.users' | tr }}: <multiselect name="accessUsersSelect" class="input-sm stretch" ng-model="applinksAdd.accessRestriction.users" ng-disabled="applinksAdd.accessRestrictionOption !== 'groups'" options="(user.username || user.email) for user in users" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{ 'appstore.installDialog.groups' | tr }}: <multiselect name="accessGroupsSelect" class="input-sm stretch" ng-model="applinksAdd.accessRestriction.groups" ng-disabled="applinksAdd.accessRestrictionOption !== 'groups'" options="group.name for group in groups" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input class="ng-hide" type="submit" ng-disabled="applinksAddForm.$invalid || applinksAdd.busy"/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
|
||||
<button type="button" class="btn btn-success" ng-click="applinksAdd.submit()" ng-disabled="applinksAddForm.$invalid || applinksAdd.busy"><i class="fa fa-circle-notch fa-spin" ng-show="applinksAdd.busy"></i> {{ 'main.dialog.save' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="!ready" class="loading-banner">
|
||||
<h1><i class="fa fa-circle-notch fa-spin"></i></h1>
|
||||
</div>
|
||||
|
||||
<!-- appstore login -->
|
||||
<div ng-show="ready && !validSubscription" class="container card card-small appstore-login ng-cloak">
|
||||
<div class="col-md-12 text-center">
|
||||
<h1 ng-show="appstoreLogin.setupType === 'signup'">{{ 'appstore.accountDialog.titleSignUp' | tr }}</h1>
|
||||
<h1 ng-show="appstoreLogin.setupType === 'login'">{{ 'appstore.accountDialog.titleLogin' | tr }}</h1>
|
||||
<h1 ng-show="appstoreLogin.setupType === 'setupToken'">{{ 'appstore.accountDialog.titleToken' | tr }}</h1>
|
||||
</div>
|
||||
<div class="col-md-12 text-center">
|
||||
<p>{{ 'appstore.accountDialog.description' | tr }}</p>
|
||||
</div>
|
||||
<div class="col-md-12" style="margin-bottom: 10px;">
|
||||
<small class="text-danger" ng-show="appstoreLogin.error.generic">{{ appstoreLogin.error.generic }}</small>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<br/>
|
||||
|
||||
<div ng-show="appstoreLogin.setupType === 'signup'">
|
||||
<form name="appstoreSignupForm" role="form" novalidate ng-submit="appstoreLogin.submit()" autocomplete="off">
|
||||
<input type="password" style="display: none;">
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': (appstoreSignupForm.email.$dirty && appstoreSignupForm.email.$invalid) || appstoreLogin.error.generic }">
|
||||
<label class="control-label">{{ 'appstore.accountDialog.email' | tr }}</label>
|
||||
<input type="email" class="form-control" ng-model="appstoreLogin.email" id="inputAppstoreSignupEmail" name="email" required autofocus>
|
||||
<div class="control-label" ng-show="(!appstoreSignupForm.email.$dirty && appstoreLogin.error.email) || (appstoreSignupForm.email.$dirty && appstoreSignupForm.email.$invalid) || appstoreLogin.error.email">
|
||||
<small class="text-danger" ng-show="appstoreLogin.error.email">{{ appstoreLogin.error.email }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': (!appstoreSignupForm.password.$dirty && appstoreLogin.error.signupPassword) || (appstoreSignupForm.password.$dirty && appstoreSignupForm.password.$invalid) || appstoreLogin.error.generic }">
|
||||
<label class="control-label">{{ 'appstore.accountDialog.password' | tr }}</label>
|
||||
<input type="password" class="form-control" ng-model="appstoreLogin.password" id="inputAppstoreSignupPassword" name="password" required password-reveal>
|
||||
<div class="control-label" ng-show="(!appstoreSignupForm.password.$dirty && appstoreLogin.error.signupPassword) || (appstoreSignupForm.password.$dirty && appstoreSignupForm.password.$invalid)">
|
||||
<small ng-show="!appstoreSignupForm.password.$dirty && appstoreLogin.error.signupPassword">{{ 'appstore.accountDialog.errorWrongPassword' | tr }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="appstoreLogin.termsAccepted" ng-required="true"><span ng-bind-html="'appstore.accountDialog.licenseCheckbox' | tr:{ licenseLink: 'https://cloudron.io/legal/license.html' }"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<center>
|
||||
<button type="submit" class="btn btn-lg btn-success" ng-disabled="appstoreSignupForm.$invalid || appstoreLogin.busy">
|
||||
<i class="fa fa-circle-notch fa-spin" ng-show="appstoreLogin.busy"></i> {{ 'appstore.accountDialog.createAccountAction' | tr }}
|
||||
</button>
|
||||
</center>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div ng-show="appstoreLogin.setupType === 'login'">
|
||||
<form name="appstoreLoginForm" role="form" novalidate ng-submit="appstoreLogin.submit()" autocomplete="off">
|
||||
<input type="password" style="display: none;">
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': (appstoreLoginForm.email.$dirty && appstoreLoginForm.email.$invalid) || appstoreLogin.error.generic }">
|
||||
<label class="control-label">{{ 'appstore.accountDialog.email' | tr }}</label>
|
||||
<input type="email" class="form-control" ng-model="appstoreLogin.email" name="email" required autofocus>
|
||||
<div class="control-label" ng-show="(!appstoreLoginForm.email.$dirty && appstoreLogin.error.email) || (appstoreLoginForm.email.$dirty && appstoreLoginForm.email.$invalid) || appstoreLogin.error.email">
|
||||
<small class="text-danger" ng-show="appstoreLogin.error.email">{{ appstoreLogin.error.email }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': (!appstoreLoginForm.password.$dirty && appstoreLogin.error.loginPassword) || (appstoreLoginForm.password.$dirty && appstoreLoginForm.password.$invalid) || appstoreLogin.error.generic }">
|
||||
<label class="control-label">{{ 'appstore.accountDialog.password' | tr }}</label>
|
||||
<input type="password" class="form-control" ng-model="appstoreLogin.password" id="inputAppstoreLoginPassword" name="password" required password-reveal>
|
||||
<div class="control-label" ng-show="(!appstoreLoginForm.password.$dirty && appstoreLogin.error.loginPassword) || (appstoreLoginForm.password.$dirty && appstoreLoginForm.password.$invalid)">
|
||||
<small ng-show="!appstoreLoginForm.password.$dirty && appstoreLogin.error.loginPassword">{{ 'appstore.accountDialog.errorWrongPassword' | tr }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': appstoreLogin.error.totpToken }">
|
||||
<label class="control-label">{{ 'appstore.accountDialog.2faToken' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="appstoreLogin.totpToken" id="inputAppstoreLoginTotpToken" name="totpToken">
|
||||
<div class="control-label" ng-show="appstoreLogin.error.totpToken">
|
||||
<small ng-show="appstoreLogin.error.totpToken">{{ appstoreLogin.error.totpToken }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="appstoreLogin.termsAccepted" ng-required="true"><span ng-bind-html="'appstore.accountDialog.licenseCheckbox' | tr:{ licenseLink: 'https://cloudron.io/legal/license.html' }"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<center>
|
||||
<button type="submit" class="btn btn-lg btn-success" ng-disabled="appstoreLoginForm.$invalid || appstoreLogin.busy">
|
||||
<i class="fa fa-circle-notch fa-spin" ng-show="appstoreLogin.busy"></i> {{ 'appstore.accountDialog.loginAction' | tr }}
|
||||
</button>
|
||||
</center>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div ng-show="appstoreLogin.setupType === 'setupToken'">
|
||||
<form name="appstoreSetupTokenForm" role="form" novalidate ng-submit="appstoreLogin.submit()" autocomplete="off">
|
||||
<input type="password" style="display: none;">
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': appstoreLogin.error.setupToken }">
|
||||
<label class="control-label">{{ 'appstore.accountDialog.setupToken' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="appstoreLogin.setupToken" id="inputAppstoreSetupToken" name="setupToken" ng-required="true">
|
||||
<div class="control-label" ng-show="appstoreLogin.error.setupToken">
|
||||
<small ng-show="appstoreLogin.error.setupToken">{{ appstoreLogin.error.setupToken }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="appstoreLogin.termsAccepted" ng-required="true"><span ng-bind-html="'appstore.accountDialog.licenseCheckbox' | tr:{ licenseLink: 'https://cloudron.io/legal/license.html' }"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<center>
|
||||
<button type="submit" class="btn btn-lg btn-success" ng-disabled="appstoreSetupTokenForm.$invalid || appstoreLogin.busy">
|
||||
<i class="fa fa-circle-notch fa-spin" ng-show="appstoreLogin.busy"></i> {{ 'appstore.accountDialog.setupWithTokenAction' | tr }}
|
||||
</button>
|
||||
</center>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<center>
|
||||
<a href="" ng-click="appstoreLogin.setupType = 'signup'" ng-show="appstoreLogin.setupType === 'login'">{{ 'appstore.accountDialog.switchToSignUpAction' | tr }}</a>
|
||||
<a href="" ng-click="appstoreLogin.setupType = 'login'" ng-show="appstoreLogin.setupType === 'signup' || appstoreLogin.setupType === 'setupToken'">{{ 'appstore.accountDialog.switchToLoginAction' | tr }}</a>
|
||||
<span ng-show="appstoreLogin.setupType !== 'setupToken'"> or <a href="" ng-click="appstoreLogin.setupType = 'setupToken'">Use a setup token</a></span>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- give more vertical spacing so the login form does not appear clipped -->
|
||||
<div ng-show="ready && !validSubscription">
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div class="appstore-layout">
|
||||
|
||||
<div ng-show="ready && validSubscription" class="ng-cloak appstore-toolbar">
|
||||
<div class="dropdown">
|
||||
<button class="btn dropdown-toggle" type="button" data-toggle="dropdown" ng-class="{ 'btn-primary': '' !== category && 'recent' !== category && 'new' !== category }">
|
||||
{{ categoryButtonLabel(category) }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="" ng-click="showCategory('');"><i class="fas fa-home fa-fw"></i> {{ 'appstore.category.all' | tr }}</a></li>
|
||||
<li><a href="" ng-click="showCategory('new');"><i class="fas fa-rss fa-fw"></i> {{ 'appstore.category.newApps' | tr }}</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li ng-repeat="category in categories | orderBy:'label'"><a href="" ng-click="showCategory(category.id);"><i class="{{ category.icon }} fa-fw"></i> {{ category.label }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="dropdown">
|
||||
<button class="btn dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<i class="{{ userManagementFilterOption.icon }} fa-fw"></i>
|
||||
{{ 'appstore.ssofilter.label' | tr }}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li ng-repeat="option in userManagementFilterOptions" ng-class="{ 'active': userManagementFilterOption.id && userManagementFilterOption.id === option.id }"><a href="" ng-click="applyUserMangamentFilter(option);"><i class="{{ option.icon }} fa-fw"></i> {{ option.label }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<input type="text" id="appstoreSearch" class="form-control" style="width: auto; flex-grow: 1;" placeholder="{{ 'appstore.searchPlaceholder' | tr }}" ng-model="searchString" ng-change="search()" autofocus>
|
||||
<button type="button" class="btn btn-default" ng-click="openAppProxy()"><i class="fas fa-exchange-alt"></i> {{ 'apps.addAppproxyAction' | tr }}</a></a>
|
||||
<button type="button" class="btn btn-default" ng-click="applinksAdd.show()"><i class="fas fa-link"></i> {{ 'apps.addApplinkAction' | tr }}</button>
|
||||
</div>
|
||||
|
||||
<div ng-show="ready && validSubscription" class="ng-cloak appstore-grid">
|
||||
<div class="text-center" ng-hide="apps.length || popularApps.length">
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<h3 class="text-muted">{{ 'appstore.noAppsFound' | tr }}</h3>
|
||||
<br/>
|
||||
<a href="https://forum.cloudron.io/category/5/app-requests" target="_blank">{{ 'appstore.appMissing' | tr }}</a>
|
||||
</div>
|
||||
<div class="" ng-show="category === '' && popularApps.length">
|
||||
<div class="row-no-margin">
|
||||
<div class="col-sm-12">
|
||||
<h2>{{ 'appstore.category.popular' | tr }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-no-margin">
|
||||
<div class="col-sm-3 appstore-item" ng-repeat="app in popularApps | userManagementFilter:userManagementFilterOption">
|
||||
<div class="appstore-item-content highlight" ng-click="gotoApp(app)" ng-class="{ 'appstore-item-content-testing': app.releaseState === 'unstable' }">
|
||||
<span class="badge badge-danger appstore-item-badge-testing" ng-show="app.releaseState === 'unstable'">{{ 'appstore.unstable' | tr }}</span>
|
||||
<div class="appstore-item-content-icon col-same-height">
|
||||
<img ng-src="{{app.iconUrl}}" onerror="this.onerror=null;this.src='img/appicon_fallback.png'" class="app-icon"/>
|
||||
</div>
|
||||
<div class="col-same-height">
|
||||
<h4 class="appstore-item-content-title">{{ app.manifest.title }}</h4>
|
||||
<div class="appstore-item-content-tagline text-muted">{{ app.manifest.tagline }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="" ng-show="apps.length">
|
||||
<div class="row-no-margin" ng-show="!category && !searchString">
|
||||
<div class="col-sm-12">
|
||||
<h2>{{ 'appstore.category.all' | tr }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-no-margin">
|
||||
<div class="col-sm-3 appstore-item" ng-repeat="app in apps | userManagementFilter:userManagementFilterOption | orderBy:'-priority' ">
|
||||
<div class="appstore-item-content highlight" ng-click="gotoApp(app)" ng-class="{ 'appstore-item-content-testing': app.releaseState === 'unstable' }">
|
||||
<span class="badge badge-danger appstore-item-badge-testing" ng-show="app.releaseState === 'unstable'">{{ 'appstore.unstable' | tr }}</span>
|
||||
<div class="appstore-item-content-icon col-same-height">
|
||||
<img ng-src="{{app.iconUrl}}" onerror="this.onerror=null;this.src='img/appicon_fallback.png'" class="app-icon"/>
|
||||
</div>
|
||||
<div class="appstore-item-content-description col-same-height">
|
||||
<h4 class="appstore-item-content-title">{{ app.manifest.title }}</h4>
|
||||
<div class="appstore-item-content-tagline text-muted">{{ app.manifest.tagline }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1,787 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/* global angular */
|
||||
/* global $ */
|
||||
/* global async */
|
||||
/* global ERROR */
|
||||
/* global RSTATES */
|
||||
/* global moment */
|
||||
|
||||
angular.module('Application').controller('AppStoreController', ['$scope', '$translate', '$location', '$timeout', '$routeParams', 'Client', function ($scope, $translate, $location, $timeout, $routeParams, Client) {
|
||||
Client.onReady(function () { if (!Client.getUserInfo().isAtLeastAdmin) $location.path('/'); });
|
||||
|
||||
$scope.HOST_PORT_MIN = 1;
|
||||
$scope.HOST_PORT_MAX = 65535;
|
||||
|
||||
$scope.ready = false;
|
||||
$scope.apps = [];
|
||||
$scope.popularApps = [];
|
||||
$scope.config = Client.getConfig();
|
||||
$scope.user = Client.getUserInfo();
|
||||
$scope.users = [];
|
||||
$scope.groups = [];
|
||||
$scope.domains = [];
|
||||
$scope.category = '';
|
||||
$scope.cachedCategory = ''; // used to cache the selected category while searching
|
||||
$scope.searchString = '';
|
||||
$scope.validSubscription = false;
|
||||
$scope.subscription = {};
|
||||
$scope.memory = null; // { memory, swap }
|
||||
|
||||
$scope.showView = function (view) {
|
||||
$('#appInstallModal').off('hidden.bs.modal');
|
||||
|
||||
// wait for dialog to be fully closed to avoid modal behavior breakage when moving to a different view already
|
||||
$('.modal').on('hidden.bs.modal', function () {
|
||||
$scope.appInstall.reset();
|
||||
$('.modal').off('hidden.bs.modal');
|
||||
$location.path(view).search({});
|
||||
});
|
||||
|
||||
$('.modal').modal('hide');
|
||||
};
|
||||
|
||||
// If new categories added make sure the translation below exists
|
||||
$scope.categories = [
|
||||
{ id: 'analytics', icon: 'fa fa-chart-line', label: 'Analytics'},
|
||||
{ id: 'automation', icon: 'fa fa-robot', label: 'Automation'},
|
||||
{ id: 'blog', icon: 'fa fa-font', label: 'Blog'},
|
||||
{ id: 'chat', icon: 'fa fa-comments', label: 'Chat'},
|
||||
{ id: 'crm', icon: 'fab fa-connectdevelop', label: 'CRM'},
|
||||
{ id: 'document', icon: 'fa fa-file-word', label: 'Documents'},
|
||||
{ id: 'email', icon: 'fa fa-envelope', label: 'Email'},
|
||||
{ id: 'federated', icon: 'fa fa-project-diagram', label: 'Federated'},
|
||||
{ id: 'finance', icon: 'fa fa-hand-holding-usd', label: 'Finance'},
|
||||
{ id: 'forum', icon: 'fa fa-users', label: 'Forum'},
|
||||
{ id: 'fun', icon: 'fa fa-gamepad', label: 'Fun'},
|
||||
{ id: 'gallery', icon: 'fa fa-images', label: 'Gallery'},
|
||||
{ id: 'game', icon: 'fa fa-gamepad', label: 'Games'},
|
||||
{ id: 'git', icon: 'fa fa-code-branch', label: 'Code Hosting'},
|
||||
{ id: 'hosting', icon: 'fa fa-server', label: 'Web Hosting'},
|
||||
{ id: 'learning', icon: 'fas fa-graduation-cap', label: 'Learning'},
|
||||
{ id: 'media', icon: 'fas fa-photo-video', label: 'Media'},
|
||||
{ id: 'no-code', icon: 'fas fa-code', label: 'No-code'},
|
||||
{ id: 'notes', icon: 'fa fa-sticky-note', label: 'Notes'},
|
||||
{ id: 'project', icon: 'fas fa-project-diagram', label: 'Project Management'},
|
||||
{ id: 'sync', icon: 'fa fa-sync-alt', label: 'File Sync'},
|
||||
{ id: 'voip', icon: 'fa fa-headset', label: 'VoIP'},
|
||||
{ id: 'vpn', icon: 'fa fa-user-secret', label: 'VPN'},
|
||||
{ id: 'wiki', icon: 'fab fa-wikipedia-w', label: 'Wiki'},
|
||||
];
|
||||
|
||||
// Translation IDs are generated as "appstore.category.<categoryId>"
|
||||
$translate($scope.categories.map(function (c) { return 'appstore.category.' + c.id; })).then(function (tr) {
|
||||
Object.keys(tr).forEach(function (key) {
|
||||
if (key === tr[key]) return; // missing translation use default label
|
||||
|
||||
var category = $scope.categories.find(function (c) { return key.endsWith(c.id); });
|
||||
if (category) category.label = tr[key];
|
||||
});
|
||||
});
|
||||
|
||||
$scope.categoryButtonLabel = function (category) {
|
||||
var categoryLabel = $translate.instant('appstore.categoryLabel');
|
||||
|
||||
if (category === '') return $translate.instant('appstore.category.all');
|
||||
if (category === 'new') return $translate.instant('appstore.category.newApps');
|
||||
|
||||
var tmp = $scope.categories.find(function (c) { return c.id === category; });
|
||||
if (tmp) return tmp.label;
|
||||
|
||||
return categoryLabel;
|
||||
};
|
||||
|
||||
$scope.isProxyApp = function (app) {
|
||||
if (!app) return false;
|
||||
|
||||
return app.id === 'io.cloudron.builtin.appproxy';
|
||||
};
|
||||
|
||||
$scope.userManagementFilterOptions = [
|
||||
{ id: '', icon: '', label: $translate.instant('appstore.ssofilter.all') },
|
||||
{ id: 'sso', icon: 'fas fa-user', label: $translate.instant('apps.auth.sso') },
|
||||
{ id: 'nosso', icon: 'far fa-user', label: $translate.instant('apps.auth.nosso') },
|
||||
{ id: 'email', icon: 'fas fa-envelope', label: $translate.instant('apps.auth.email') },
|
||||
];
|
||||
$scope.userManagementFilterOption = $scope.userManagementFilterOptions[0];
|
||||
|
||||
$scope.userManagementFilterOptionIsActive = function (option) {
|
||||
return option.id === $scope.userManagementFilterOption.id;
|
||||
};
|
||||
|
||||
$scope.applyUserMangamentFilter = function (option) {
|
||||
$scope.userManagementFilterOption = option;
|
||||
};
|
||||
|
||||
$scope.appInstall = {
|
||||
busy: false,
|
||||
state: 'appInfo',
|
||||
error: {},
|
||||
app: {},
|
||||
needsOverwrite: false,
|
||||
subdomain: '',
|
||||
domain: null, // object and not the string
|
||||
secondaryDomains: {},
|
||||
ports: {},
|
||||
portsEnabled: {},
|
||||
mediaLinks: [],
|
||||
keyFile: null,
|
||||
keyFileName: '',
|
||||
accessRestrictionOption: '',
|
||||
accessRestriction: { users: [], groups: [] },
|
||||
customAuth: false,
|
||||
optionalSso: false,
|
||||
subscriptionErrorMesssage: '',
|
||||
upstreamUri: '',
|
||||
|
||||
isAccessRestrictionValid: function () {
|
||||
var tmp = $scope.appInstall.accessRestriction;
|
||||
return !!(tmp.users.length || tmp.groups.length);
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
$scope.appInstall.app = {};
|
||||
$scope.appInstall.error = {};
|
||||
$scope.appInstall.needsOverwrite = false;
|
||||
$scope.appInstall.subdomain = '';
|
||||
$scope.appInstall.domain = null;
|
||||
$scope.appInstall.secondaryDomains = {};
|
||||
$scope.appInstall.ports = {};
|
||||
$scope.appInstall.state = 'appInfo';
|
||||
$scope.appInstall.mediaLinks = [];
|
||||
$scope.appInstall.keyFile = null;
|
||||
$scope.appInstall.keyFileName = '';
|
||||
$scope.appInstall.accessRestrictionOption = '';
|
||||
$scope.appInstall.accessRestriction = { users: [], groups: [] };
|
||||
$scope.appInstall.optionalSso = false;
|
||||
$scope.appInstall.customAuth = false;
|
||||
$scope.appInstall.subscriptionErrorMesssage = '';
|
||||
$scope.appInstall.upstreamUri = '';
|
||||
|
||||
$('#collapseInstallForm').collapse('hide');
|
||||
$('#collapseResourceConstraint').collapse('hide');
|
||||
$('#collapseSubscriptionRequired').collapse('hide');
|
||||
$('#collapseMediaLinksCarousel').collapse('show');
|
||||
|
||||
if ($scope.appInstallForm) {
|
||||
$scope.appInstallForm.$setPristine();
|
||||
$scope.appInstallForm.$setUntouched();
|
||||
}
|
||||
},
|
||||
|
||||
showForm: function (force) {
|
||||
var app = $scope.appInstall.app;
|
||||
var DEFAULT_MEMORY_LIMIT = 1024 * 1024 * 256;
|
||||
|
||||
var needed = app.manifest.memoryLimit || DEFAULT_MEMORY_LIMIT; // RAM
|
||||
var used = Client.getInstalledApps().reduce(function (prev, cur) {
|
||||
if (cur.runState === RSTATES.STOPPED) return prev;
|
||||
|
||||
return prev + (cur.memoryLimit || cur.manifest.memoryLimit || DEFAULT_MEMORY_LIMIT);
|
||||
}, 0);
|
||||
var totalMemory = $scope.memory.memory * 2;
|
||||
var available = (totalMemory || 0) - used;
|
||||
|
||||
var enoughResourcesAvailable = (available - needed) >= 0;
|
||||
|
||||
if (enoughResourcesAvailable || force) {
|
||||
$scope.appInstall.state = 'installForm';
|
||||
$('#collapseMediaLinksCarousel').collapse('hide');
|
||||
$('#collapseResourceConstraint').collapse('hide');
|
||||
$('#collapseInstallForm').collapse('show');
|
||||
$('#appInstallLocationInput').focus();
|
||||
} else {
|
||||
$scope.appInstall.state = 'resourceConstraint';
|
||||
$('#collapseMediaLinksCarousel').collapse('hide');
|
||||
$('#collapseResourceConstraint').collapse('show');
|
||||
}
|
||||
},
|
||||
|
||||
show: function (app) { // this is an appstore app object!
|
||||
$scope.appInstall.reset();
|
||||
|
||||
// make a copy to work with in case the app object gets updated while polling
|
||||
angular.copy(app, $scope.appInstall.app);
|
||||
|
||||
$scope.appInstall.mediaLinks = $scope.appInstall.app.manifest.mediaLinks || [];
|
||||
$scope.appInstall.domain = $scope.domains.find(function (d) { return $scope.config.adminDomain === d.domain; }); // pre-select the adminDomain
|
||||
|
||||
$scope.appInstall.secondaryDomains = {};
|
||||
var httpPorts = $scope.appInstall.app.manifest.httpPorts || {};
|
||||
for (var env2 in httpPorts) {
|
||||
$scope.appInstall.secondaryDomains[env2] = {
|
||||
subdomain: httpPorts[env2].defaultValue || '',
|
||||
domain: $scope.appInstall.domain
|
||||
};
|
||||
}
|
||||
|
||||
$scope.appInstall.portInfo = angular.extend({}, $scope.appInstall.app.manifest.tcpPorts, $scope.appInstall.app.manifest.udpPorts); // Portbinding map only for information
|
||||
$scope.appInstall.ports = {}; // This holds the env:port pair
|
||||
$scope.appInstall.portsEnabled = {}; // This holds the enabled/disabled flag
|
||||
|
||||
var manifest = app.manifest;
|
||||
$scope.appInstall.optionalSso = !!manifest.optionalSso;
|
||||
$scope.appInstall.customAuth = !(manifest.addons['ldap'] || manifest.addons['oidc'] || manifest.addons['proxyAuth']);
|
||||
|
||||
$scope.appInstall.accessRestrictionOption = $scope.groups.length ? '' : 'any'; // make the user select an ACL conciously if groups are used
|
||||
$scope.appInstall.accessRestriction = { users: [], groups: [] };
|
||||
|
||||
// set default ports
|
||||
var allPorts = angular.extend({}, $scope.appInstall.app.manifest.tcpPorts, $scope.appInstall.app.manifest.udpPorts);
|
||||
for (var env in allPorts) {
|
||||
$scope.appInstall.ports[env] = allPorts[env].defaultValue || 0;
|
||||
$scope.appInstall.portsEnabled[env] = true;
|
||||
}
|
||||
|
||||
$('#appInstallModal').modal('show');
|
||||
},
|
||||
|
||||
submit: function () {
|
||||
$scope.appInstall.busy = true;
|
||||
$scope.appInstall.error.other = null;
|
||||
$scope.appInstall.error.location = null;
|
||||
$scope.appInstall.error.port = null;
|
||||
|
||||
var secondaryDomains = {};
|
||||
for (var env2 in $scope.appInstall.secondaryDomains) {
|
||||
secondaryDomains[env2] = {
|
||||
subdomain: $scope.appInstall.secondaryDomains[env2].subdomain,
|
||||
domain: $scope.appInstall.secondaryDomains[env2].domain.domain
|
||||
};
|
||||
}
|
||||
|
||||
// only use enabled ports from ports
|
||||
var finalPorts = {};
|
||||
for (var env in $scope.appInstall.ports) {
|
||||
if ($scope.appInstall.portsEnabled[env]) {
|
||||
finalPorts[env] = $scope.appInstall.ports[env];
|
||||
}
|
||||
}
|
||||
|
||||
var finalAccessRestriction = null;
|
||||
if ($scope.appInstall.accessRestrictionOption === 'groups') {
|
||||
finalAccessRestriction = { users: [], groups: [] };
|
||||
finalAccessRestriction.users = $scope.appInstall.accessRestriction.users.map(function (u) { return u.id; });
|
||||
finalAccessRestriction.groups = $scope.appInstall.accessRestriction.groups.map(function (g) { return g.id; });
|
||||
}
|
||||
|
||||
var data = {
|
||||
overwriteDns: $scope.appInstall.needsOverwrite,
|
||||
subdomain: $scope.appInstall.subdomain || '',
|
||||
domain: $scope.appInstall.domain.domain,
|
||||
secondaryDomains: secondaryDomains,
|
||||
ports: finalPorts,
|
||||
accessRestriction: finalAccessRestriction,
|
||||
sso: !$scope.appInstall.optionalSso ? undefined : ($scope.appInstall.accessRestrictionOption !== 'nosso'),
|
||||
};
|
||||
|
||||
if ($scope.appInstall.upstreamUri) {
|
||||
data.upstreamUri = $scope.appInstall.upstreamUri;
|
||||
data.upstreamUri = data.upstreamUri.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
var domains = [];
|
||||
domains.push({ subdomain: data.subdomain, domain: data.domain, type: 'primary' });
|
||||
var canInstall = true;
|
||||
|
||||
async.eachSeries(domains, function (domain, callback) {
|
||||
if (data.overwriteDns) return callback();
|
||||
|
||||
Client.checkDNSRecords(domain.domain, domain.subdomain, function (error, result) {
|
||||
if (error) return callback(error);
|
||||
|
||||
var message;
|
||||
if (result.error) {
|
||||
if (result.error.reason === ERROR.ACCESS_DENIED) {
|
||||
message = 'DNS credentials for ' + domain.domain + ' are invalid. Update it in Domains & Certs view';
|
||||
if (domain.type === 'primary') {
|
||||
$scope.appInstall.error.location = message;
|
||||
} else {
|
||||
$scope.appInstall.error.secondaryDomain = message;
|
||||
}
|
||||
} else {
|
||||
if (domain.type === 'primary') {
|
||||
$scope.appInstall.error.location = result.error.message;
|
||||
} else {
|
||||
$scope.appInstall.error.secondaryDomain = message;
|
||||
}
|
||||
}
|
||||
canInstall = false;
|
||||
} else if (result.needsOverwrite) {
|
||||
message = 'DNS Record already exists. Confirm that the domain is not in use for services external to Cloudron';
|
||||
if (data.type === 'primary') {
|
||||
$scope.appInstall.error.location = message;
|
||||
} else {
|
||||
$scope.appInstall.error.secondaryDomain = message;
|
||||
}
|
||||
$scope.appInstall.needsOverwrite = true;
|
||||
canInstall = false;
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}, function (error) {
|
||||
if (error) {
|
||||
$scope.appInstall.busy = false;
|
||||
return Client.error(error);
|
||||
}
|
||||
|
||||
if (!canInstall) {
|
||||
$scope.appInstall.busy = false;
|
||||
$scope.appInstallForm.location.$setPristine();
|
||||
$('#appInstallLocationInput').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
Client.installApp($scope.appInstall.app.id, $scope.appInstall.app.manifest, data, function (error, newAppId) {
|
||||
if (error) {
|
||||
var errorMessage = error.message.toLowerCase();
|
||||
|
||||
if (error.statusCode === 402) {
|
||||
$scope.appInstall.state = 'subscriptionRequired';
|
||||
$scope.appInstall.subscriptionErrorMesssage = error.message;
|
||||
$('#collapseMediaLinksCarousel').collapse('hide');
|
||||
$('#collapseResourceConstraint').collapse('hide');
|
||||
$('#collapseInstallForm').collapse('hide');
|
||||
$('#collapseSubscriptionRequired').collapse('show');
|
||||
} else if (error.statusCode === 409) {
|
||||
if (errorMessage.indexOf('port') !== -1) {
|
||||
$scope.appInstall.error.port = error.message;
|
||||
} else if (errorMessage.indexOf('location') !== -1) {
|
||||
if (errorMessage.indexOf('primary') !== -1) {
|
||||
$scope.appInstall.error.location = error.message;
|
||||
$scope.appInstallForm.location.$setPristine();
|
||||
$('#appInstallLocationInput').focus();
|
||||
} else {
|
||||
$scope.appInstall.error.secondaryDomain = error.message;
|
||||
}
|
||||
} else {
|
||||
$scope.appInstall.error.other = error.message;
|
||||
}
|
||||
} else if (error.statusCode === 400) {
|
||||
$scope.appInstall.error.other = error.message;
|
||||
} else {
|
||||
$scope.appInstall.error.other = error.message;
|
||||
}
|
||||
|
||||
$scope.appInstall.busy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.appInstall.busy = false;
|
||||
|
||||
// stash new app id for later
|
||||
$scope.appInstall.app.id = newAppId;
|
||||
|
||||
// we track the postinstall confirmation for the current user's browser
|
||||
// TODO later we might want to have a notification db to track the state across admins and browsers
|
||||
if ($scope.appInstall.app.manifest.postInstallMessage) {
|
||||
localStorage['confirmPostInstall_' + $scope.appInstall.app.id] = true;
|
||||
}
|
||||
|
||||
$scope.showView('/apps');
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.appNotFound = {
|
||||
appId: '',
|
||||
version: ''
|
||||
};
|
||||
|
||||
$scope.appstoreLogin = {
|
||||
busy: false,
|
||||
error: {},
|
||||
email: '',
|
||||
password: '',
|
||||
totpToken: '',
|
||||
setupType: 'login',
|
||||
termsAccepted: false,
|
||||
setupToken: '',
|
||||
|
||||
submit: function () {
|
||||
$scope.appstoreLogin.error = {};
|
||||
$scope.appstoreLogin.busy = true;
|
||||
|
||||
var func = $scope.appstoreLogin.setupToken ? Client.registerCloudronWithSetupToken.bind(null, $scope.appstoreLogin.setupToken) : Client.registerCloudron.bind(null, $scope.appstoreLogin.email, $scope.appstoreLogin.password, $scope.appstoreLogin.totpToken, $scope.appstoreLogin.setupType === 'register');
|
||||
func(function (error) {
|
||||
if (error) {
|
||||
$scope.appstoreLogin.busy = false;
|
||||
|
||||
if (error.statusCode === 409) {
|
||||
$scope.appstoreLogin.error.email = 'An account with this email already exists';
|
||||
$scope.appstoreLogin.password = '';
|
||||
$scope.appstoreSignupForm.email.$setPristine();
|
||||
$scope.appstoreSignupForm.password.$setPristine();
|
||||
$('#inputAppstoreLoginEmail').focus();
|
||||
} else if (error.statusCode === 412) {
|
||||
if (error.message.indexOf('TOTP token missing') !== -1) {
|
||||
$scope.appstoreLogin.error.totpToken = 'A 2FA token is required';
|
||||
setTimeout(function () { $('#inputAppstoreLoginTotpToken').focus(); }, 0);
|
||||
} else if (error.message.indexOf('TOTP token invalid') !== -1) {
|
||||
$scope.appstoreLogin.error.totpToken = 'Wrong 2FA token';
|
||||
$scope.appstoreLogin.totpToken = '';
|
||||
setTimeout(function () { $('#inputAppstoreLoginTotpToken').focus(); }, 0);
|
||||
} else {
|
||||
$scope.appstoreLogin.error.loginPassword = 'Wrong email or password';
|
||||
$scope.appstoreLogin.password = '';
|
||||
$('#inputAppstoreLoginPassword').focus();
|
||||
$scope.appstoreLoginForm.password.$setPristine();
|
||||
}
|
||||
} else if (error.statusCode === 424) {
|
||||
if (error.message === 'wrong user') {
|
||||
$scope.appstoreLogin.error.generic = 'Wrong cloudron.io account';
|
||||
$scope.appstoreLogin.email = '';
|
||||
$scope.appstoreLogin.password = '';
|
||||
$scope.appstoreLoginForm.email.$setPristine();
|
||||
$scope.appstoreLoginForm.password.$setPristine();
|
||||
$scope.appstoreSignupForm.email.$setPristine();
|
||||
$scope.appstoreSignupForm.password.$setPristine();
|
||||
$('#inputAppstoreLoginEmail').focus();
|
||||
} else {
|
||||
console.error(error);
|
||||
$scope.appstoreLogin.error.generic = error.message;
|
||||
}
|
||||
} else if (error.statusCode === 402) {
|
||||
$scope.appstoreLogin.error.setupToken = 'Invalid or expired setup token';
|
||||
$scope.appstoreLogin.setupToken = '';
|
||||
$scope.appstoreSetupTokenForm.setupToken.$setPristine();
|
||||
$('#inputAppstoreSetupToken').focus();
|
||||
} else {
|
||||
console.error(error);
|
||||
$scope.appstoreLogin.error.generic = error.message || 'Please retry later';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// do a full re-init of the view now that we have a subscription
|
||||
init();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// TODO does not support testing apps in search
|
||||
$scope.search = function () {
|
||||
if (!$scope.searchString) return $scope.showCategory($scope.cachedCategory);
|
||||
|
||||
$scope.category = '';
|
||||
|
||||
Client.getAppstoreAppsFast(function (error, apps) {
|
||||
if (error) return $timeout($scope.search, 1000);
|
||||
|
||||
var token = $scope.searchString.toUpperCase();
|
||||
|
||||
$scope.popularApps = [];
|
||||
$scope.apps = apps.filter(function (app) {
|
||||
// on searches we give highe priority if title or tagline matches
|
||||
app.priority = 0;
|
||||
|
||||
if (app.manifest.title.toUpperCase().indexOf(token) !== -1) {
|
||||
app.priority = 2;
|
||||
return true;
|
||||
}
|
||||
if (app.manifest.tagline.toUpperCase().indexOf(token) !== -1) {
|
||||
app.priority = 1;
|
||||
return true;
|
||||
}
|
||||
if (app.manifest.id.toUpperCase().indexOf(token) !== -1) return true;
|
||||
if (app.manifest.description.toUpperCase().indexOf(token) !== -1) return true;
|
||||
if (app.manifest.tags.join().toUpperCase().indexOf(token) !== -1) return true;
|
||||
return false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function filterForNewApps(apps) {
|
||||
var minApps = apps.length < 12 ? apps.length : 12; // prevent endless loop
|
||||
var tmp = [];
|
||||
var i = 0;
|
||||
|
||||
do {
|
||||
var offset = moment().subtract(i++, 'days');
|
||||
tmp = apps.filter(function (app) { return moment(app.publishedAt).isAfter(offset); });
|
||||
} while(tmp.length < minApps);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function filterForRecentlyUpdatedApps(apps) {
|
||||
var minApps = apps.length < 12 ? apps.length : 12; // prevent endless loop
|
||||
var tmp = [];
|
||||
var i = 0;
|
||||
|
||||
do {
|
||||
var offset = moment().subtract(i++, 'days');
|
||||
tmp = apps.filter(function (app) { return moment(app.creationDate).isAfter(offset); }); // creationDate here is from appstore's appversions table
|
||||
} while(tmp.length < minApps);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
$scope.showCategory = function (category) {
|
||||
$scope.category = category;
|
||||
|
||||
$scope.cachedCategory = $scope.category;
|
||||
|
||||
Client.getAppstoreAppsFast(function (error, apps) {
|
||||
if (error) return $timeout($scope.showCategory.bind(null, category), 1000);
|
||||
|
||||
if (!$scope.category) {
|
||||
$scope.apps = apps.slice(0).filter(function (app) { return !app.featured; }).sort(function (a1, a2) { return a1.manifest.title.localeCompare(a2.manifest.title); });
|
||||
$scope.popularApps = apps.slice(0).filter(function (app) { return app.featured; }).sort(function (a1, a2) { return a2.ranking - a1.ranking; });
|
||||
} else if ($scope.category === 'new') {
|
||||
$scope.apps = filterForNewApps(apps);
|
||||
} else if ($scope.category === 'recent') {
|
||||
$scope.apps = filterForRecentlyUpdatedApps(apps);
|
||||
} else {
|
||||
$scope.apps = apps.filter(function (app) {
|
||||
return app.manifest.tags.some(function (tag) { return $scope.category.toUpperCase() === tag.toUpperCase(); }); // reverse sort;
|
||||
}).sort(function (a1, a2) { return a2.ranking - a1.ranking; });
|
||||
}
|
||||
|
||||
// ensure we scroll to top
|
||||
document.getElementById('ng-view').scrollTop = 0;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.openSubscriptionSetup = function () {
|
||||
Client.getSubscription(function (error, subscription) {
|
||||
if (error) return console.error('Unable to get subscription.', error);
|
||||
|
||||
Client.openSubscriptionSetup(subscription);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.showAppNotFound = function (appId, version) {
|
||||
$scope.appNotFound.appId = appId;
|
||||
$scope.appNotFound.version = version || 'latest';
|
||||
|
||||
$('#appNotFoundModal').modal('show');
|
||||
};
|
||||
|
||||
$scope.gotoApp = function (app) {
|
||||
$location.path('/appstore/' + app.manifest.id, false).search({ version : app.manifest.version });
|
||||
};
|
||||
|
||||
$scope.openAppProxy = function () {
|
||||
$location.path('/appstore/io.cloudron.builtin.appproxy', false).search({});
|
||||
};
|
||||
|
||||
$scope.applinksAdd = {
|
||||
error: {},
|
||||
busy: false,
|
||||
upstreamUri: '',
|
||||
label: '',
|
||||
tags: '',
|
||||
accessRestrictionOption: 'any',
|
||||
accessRestriction: { users: [], groups: [] },
|
||||
|
||||
isAccessRestrictionValid: function () {
|
||||
return !!($scope.applinksAdd.accessRestriction.users.length || $scope.applinksAdd.accessRestriction.groups.length);
|
||||
},
|
||||
|
||||
show: function () {
|
||||
$scope.applinksAdd.error = {};
|
||||
$scope.applinksAdd.busy = false;
|
||||
$scope.applinksAdd.upstreamUri = '';
|
||||
$scope.applinksAdd.label = '';
|
||||
$scope.applinksAdd.tags = '';
|
||||
|
||||
$scope.applinksAddForm.$setUntouched();
|
||||
$scope.applinksAddForm.$setPristine();
|
||||
|
||||
$('#applinksAddModal').modal('show');
|
||||
|
||||
return false; // prevent propagation and default
|
||||
},
|
||||
|
||||
submit: function () {
|
||||
if (!$scope.applinksAdd.upstreamUri) return;
|
||||
|
||||
$scope.applinksAdd.busy = true;
|
||||
$scope.applinksAdd.error = {};
|
||||
|
||||
var accessRestriction = null;
|
||||
if ($scope.applinksAdd.accessRestrictionOption === 'groups') {
|
||||
accessRestriction = { users: [], groups: [] };
|
||||
accessRestriction.users = $scope.applinksAdd.accessRestriction.users.map(function (u) { return u.id; });
|
||||
accessRestriction.groups = $scope.applinksAdd.accessRestriction.groups.map(function (g) { return g.id; });
|
||||
}
|
||||
|
||||
var data = {
|
||||
upstreamUri: $scope.applinksAdd.upstreamUri,
|
||||
label: $scope.applinksAdd.label,
|
||||
accessRestriction: accessRestriction,
|
||||
tags: $scope.applinksAdd.tags.split(' ').map(function (t) { return t.trim(); }).filter(function (t) { return !!t; })
|
||||
};
|
||||
|
||||
Client.addApplink(data, function (error) {
|
||||
$scope.applinksAdd.busy = false;
|
||||
|
||||
if (error && error.statusCode === 400 && error.message.includes('upstreamUri')) {
|
||||
$scope.applinksAdd.error.upstreamUri = error.message;
|
||||
$scope.applinksAddForm.$setUntouched();
|
||||
$scope.applinksAddForm.$setPristine();
|
||||
return;
|
||||
}
|
||||
if (error) return console.error('Failed to add applink', error);
|
||||
|
||||
$scope.showView('/apps');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function hashChangeListener() {
|
||||
// event listener is called from DOM not angular, need to use $apply
|
||||
$scope.$apply(function () {
|
||||
var appId = $location.path().slice('/appstore/'.length);
|
||||
var version = $location.search().version;
|
||||
|
||||
if (appId) {
|
||||
Client.getAppstoreAppByIdAndVersion(appId, version || 'latest', function (error, result) {
|
||||
if (error) {
|
||||
$scope.showAppNotFound(appId, version);
|
||||
console.error(error);
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.appInstall.show(result);
|
||||
});
|
||||
} else {
|
||||
$scope.appInstall.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fetchUsers() {
|
||||
Client.getAllUsers(function (error, users) {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
return $timeout(fetchUsers, 5000);
|
||||
}
|
||||
|
||||
$scope.users = users;
|
||||
});
|
||||
}
|
||||
|
||||
function fetchGroups() {
|
||||
Client.getGroups(function (error, groups) {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
return $timeout(fetchGroups, 5000);
|
||||
}
|
||||
|
||||
$scope.groups = groups;
|
||||
});
|
||||
}
|
||||
|
||||
function fetchMemory() {
|
||||
Client.memory(function (error, memory) {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
return $timeout(fetchMemory, 5000);
|
||||
}
|
||||
|
||||
$scope.memory = memory;
|
||||
});
|
||||
}
|
||||
|
||||
function getSubscription(callback) {
|
||||
var validSubscription = false;
|
||||
|
||||
Client.getSubscription(function (error, subscription) {
|
||||
if (error) {
|
||||
if (error.statusCode === 412) { // not registered yet
|
||||
validSubscription = false;
|
||||
} else if (error.statusCode === 402) { // invalid token, license error
|
||||
validSubscription = false;
|
||||
} else { // 424/external error?
|
||||
return callback(error);
|
||||
}
|
||||
} else {
|
||||
validSubscription = true;
|
||||
$scope.subscription = subscription;
|
||||
}
|
||||
|
||||
// clear busy state when a login/signup was performed
|
||||
$scope.appstoreLogin.busy = false;
|
||||
|
||||
// also update the root controller status
|
||||
if ($scope.$parent) $scope.$parent.updateSubscriptionStatus();
|
||||
|
||||
callback(null, validSubscription);
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
Client.getAppstoreAppsFast(function (error) {
|
||||
if (error && error.statusCode === 402) {
|
||||
$scope.validSubscription = false;
|
||||
$scope.ready = true;
|
||||
return;
|
||||
} else if (error) {
|
||||
console.error('Failed to get apps. Will retry.', error);
|
||||
$timeout(init, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.showCategory('');
|
||||
|
||||
getSubscription(function (error, validSubscription) {
|
||||
if (error) console.error('Failed to get subscription.', error);
|
||||
|
||||
// autofocus login
|
||||
if (!validSubscription) setTimeout(function () { $('[name=appstoreLoginForm]').find('[autofocus]:first').focus(); }, 1000);
|
||||
|
||||
$scope.validSubscription = validSubscription;
|
||||
$scope.ready = true;
|
||||
|
||||
// refresh everything in background
|
||||
Client.getAppstoreApps(function (error) { if (error) console.error('Failed to fetch apps.', error); });
|
||||
Client.refreshConfig(); // refresh domain, user, group limit etc
|
||||
fetchUsers();
|
||||
fetchGroups();
|
||||
fetchMemory();
|
||||
|
||||
// domains is required since we populate the dropdown with domains[0]
|
||||
Client.getDomains(function (error, result) {
|
||||
if (error) return console.error('Error getting domains.', error);
|
||||
|
||||
$scope.domains = result;
|
||||
|
||||
// show install app dialog immediately if an app id was passed in the query
|
||||
// hashChangeListener calls $apply, so make sure we don't double digest here
|
||||
setTimeout(hashChangeListener, 1);
|
||||
|
||||
setTimeout(function () { $('#appstoreSearch').focus(); }, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Client.onReady(init);
|
||||
|
||||
$('#appInstallModal').on('hidden.bs.modal', function () {
|
||||
// clear the appid and version in the search bar when dialog is cancelled
|
||||
$scope.$apply(function () {
|
||||
$location.path('/appstore', false).search({ }); // 'false' means do not reload
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('hashchange', hashChangeListener);
|
||||
|
||||
$scope.$on('$destroy', function handler() {
|
||||
window.removeEventListener('hashchange', hashChangeListener);
|
||||
});
|
||||
|
||||
// setup all the dialog focus handling
|
||||
['appInstallModal'].forEach(function (id) {
|
||||
$('#' + id).on('shown.bs.modal', function () {
|
||||
$(this).find('[autofocus]:first').focus();
|
||||
});
|
||||
});
|
||||
|
||||
$('.modal-backdrop').remove();
|
||||
}]);
|
||||
@@ -1,816 +0,0 @@
|
||||
<!-- Modal details -->
|
||||
<div class="modal fade" id="backupDetailsModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" style="width: 750px">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'backups.backupDetails.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-xs-2 text-muted">{{ 'backups.backupDetails.id' | tr }}:</div>
|
||||
<div class="col-xs-10 text-right">{{ backupDetails.backup.id }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-2 text-muted">{{ 'backups.backupEdit.label' | tr }}:</div>
|
||||
<div class="col-xs-10 text-right">{{ backupDetails.backup.label }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-2 text-muted">{{ 'backups.backupEdit.remotePath' | tr }}:</div>
|
||||
<div class="col-xs-10 text-right">{{ backupDetails.backup.remotePath }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-2 text-muted">{{ 'backups.backupDetails.date' | tr }}:</div>
|
||||
<div class="col-xs-10 text-right">{{ backupDetails.backup.creationTime | prettyLongDate }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-2 text-muted">{{ 'backups.backupDetails.version' | tr }}:</div>
|
||||
<div class="col-xs-10 text-right">v{{ backupDetails.backup.packageVersion }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-2 text-muted">{{ 'backups.backupDetails.format' | tr }}:</div>
|
||||
<div class="col-xs-10 text-right">{{ backupDetails.backup.format }}</div>
|
||||
</div>
|
||||
<br/>
|
||||
<p class="text-muted">{{ 'backups.backupDetails.list' | tr:{ appCount: backupDetails.backup.contents.length } }}:</p>
|
||||
<span ng-repeat="content in backupDetails.backup.contents | orderBy:['label','fqdn']">
|
||||
<a ng-if="content.fqdn" ng-href="/#/app/{{content.id}}/backups">{{ content.label || content.fqdn }}</a>
|
||||
<a ng-if="!content.fqdn" ng-href="/#/eventlog?search={{content.id}}">{{ content.id }}</a>
|
||||
<span ng-hide="$last">,</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal edit individual backup (label and retention sec) -->
|
||||
<div class="modal fade" id="editBackupModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'backups.backupEdit.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="editBackupForm" role="form" novalidate ng-submit="editBackup.submit()" autocomplete="off">
|
||||
<p class="has-error text-center" ng-show="editBackup.error">{{ editBackup.error }}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="inputBackupLabel">{{ 'backups.backupEdit.label' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="editBackup.label" id="inputBackupLabel" name="label" ng-disabled="editBackup.busy" placeholder="" autofocus>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="editBackup.persist">{{ 'backups.backupEdit.preserved.description' | tr }}</input>
|
||||
|
||||
<sup><a popover-placement="top-right" popover-trigger="outsideClick" uib-popover="{{ 'backups.backupEdit.preserved.tooltip' | tr: { appsLength: editBackup.backup.contents.length} }}"><i class="fa fa-question-circle"></i></a></sup>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
||||
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="editBackup.submit()" ng-disabled="editBackupForm.$invalid || editBackup.busy"><i class="fa fa-circle-notch fa-spin" ng-show="editBackup.busy"></i><span> {{ 'main.dialog.save' | tr }}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal backup failed -->
|
||||
<div class="modal fade" id="createBackupFailedModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'backups.backupFailed.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ createBackup.errorMessage }}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Cleanup backups info -->
|
||||
<div class="modal fade" id="cleanupBackupsModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'backups.cleanupBackups.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">{{ 'backups.cleanupBackups.description' | tr }}</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
||||
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="cleanupBackups.start()">{{ 'backups.cleanupBackups.cleanupNow' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- modal backup schedule config -->
|
||||
<div class="modal fade" id="backupPolicyModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'backups.configureBackupSchedule.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="backupPolicyForm" role="form" novalidate ng-submit="backupPolicy.submit()" autocomplete="off">
|
||||
<p class="has-error text-center" ng-show="backupPolicy.error">{{ backupPolicy.error.generic }}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="backupSchedule">{{ 'backups.configureBackupSchedule.schedule' | tr }}</label>
|
||||
<p ng-bind-html="'backups.configureBackupSchedule.scheduleDescription' | tr"></p>
|
||||
|
||||
<div class="row" style="margin-left: 20px;">
|
||||
<div class="col-md-5" ng-class="{ 'has-error': !backupPolicy.days.length }">
|
||||
{{ 'backups.configureBackupSchedule.days' | tr }}: <multiselect id="backupSchedule" class="input-sm stretch" ng-model="backupPolicy.days" options="a.name for a in cronDays" data-multiple="true" ng-required></multiselect>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5" ng-class="{ 'has-error': !backupPolicy.hours.length }">
|
||||
{{ 'backups.configureBackupSchedule.hours' | tr }}: <multiselect class="input-sm stretch" ng-model="backupPolicy.hours" options="a.name for a in cronHours" data-multiple="true"></multiselect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="backupRetention">{{ 'backups.configureBackupSchedule.retentionPolicy' | tr }}</label>
|
||||
<select class="form-control" id="backupRetention" ng-model="backupPolicy.retention" ng-options="a.value as a.name for a in backupRetentions"></select>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer ">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
||||
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="backupPolicy.submit()" ng-disabled="!backupPolicy.valid() || backupPolicy.busy"><i class="fa fa-circle-notch fa-spin" ng-show="backupPolicy.busy"></i><span> {{ 'main.dialog.save' | tr }}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- modal backup config -->
|
||||
<div class="modal fade" id="configureBackupModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'backups.configureBackupStorage.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="configureBackupForm" role="form" novalidate ng-submit="configureBackup.submit()" autocomplete="off">
|
||||
<p class="has-error text-center" ng-show="configureBackup.error">{{ configureBackup.error.generic }}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="storageProviderProvider">{{ 'backups.configureBackupStorage.provider' | tr }} <sup><a ng-href="https://docs.cloudron.io/backups/#storage-providers" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
||||
<p class="small text-info" ng-show="backupConfig.provider !== configureBackup.provider">Backups in the old storage location have to be removed manually.</p>
|
||||
<select class="form-control" id="storageProviderProvider" ng-model="configureBackup.provider" ng-options="a.value as a.name for a in storageProviders" ng-change=configureBackup.clearProviderFields()></select>
|
||||
</div>
|
||||
|
||||
<!-- Noop -->
|
||||
<div class="form-group" ng-show="configureBackup.provider === 'noop'">
|
||||
<p class="has-error">{{ 'backups.configureBackupStorage.noopNote' | tr }}</p>
|
||||
</div>
|
||||
|
||||
<!-- mountpoint -->
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.mountPoint || (configureBackupForm.mountPoint.$dirty && !configureBackup.mountPoint) }" ng-show="configureBackup.provider === 'mountpoint'">
|
||||
<label class="control-label" for="inputConfigureMountPoint">{{ 'backups.configureBackupStorage.mountPoint' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.mountPoint" id="inputConfigureMountPoint" name="mountPoint" ng-disabled="configureBackup.busy" placeholder="/mnt/backups" ng-required="configureBackup.provider === 'mountpoint'">
|
||||
<p ng-show="configureBackup.provider === 'mountpoint'" ng-bind-html="'backups.configureBackupStorage.mountPointDescription' | tr:{ providerDocsLink: 'https://docs.cloudron.io/backups/#'+configureBackup.provider }"></p>
|
||||
</div>
|
||||
|
||||
<!-- CIFS/NFS/SSHFS -->
|
||||
<div class="form-group" ng-show="configureBackup.provider === 'cifs' || configureBackup.provider === 'nfs' || configureBackup.provider === 'sshfs'">
|
||||
<label class="control-label" for="configureBackupHost">{{ 'backups.configureBackupStorage.server' | tr }} ({{ configureBackup.provider }})</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.mountOptions.host" id="configureBackupHost" name="host" ng-disabled="configureBackup.busy" placeholder="Server IP or hostname" ng-required="configureBackup.provider === 'cifs' || configureBackup.provider === 'nfs' || configureBackup.provider === 'sshfs'">
|
||||
</div>
|
||||
|
||||
<!-- CIFS -->
|
||||
<div class="checkbox" ng-show="configureBackup.provider === 'cifs'">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="configureBackup.mountOptions.seal">{{ 'backups.configureBackupStorage.cifsSealSupport' | tr }}</input>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- CIFS/NFS/SSHFS -->
|
||||
<div class="form-group" ng-show="configureBackup.provider === 'cifs' || configureBackup.provider === 'nfs' || configureBackup.provider === 'sshfs'">
|
||||
<label class="control-label" for="configureBackupRemoteDir">{{ 'backups.configureBackupStorage.remoteDirectory' | tr }} ({{ configureBackup.provider }})</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.mountOptions.remoteDir" id="configureBackupRemoteDir" name="remoteDir" ng-disabled="configureBackup.busy" placeholder="/share" ng-required="configureBackup.provider === 'cifs' || configureBackup.provider === 'nfs' || configureBackup.provider === 'sshfs'">
|
||||
</div>
|
||||
|
||||
<!-- CIFS -->
|
||||
<div class="form-group" ng-show="configureBackup.provider === 'cifs'">
|
||||
<label class="control-label" for="configureBackupUsername">{{ 'backups.configureBackupStorage.username' | tr }} ({{ configureBackup.provider }})</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.mountOptions.username" id="configureBackupUsername" name="cifsUsername" ng-disabled="configureBackup.busy">
|
||||
</div>
|
||||
|
||||
<!-- CIFS -->
|
||||
<div class="form-group" ng-show="configureBackup.provider === 'cifs'">
|
||||
<label class="control-label" for="configureBackupPassword">{{ 'backups.configureBackupStorage.password' | tr }} ({{ configureBackup.provider }})</label>
|
||||
<input type="password" class="form-control" ng-model="configureBackup.mountOptions.password" id="configureBackupPassword" name="cifsPassword" ng-disabled="configureBackup.busy" password-reveal>
|
||||
</div>
|
||||
|
||||
<!-- EXT4/XFS -->
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.diskPath || !configureBackup.mountOptions.diskPath }" ng-show="configureBackup.provider === 'xfs' || configureBackup.provider === 'ext4'">
|
||||
<label class="control-label" for="inputConfigureDiskPath">{{ 'backups.configureBackupStorage.diskPath' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.mountOptions.diskPath" id="inputConfigureDiskPath" name="diskPath" ng-disabled="configureBackup.busy" placeholder="/dev/disk/by-uuid/uuid" ng-required="configureBackup.provider === 'xfs' || configureBackup.provider === 'ext4'">
|
||||
</div>
|
||||
|
||||
<!-- Disk -->
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.diskPath || !configureBackup.mountOptions.diskPath }" ng-show="configureBackup.provider === 'disk'">
|
||||
<label class="control-label">{{ 'backups.configureBackupStorage.diskPath' | tr }}</label>
|
||||
<select class="form-control" ng-model="configureBackup.disk" ng-options="item as item.label for item in configureBackup.blockDevices track by item.path" ng-required="configureBackup.provider === 'disk'"></select>
|
||||
</div>
|
||||
|
||||
<!-- SSHFS -->
|
||||
<div class="form-group" ng-show="configureBackup.provider === 'sshfs'">
|
||||
<label class="control-label" for="configureBackupPort">{{ 'backups.configureBackupStorage.port' | tr }}</label>
|
||||
<input type="number" class="form-control" ng-model="configureBackup.mountOptions.port" id="configureBackupPort" name="port" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'sshfs'">
|
||||
</div>
|
||||
|
||||
<!-- SSHFS -->
|
||||
<div class="form-group" ng-show="configureBackup.provider === 'sshfs'">
|
||||
<label class="control-label" for="configureBackupUser">{{ 'backups.configureBackupStorage.user' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.mountOptions.user" id="configureBackupUser" name="user" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'sshfs'">
|
||||
</div>
|
||||
|
||||
<!-- SSHFS -->
|
||||
<div class="form-group" ng-show="configureBackup.provider === 'sshfs'">
|
||||
<label class="control-label" for="configureBackupPrivateKey">{{ 'backups.configureBackupStorage.privateKey' | tr }}</label>
|
||||
<textarea class="form-control" ng-model="configureBackup.mountOptions.privateKey" id="configureBackupPrivateKey" name="privateKey" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'sshfs'"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Filesystem -->
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.backupFolder }" ng-show="configureBackup.provider === 'filesystem'">
|
||||
<label class="control-label" for="inputConfigureBackupFolder">{{ 'backups.configureBackupStorage.localDirectory' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.backupFolder" id="inputConfigureBackupFolder" name="backupFolder" ng-disabled="configureBackup.busy" placeholder="Directory for backups" ng-required="configureBackup.provider === 'filesystem'">
|
||||
</div>
|
||||
|
||||
<!-- Filesystem/SSHFS/CIFS/NFS/EXT4/mountpoint -->
|
||||
<div class="checkbox" ng-show="configureBackup.provider === 'filesystem' || mountlike(configureBackup.provider)">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="configureBackup.useHardlinks">{{ 'backups.configureBackupStorage.hardlinksLabel' | tr }}</input>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- CIFS/mountpoint -->
|
||||
<div class="checkbox" ng-show="configureBackup.provider === 'mountpoint' || configureBackup.provider === 'cifs'">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="configureBackup.preserveAttributes">{{ 'backups.configureBackupStorage.preserveAttributesLabel' | tr }}</input>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- mountpoint -->
|
||||
<div class="checkbox" ng-show="configureBackup.provider === 'mountpoint'">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="configureBackup.chown">{{ 'backups.configureBackupStorage.chown' | tr }}</input>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- S3/Minio/SOS/GCS/UpCloud/B2/R2 -->
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.endpoint }" ng-show="configureBackup.provider === 'minio' || configureBackup.provider === 'upcloud-objectstorage' || configureBackup.provider === 'backblaze-b2' || configureBackup.provider === 'cloudflare-r2' || configureBackup.provider === 's3-v4-compat' || configureBackup.provider === 'idrive-e2'">
|
||||
<label class="control-label" for="inputConfigureBackupEndpoint">{{ 'backups.configureBackupStorage.s3Endpoint' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.endpoint" id="inputConfigureBackupEndpoint" name="endpoint" ng-disabled="configureBackup.busy" placeholder="URL" ng-required="configureBackup.provider === 'minio' || configureBackup.provider === 'upcloud-objectstorage' || configureBackup.provider === 'backblaze-b2' || configureBackup.provider === 'cloudflare-r2' || configureBackup.provider === 's3-v4-compat' || configureBackup.provider === 'idrive-e2'">
|
||||
</div>
|
||||
|
||||
<div class="checkbox" ng-show="configureBackup.provider === 'minio' || configureBackup.provider === 's3-v4-compat'" >
|
||||
<label>
|
||||
<input type="checkbox" ng-model="configureBackup.acceptSelfSignedCerts">{{ 'backups.configureBackupStorage.acceptSelfSignedCerts' | tr }}</input>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.bucket }" ng-show="s3like(configureBackup.provider) || configureBackup.provider === 'gcs'">
|
||||
<label class="control-label" for="inputConfigureBackupBucket">{{ 'backups.configureBackupStorage.bucketName' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.bucket" id="inputConfigureBackupBucket" name="bucket" ng-disabled="configureBackup.busy" ng-required="s3like(configureBackup.provider)">
|
||||
</div>
|
||||
|
||||
<!-- S3/Minio/SOS/GCS/SSHFS/CIFS/NFS/B2 -->
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.prefix }" ng-show="configureBackup.provider !== 'filesystem' && configureBackup.provider !== 'noop'">
|
||||
<label class="control-label" for="inputConfigureBackupPrefix">{{ 'backups.configureBackupStorage.prefix' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.prefix" id="inputConfigureBackupPrefix" name="prefix" ng-disabled="configureBackup.busy" placeholder="Prefix for backup file names">
|
||||
</div>
|
||||
|
||||
<!-- S3/Minio/SOS/GCS -->
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 's3'">
|
||||
<label class="control-label" for="inputConfigureBackupS3Region">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupS3Region" ng-model="configureBackup.region" ng-options="a.value as a.name for a in s3Regions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 's3'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 's3-v4-compat'">
|
||||
<label class="control-label" for="inputConfigureBackupS3V4CompatRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<input class="form-control" type="text" name="region" id="inputConfigureBackupS3V4CompatRegion" ng-model="configureBackup.region" ng-disabled="configureBackup.busy" placeholder="Leave empty to use us-east-1 as default"></input>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'digitalocean-spaces'">
|
||||
<label class="control-label" for="inputConfigureBackupDORegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupDORegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in doSpacesRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'digitalocean-spaces'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'hetzner-objectstorage'">
|
||||
<label class="control-label" for="inputConfigureBackupHetznerRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupHetznerRegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in hetznerRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'hetzner-objectstorage'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'exoscale-sos'">
|
||||
<label class="control-label" for="inputConfigureBackupExoscaleRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupExoscaleRegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in exoscaleSosRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'exoscale-sos'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'wasabi'">
|
||||
<label class="control-label" for="inputConfigureBackupWasabiRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupWasabiRegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in wasabiRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'wasabi'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'scaleway-objectstorage'">
|
||||
<label class="control-label" for="inputConfigureBackupScalewayRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupScalewayRegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in scalewayRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'scaleway-objectstorage'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'linode-objectstorage'">
|
||||
<label class="control-label" for="inputConfigureBackupLinodeRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupLinodeRegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in linodeRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'linode-objectstorage'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'ovh-objectstorage'">
|
||||
<label class="control-label" for="inputConfigureBackupOvhRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupOvhRegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in ovhRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'ovh-objectstorage'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'ionos-objectstorage'">
|
||||
<label class="control-label" for="inputConfigureBackupIonosRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupIonosRegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in ionosRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'ionos-objectstorage'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'vultr-objectstorage'">
|
||||
<label class="control-label" for="inputConfigureBackupVultrRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupVultrRegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in vultrRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'vultr-objectstorage'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 'contabo-objectstorage'">
|
||||
<label class="control-label" for="inputConfigureBackupContaboRegion">{{ 'backups.configureBackupStorage.region' | tr }}</label>
|
||||
<select class="form-control" name="region" id="inputConfigureBackupContaboRegion" ng-model="configureBackup.endpoint" ng-options="a.value as a.name for a in contaboRegions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'contabo-objectstorage'"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.accessKeyId }" ng-show="s3like(configureBackup.provider)">
|
||||
<label class="control-label" for="inputConfigureBackupAccessKeyId">{{ 'backups.configureBackupStorage.s3AccessKeyId' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.accessKeyId" id="inputConfigureBackupAccessKeyId" name="accessKeyId" ng-disabled="configureBackup.busy" ng-required="s3like(configureBackup.provider)">
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.secretAccessKey }" ng-show="s3like(configureBackup.provider)">
|
||||
<label class="control-label" for="inputConfigureBackupSecretAccessKey">{{ 'backups.configureBackupStorage.s3SecretAccessKey' | tr }}</label>
|
||||
<input type="text" class="form-control" ng-model="configureBackup.secretAccessKey" id="inputConfigureBackupSecretAccessKey" name="secretAccessKey" ng-disabled="configureBackup.busy" ng-required="s3like(configureBackup.provider)">
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.gcsKeyInput }" ng-show="configureBackup.provider === 'gcs'">
|
||||
<label class="control-label" for="gcsKeyInput">{{ 'backups.configureBackupStorage.gcsServiceKey' | tr }}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input type="file" id="gcsKeyFileInput" style="display:none"/>
|
||||
<input type="text" class="form-control" placeholder="Service Account Key" ng-model="configureBackup.gcsKey.keyFileName" id="gcsKeyInput" name="cert" onclick="getElementById('gcsKeyFileInput').click();" style="cursor: pointer;" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 'gcs'">
|
||||
<span class="input-group-addon">
|
||||
<i class="fa fa-upload" onclick="getElementById('gcsKeyFileInput').click();"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="configureBackup.provider !== 'noop'">
|
||||
<label class="control-label" for="storageFormat">{{ 'backups.configureBackupStorage.format' | tr }} <sup><a ng-href="https://docs.cloudron.io/backups/#backup-formats" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
||||
<p class="small text-info" ng-show="backupConfig.format !== configureBackup.format">{{ 'backups.configureBackupStorage.formatChangeNote' | tr }}</p>
|
||||
<p class="small text-info" ng-show="configureBackup.format === 'rsync' && (s3like(configureBackup.provider) || configureBackup.provider === 'gcs')">{{ 'backups.configureBackupStorage.s3LikeNote' | tr }} <sup><a ng-href="https://docs.cloudron.io/backups/#amazon-s3" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></p>
|
||||
<select class="form-control" id="storageFormat" ng-model="configureBackup.format" ng-options="a.value as a.name for a in formats"></select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.password }" ng-show="configureBackup.provider !== 'noop'">
|
||||
<label class="control-label" for="inputConfigureBackupPassword">{{ 'backups.configureBackupStorage.encryptionPassword' | tr }} <sup><a ng-href="https://docs.cloudron.io/backups/#encryption" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
|
||||
<p class="small">{{ 'backups.configureBackupStorage.encryptionDescription' | tr }}</p>
|
||||
<input type="text" class="form-control" name="encryptionPassword" ng-model="configureBackup.password" id="inputConfigureBackupPassword" ng-disabled="configureBackup.busy" placeholder="{{ 'backups.configureBackupStorage.encryptionPasswordPlaceholder' | tr }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="configureBackup.password && configureBackup.password !== SECRET_PLACEHOLDER" ng-class="{ 'has-error': (configureBackupForm.encryptionPassword.$dirty && configureBackup.password !== configureBackup.passwordRepeat) }">
|
||||
<label class="control-label" for="inputConfigureBackupPasswordRepeat">{{ 'backups.configureBackupStorage.encryptionPasswordRepeat' | tr }}</label>
|
||||
<input id="inputConfigureBackupPasswordRepeat" type="text" class="form-control" name="passwordRepeat" ng-model="configureBackup.passwordRepeat" ng-disabled="configureBackup.busy">
|
||||
</div>
|
||||
|
||||
<div class="checkbox" ng-show="configureBackup.password !== '' && configureBackup.format === 'rsync'">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="configureBackup.encryptedFilenames">{{ 'backups.configureBackupStorage.encryptFilenames' | tr }}</input>
|
||||
<sup><a ng-href="https://docs.cloudron.io/backups/#filenames" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<a href="" ng-click="configureBackup.advancedVisible = true" ng-hide="configureBackup.advancedVisible">{{ 'backups.configureBackupStorage.advancedSettings' | tr }}</a>
|
||||
<div uib-collapse="!configureBackup.advancedVisible">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="sliderConfigureBackupMemoryLimit">{{ 'backups.configureBackupStorage.memoryLimit' | tr }}: <b>{{ configureBackup.memoryLimit | prettyBinarySize:'1024 MB' }}</b></label>
|
||||
<p class="small">{{ 'backups.configureBackupStorage.memoryLimitDescription' | tr }}</p>
|
||||
<input type="range" id="sliderConfigureBackupMemoryLimit" ng-model="configureBackup.memoryLimit" step="{{ 256*1024*1024 }}" min="{{ MIN_MEMORY_LIMIT }}" max="{{ MAX_MEMORY_LIMIT }}" />
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="s3like(configureBackup.provider)">
|
||||
<label class="control-label" for="sliderConfigureBackupUploadPartSize">{{ 'backups.configureBackupStorage.uploadPartSize' | tr }}: <b>{{ configureBackup.uploadPartSize | prettyBinarySize:'Default (50 MiB)' }}</b></label>
|
||||
<p class="small">{{ 'backups.configureBackupStorage.uploadPartSizeDescription' | tr }}</p>
|
||||
<input type="range" id="sliderConfigureBackupUploadPartSize" ng-model="configureBackup.uploadPartSize" list="uploadPartSizeTicks" step="{{ 1024*1024 }}" min="{{ 1024*1024 }}" max="{{ 1024*1024*1024 }}" />
|
||||
<datalist id="uploadPartSizeTicks">
|
||||
<option value="{{ 1024*1024 }}"></option>
|
||||
<option value="{{ 64*1024*1024 }}"></option>
|
||||
<option value="{{ 128*1024*1024 }}"></option>
|
||||
<option value="{{ 256*1024*1024 }}"></option>
|
||||
<option value="{{ 512*1024*1024 }}"></option>
|
||||
<option value="{{ 1024*1024*1024 }}"></option>
|
||||
</datalist>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="configureBackup.format === 'rsync' && configureBackup.provider !== 'noop'">
|
||||
<label class="control-label" for="sliderConfigureBackupSyncConcurrency">{{ 'backups.configureBackupStorage.uploadConcurrency' | tr }}: <b>{{ configureBackup.syncConcurrency }}</b></label>
|
||||
<p class="small">{{ 'backups.configureBackupStorage.uploadConcurrencyDescription' | tr }}</p>
|
||||
<input type="range" id="sliderConfigureBackupSyncConcurrency" ng-model="configureBackup.syncConcurrency" step="10" min="10" max="200" />
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="configureBackup.format === 'rsync' && (s3like(configureBackup.provider) || configureBackup.provider === 'gcs')">
|
||||
<label class="control-label" for="sliderConfigureBackupDownloadConcurrency">{{ 'backups.configureBackupStorage.downloadConcurrency' | tr }}: <b>{{ configureBackup.downloadConcurrency }}</b></label>
|
||||
<p class="small">{{ 'backups.configureBackupStorage.downloadConcurrencyDescription' | tr }}</p>
|
||||
<input type="range" id="sliderConfigureBackupDownloadConcurrency" ng-model="configureBackup.downloadConcurrency" step="10" min="10" max="200" />
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="configureBackup.format === 'rsync' && (s3like(configureBackup.provider) || configureBackup.provider === 'gcs')">
|
||||
<label class="control-label" for="sliderConfigureBackupCopyConcurrency">{{ 'backups.configureBackupStorage.copyConcurrency' | tr }}: <b>{{ configureBackup.copyConcurrency }}</b></label>
|
||||
<p class="small">{{ 'backups.configureBackupStorage.copyConcurrencyDescription' | tr }}
|
||||
<span ng-show="configureBackup.provider === 'digitalocean-spaces'">{{ 'backups.configureBackupStorage.copyConcurrencyDigitalOceanNote' | tr }}</span>
|
||||
</p>
|
||||
<input type="range" id="sliderConfigureBackupCopyConcurrency" ng-model="configureBackup.copyConcurrency" step="10" min="10" max="500" />
|
||||
</div>
|
||||
|
||||
</div> <!-- advanced -->
|
||||
|
||||
<input class="ng-hide" type="submit" ng-disabled="configureBackupForm.$invalid || (configureBackup.password !== SECRET_PLACEHOLDER && configureBackup.password !== configureBackup.passwordRepeat)"/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer ">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
||||
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="configureBackup.submit()" ng-disabled="configureBackupForm.$invalid || configureBackup.busy || (configureBackup.password !== SECRET_PLACEHOLDER && configureBackup.password !== configureBackup.passwordRepeat)"><i class="fa fa-circle-notch fa-spin" ng-show="configureBackup.busy"></i><span> {{ 'main.dialog.save' | tr }}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal archive restore -->
|
||||
<div class="modal fade" id="restoreArchiveModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'backups.restoreArchiveDialog.title' | tr }}</h4>
|
||||
</div>
|
||||
<div class="modal-body" style="padding: 0 15px">
|
||||
<p ng-bind-html="'backups.restoreArchiveDialog.description' | tr:{ appId: archiveRestore.manifest.id, fqdn: archiveRestore.fqdn, creationTime: (archiveRestore.archive.creationTime | prettyLongDate) }"></p>
|
||||
<form role="form" ng-submit="archiveRestore.submit()" autocomplete="off">
|
||||
<fieldset>
|
||||
<div class="form-group" ng-class="{ 'has-error': archiveRestore.error.location.fqdn === archiveRestore.subdomain + '.' + archiveRestore.domain.domain }">
|
||||
<label class="control-label" for="cloneLocationInput">{{ 'app.cloneDialog.location' | tr }}</label>
|
||||
<div ng-show="archiveRestore.error.location.fqdn === archiveRestore.subdomain + '.' + archiveRestore.domain.domain"><small>{{ archiveRestore.error.location.message }}</small></div>
|
||||
<div class="input-group form-inline">
|
||||
<input type="text" class="form-control" ng-model="archiveRestore.subdomain" id="cloneLocationInput" name="location" placeholder="{{ 'appstore.installDialog.locationPlaceholder' | tr }}" autofocus>
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span>{{ '.' + archiveRestore.domain.domain }}</span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<li ng-repeat="domain in domains">
|
||||
<a href="" ng-click="archiveRestore.domain = domain">{{ domain.domain }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="has-error text-center" ng-show="archiveRestore.error.secondaryDomain">{{ archiveRestore.error.secondaryDomain }}</div>
|
||||
<div ng-repeat="(env, info) in archiveRestore.manifest.httpPorts">
|
||||
<ng-form name="secondaryDomainInfo_form">
|
||||
<div class="form-group" ng-class="{ 'has-error': (!secondaryDomainInfo_form.itemName{{$index}}.$dirty && archiveRestore.error.secondaryDomain) || (secondaryDomainInfo_form.itemName{{$index}}.$dirty && secondaryDomainInfo_form.itemName{{$index}}.$invalid) || (archiveRestore.error.location.fqdn === archiveRestore.secondaryDomains[env].subdomain + '.' + archiveRestore.secondaryDomains[env].domain.domain) }">
|
||||
<label class="control-label" for="secondaryDomainInput{{env}}">
|
||||
{{ info.title }}
|
||||
<sup>
|
||||
<a popover-placement="top-right" popover-trigger="outsideClick" uib-popover="{{info.description}}"><i class="fa fa-question-circle"></i></a>
|
||||
</sup>
|
||||
</label>
|
||||
|
||||
<div ng-show="archiveRestore.error.location.fqdn === archiveRestore.secondaryDomains[env].subdomain + '.' + archiveRestore.secondaryDomains[env].domain.domain"><small>{{ archiveRestore.error.location.message }}</small></div>
|
||||
<div class="input-group form-inline">
|
||||
<input type="text" class="form-control" ng-model="archiveRestore.secondaryDomains[env].subdomain" name="location{{$index}}" placeholder="{{ 'app.location.locationPlaceholder' | tr }}" autofocus>
|
||||
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span>.{{ archiveRestore.secondaryDomains[env].domain.domain }}</span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<li ng-repeat="domain in domains">
|
||||
<a href="" ng-click="archiveRestore.secondaryDomains[env].domain = domain">{{ domain.domain }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
<p class="text-small text-warning" ng-show="archiveRestore.domain.provider === 'noop' || archiveRestore.domain.provider === 'manual'" ng-bind-html="'appstore.installDialog.manualWarning' | tr:{ location: ((archiveRestore.subdomain ? archiveRestore.subdomain + '.' : '') + archiveRestore.domain.domain) }"></p>
|
||||
|
||||
<div class="has-error text-center" ng-show="archiveRestore.error.port">{{ archiveRestore.error.port }}</div>
|
||||
<div ng-repeat="(env, info) in archiveRestore.portInfo">
|
||||
<ng-form name="portInfo_form">
|
||||
<div class="form-group" ng-class="{ 'has-error': (!archiveRestore.itemName{{$index}}.$dirty && archiveRestore.error.port) || (portInfo_form.itemName{{$index}}.$dirty && portInfo_form.itemName{{$index}}.$invalid) }">
|
||||
<label class="control-label" for="inputPortInfo{{env}}"><input type="checkbox" ng-model="archiveRestore.portsEnabled[env]">
|
||||
{{ info.title }}
|
||||
<sup>
|
||||
<a popover-placement="top-right" popover-trigger="outsideClick" uib-popover="{{info.description}}"><i class="fa fa-question-circle"></i></a>
|
||||
</sup>
|
||||
<small style="padding-left: 5px;" ng-show="info.readOnly">{{ 'appstore.installDialog.portReadOnly' | tr }}</small>
|
||||
</label>
|
||||
<input type="number" class="form-control" ng-model="archiveRestore.ports[env]" ng-disabled="!archiveRestore.portsEnabled[env]" ng-readonly="info.readOnly" id="inputPortInfo{{env}}" later-name="itemName{{$index}}" min="{{hostPortMin}}" max="{{hostPortMax}}" required>
|
||||
<p class="text-small text-warning text-bold" ng-show="archiveRestore.domain.provider === 'cloudflare'">{{ 'appstore.installDialog.cloudflarePortWarning' | tr }} </p>
|
||||
</div>
|
||||
</ng-form>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
||||
<button type="button" class="btn btn-success" ng-click="archiveRestore.submit()" ng-disabled="archiveRestore.busy"><i class="fas fa-history" ng-hide="archiveRestore.busy"></i><i class="fa fa-circle-notch fa-spin" ng-show="archiveRestore.busy"></i> {{ 'backups.restoreArchiveDialog.restoreAction' | tr:{ dnsOverwrite: archiveRestore.needsOverwrite } }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal delete archive -->
|
||||
<div class="modal fade" id="archiveDeleteModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ 'backups.deleteArchiveDialog.title' | tr:{ appTitle: archiveDelete.title, fqdn: archiveDelete.fqdn } }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{ 'backups.deleteArchiveDialog.description' | tr }}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="archiveDelete.submit()" ng-disabled="archiveDelete.busy"><i class="fa fa-circle-notch fa-spin" ng-show="archiveDelete.busy"></i> {{ 'backups.deleteArchive.deleteAction' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
|
||||
<h1 class="section-header">{{ 'backups.title' | tr }}</h1>
|
||||
|
||||
<div class="text-left">
|
||||
<h3>{{ 'backups.location.title' | tr }}</h3>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom: 15px;">
|
||||
<p>{{ 'backups.location.description' | tr }}
|
||||
<span ng-show="manualBackupApps.length">
|
||||
{{ 'backups.location.disabledList' | tr }}
|
||||
<span ng-repeat="app in manualBackupApps">
|
||||
<a ng-href="/#/app/{{app.id}}/backups">{{app.label || app.fqdn}}</a><span ng-hide="$last">,</span>
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p ng-show="backupConfig.provider === 'noop'" class="text-danger" ng-bind-html="'backups.check.noop' | tr | markdown2html"></p>
|
||||
<p ng-show="backupConfig.provider === 'filesystem'" class="text-danger" ng-bind-html="'backups.check.sameDisk' | tr | markdown2html"></p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<span class="text-muted">{{ 'backups.location.provider' | tr }}</span>
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
<span>{{ prettyProviderName(backupConfig.provider) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-show="backupConfig.provider !== 'noop'">
|
||||
<div class="col-xs-6">
|
||||
<span class="text-muted">{{ 'backups.location.location' | tr }}</span>
|
||||
</div>
|
||||
<div class="col-xs-6 text-right no-wrap">
|
||||
<span ng-show="backupConfig.provider === 'filesystem'">{{ backupConfig.backupFolder }}</span>
|
||||
<span ng-show="mountlike(backupConfig.provider)">
|
||||
<i class="fa fa-circle" ng-style="{ color: mountStatus.state === 'active' ? '#27CE65' : '#d9534f' }" ng-show="mountStatus" uib-tooltip="{{ mountStatus.message }}"></i>
|
||||
<span ng-show="backupConfig.provider === 'disk' || backupConfig.provider === 'filesystem' || backupConfig.provider === 'ext4' || backupConfig.provider === 'xfs' || backupConfig.provider === 'mountpoint'">{{ backupConfig.mountOptions.diskPath || backupConfig.mountPoint }}{{ (backupConfig.prefix ? '/' : '') + backupConfig.prefix }}</span>
|
||||
<span ng-show="backupConfig.provider === 'cifs' || backupConfig.provider === 'nfs' || backupConfig.provider === 'sshfs'">{{ backupConfig.mountOptions.host }}:{{ backupConfig.mountOptions.remoteDir }}{{ (backupConfig.prefix ? '/' : '') + backupConfig.prefix }}</span>
|
||||
</span>
|
||||
|
||||
<span ng-show="backupConfig.provider !== 's3' && backupConfig.provider !== 'minio' && (s3like(backupConfig.provider) || backupConfig.provider === 'gcs')">{{ backupConfig.bucket + (backupConfig.prefix ? '/' : '') + backupConfig.prefix }}</span>
|
||||
<span ng-show="backupConfig.provider === 's3'">{{ backupConfig.region + ' ' + backupConfig.bucket + (backupConfig.prefix ? '/' : '') + backupConfig.prefix }}</span>
|
||||
<span ng-show="backupConfig.provider === 'minio'">{{ backupConfig.endpoint + ' ' + backupConfig.bucket + (backupConfig.prefix ? '/' : '') + backupConfig.prefix }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-show="backupConfig.endpoint && backupConfig.provider !== 'minio'">
|
||||
<div class="col-xs-3">
|
||||
<span class="text-muted">{{ 'backups.location.endpoint' | tr }}</span>
|
||||
</div>
|
||||
<div class="col-xs-9 text-right">
|
||||
<span>{{ backupConfig.endpoint || backupConfig.region }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<span class="text-muted">{{ 'backups.location.format' | tr }}</span>
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
<span>{{ backupConfig.format }} <i class="fas fa-lock" ng-show="backupConfig.password" ></i></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<button class="btn btn-outline btn-primary pull-right" ng-show="user.isAtLeastOwner" ng-click="configureBackup.show()">{{ 'backups.location.configure' | tr }}</button>
|
||||
<button class="btn btn-outline btn-default pull-right" ng-show="user.isAtLeastOwner && mountlike(backupConfig.provider)" ng-disabled="remount.busy" ng-click="remount.submit()"><i class="fa fa-circle-notch fa-spin" ng-show="remount.busy"></i> {{ 'backups.location.remount' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="section-header">
|
||||
{{ 'backups.schedule.title' | tr }}
|
||||
<!-- <a class="btn btn-sm btn-default pull-right" ng-href="/logs.html?taskId={{cleanupBackups.taskId}}" target="_blank" uib-tooltip="{{ 'backups.logs.showLogs' | tr }}"><i class="fas fa-align-left"></i></a> -->
|
||||
<div class="btn-group btn-group-sm pull-right">
|
||||
<button type="button" class="btn btn-small btn-default dropdown-toggle" ng-show="cleanupTasks.length" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" uib-tooltip="{{ 'backups.logs.showLogs' | tr }}">
|
||||
<i class="fas fa-align-left"></i> <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li ng-repeat="task in cleanupTasks">
|
||||
<a ng-href="/logs.html?taskId={{task.id}}" target="_blank" class="text-right">
|
||||
{{ task.ts | prettyLongDate }} <i class="fa" style="margin-left: 20px" ng-class="{ 'status-active fa-check-circle': !task.active && task.success, 'fa-circle-notch fa-spin': task.active, 'status-error fa-times-circle': !task.active && !task.success }"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
<div class="card" style="margin-bottom: 15px;">
|
||||
<p ng-bind-html=" 'backups.schedule.description' | tr "></p>
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<span class="text-muted">{{ 'backups.schedule.schedule' | tr }}</span>
|
||||
</div>
|
||||
<div class="col-xs-8 text-right" style="text-overflow: ellipsis; overflow: hidden; white-space: nowrap;">
|
||||
<span>{{ prettyBackupSchedule(backupPolicy.currentPolicy.schedule) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<span class="text-muted">{{ 'backups.schedule.retentionPolicy' | tr }}</span>
|
||||
</div>
|
||||
<div class="col-xs-8 text-right">
|
||||
<span>{{ prettyBackupRetention(backupPolicy.currentPolicy.retention) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-right">
|
||||
<button class="btn btn-default" ng-click="cleanupBackups.ask()" ng-disabled="cleanupBackups.busy" style="margin-right: 5px"><i class="fa fa-circle-notch fa-spin" ng-show="cleanupBackups.busy"></i> {{ 'backups.listing.cleanupBackups' | tr }}</button>
|
||||
<button class="btn btn-outline btn-primary pull-right" ng-show="user.isAtLeastOwner" ng-click="backupPolicy.show()">{{ 'backups.schedule.configure' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="section-header">
|
||||
{{ 'backups.listing.title' | tr }}
|
||||
<div class="btn-group btn-group-sm pull-right">
|
||||
<button type="button" class="btn btn-small btn-default dropdown-toggle" ng-show="backupTasks.length" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" uib-tooltip="{{ 'backups.logs.showLogs' | tr }}">
|
||||
<i class="fas fa-align-left"></i> <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li ng-repeat="task in backupTasks">
|
||||
<a ng-href="/logs.html?taskId={{task.id}}" target="_blank" class="text-right">
|
||||
{{ task.ts | prettyLongDate }} <i class="fa" style="margin-left: 20px" ng-class="{ 'status-active fa-check-circle': !task.active && task.success, 'fa-circle-notch fa-spin': task.active, 'status-error fa-times-circle': !task.active && !task.success }"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
<div class="card card-large">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<p ng-show="!backups.length">{{ 'backups.listing.noBackups' | tr }}</p>
|
||||
|
||||
<table class="table table-hover" style="margin: 0;" ng-hide="!backups.length">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20px"></th>
|
||||
<th>{{ 'backups.listing.version' | tr }}</th>
|
||||
<th>{{ 'main.table.date' | tr }}</th>
|
||||
<th class="hide-mobile">{{ 'backups.listing.contents' | tr }}</th>
|
||||
<th class="text-right">{{ 'main.actions' | tr }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="backup in backups">
|
||||
<td><i class="fas fa-archive" ng-show="backup.preserveSecs === -1" uib-tooltip="{{ 'backups.listing.tooltipPreservedBackup' | tr }}"></i></td>
|
||||
<td ng-click="backupDetails.show(backup)" class="hand">v{{ backup.packageVersion }}</td>
|
||||
<td ng-click="backupDetails.show(backup)" class="hand">{{ backup.creationTime | prettyLongDate }} <b ng-show="backup.label">({{ backup.label }})</b></td>
|
||||
<td ng-click="backupDetails.show(backup)" class="hand hide-mobile">
|
||||
<span ng-show="!backup.contents.length">{{ 'backups.listing.noApps' | tr }}</span>
|
||||
<span ng-show="backup.contents.length">{{ 'backups.listing.appCount' | tr:{ appCount: backup.contents.length } }}</span>
|
||||
</td>
|
||||
<td class="text-right no-wrap">
|
||||
<button class="btn btn-xs btn-default" ng-click="editBackup.show(backup)" uib-tooltip="{{ 'backups.listing.tooltipEditBackup' | tr }}"><i class="fa fa-pencil-alt"></i></button>
|
||||
<button class="btn btn-xs btn-default" ng-click="downloadConfig(backup)" uib-tooltip="{{ 'backups.listing.tooltipDownloadBackupConfig' | tr }}"><i class="fas fa-file-alt"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="row" ng-show="createBackup.busy">
|
||||
<div class="col-md-12" style="margin-bottom: 10px;">
|
||||
<div class="progress progress-striped active animateMe">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ createBackup.percent }}%"></div>
|
||||
</div>
|
||||
<p>{{ createBackup.message }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-show="!createBackup.busy && !createBackup.active && createBackup.errorMessage">
|
||||
<div class="col-md-12">
|
||||
<p class="has-error">{{ createBackup.errorMessage }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-right">
|
||||
<button class="btn btn-outline btn-primary" ng-click="createBackup.startBackup()" ng-show="!createBackup.busy">{{ 'backups.listing.backupNow' | tr }}</button>
|
||||
<button class="btn btn-outline btn-danger" ng-click="createBackup.stopTask()" ng-show="createBackup.busy">{{ 'backups.listing.stopTask' | tr }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="section-header">
|
||||
{{ 'backups.archives.title' | tr }}
|
||||
</h3>
|
||||
|
||||
<div class="card card-large">
|
||||
<p ng-bind-html=" 'backups.archive.description' | tr "></p>
|
||||
|
||||
<div class="grid-item-top">
|
||||
<div class="row ng-hide" ng-show="!archiveList.ready">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h2><i class="fa fa-circle-notch fa-spin"></i></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row animateMeOpacity ng-hide" ng-show="archiveList.ready">
|
||||
<div class="col-lg-12">
|
||||
<table class="table table-hover" style="margin: 0;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 5%"></th> <!-- icon -->
|
||||
<th style="width: 35%">{{ 'backups.archives.location' | tr }}</th>
|
||||
<th style="width: 35%" class="hide-mobile">{{ 'backups.archives.info' | tr }}</th>
|
||||
<th style="width: 20%">{{ 'main.table.date' | tr }}</th>
|
||||
<th style="width: 5%" class="text-right hide-mobile">{{ 'main.actions' | tr }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="archive in archiveList.archives">
|
||||
<td>
|
||||
<img ng-src="{{ archive.iconUrl || 'img/appicon_fallback.png' }}" fallback-icon="img/appicon_fallback.png" onerror="imageErrorHandler(this)" height="48" width="48"/>
|
||||
</td>
|
||||
<!-- for pre-8.2 backups, appConfig can be null -->
|
||||
<td class="hand elide-table-cell" style="text-overflow: ellipsis; white-space: nowrap;" ng-click="archiveRestore.show(archive)">
|
||||
{{ archive.appConfig ? archive.appConfig.fqdn : '-' }}
|
||||
</td>
|
||||
<td class="hand elide-table-cell hide-mobile" style="text-overflow: ellipsis; white-space: nowrap;" ng-click="archiveRestore.show(archive)">
|
||||
<span uib-tooltip="{{ archive.manifest.id }}@{{ archive.manifest.version }}">{{ archive.manifest.title }}</span>
|
||||
</td>
|
||||
<td class="hand elide-table-cell" style="text-overflow: ellipsis; white-space: nowrap;" ng-click="archiveRestore.show(archive)">
|
||||
{{ archive.creationTime | prettyDate }}
|
||||
</td>
|
||||
<td class="text-right no-wrap hide-mobile" style="vertical-align: middle;">
|
||||
<button class="btn btn-xs btn-default" ng-click="archiveRestore.show(archive)" uib-tooltip="Restore from Archive"><i class="fas fa-history"></i></button>
|
||||
<button class="btn btn-xs btn-default" ng-click="downloadConfig(archive, true)" uib-tooltip="{{ 'backups.listing.tooltipDownloadBackupConfig' | tr }}"><i class="fas fa-file-alt"></i></button>
|
||||
<button class="btn btn-xs btn-danger" ng-click="archiveDelete.ask(archive)" uib-tooltip="Delete Archive"><i class="fa fa-trash-alt"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||