Compare commits
1226 commits
middleware
...
master
Author | SHA1 | Date | |
---|---|---|---|
b72f3f3395 | |||
![]() |
42380643df | ||
bfd8619505 | |||
0c43c56698 | |||
c1eb44e599 | |||
2c53acc214 | |||
cb8f0aab18 | |||
0d653acd2e | |||
c41281378b | |||
136aca5b83 | |||
1624fdecc2 | |||
de0f0d3040 | |||
0e600c7113 | |||
eb9232305f | |||
2f30d8d27f | |||
0f1cd2e32a | |||
b99b4ffdc4 | |||
c75697b221 | |||
7da38fbc8a | |||
23620e178b | |||
b81648cdc8 | |||
83efe094b8 | |||
c2ed4b9cc2 | |||
074c9414b2 | |||
63285485ca | |||
d59cba7c0d | |||
9a6b66f7d9 | |||
283320b161 | |||
773cd7d419 | |||
326be3eaa0 | |||
6bfeab0a5a | |||
befb013e58 | |||
82a1efc965 | |||
aed8e0ea44 | |||
7237364ba5 | |||
6eb4633af0 | |||
9ccacaecb5 | |||
955dd60235 | |||
0a58751155 | |||
d1ba5057f1 | |||
683796ea7e | |||
4a771b802b | |||
84ed9e09a7 | |||
9460c484f7 | |||
2767e82f11 | |||
42c651ceb7 | |||
5d4b600b00 | |||
c1da67dbb4 | |||
5125525238 | |||
34f0dffd79 | |||
9e513bba9a | |||
ef9d51d922 | |||
ca5e6728dd | |||
7563dd728c | |||
cb14e4a91e | |||
1719e8be9a | |||
0634cdad87 | |||
90e7b97b85 | |||
4001822842 | |||
7ca7093371 | |||
fbd75d2f72 | |||
e12b614e1c | |||
bcda95f0b3 | |||
6c35a5b6f3 | |||
e933c6978d | |||
2f814956a7 | |||
f61533df0a | |||
7676b0ef60 | |||
95b46541c0 | |||
0af99d4f3e | |||
f369110cd3 | |||
c54e11f25a | |||
e205ca52d3 | |||
44a8649d0e | |||
a4175f836e | |||
174087edc7 | |||
4906f82365 | |||
41032be9eb | |||
422caadb9e | |||
aa997bfcd8 | |||
1a2bef328b | |||
a84df1909b | |||
0724030bef | |||
833893f233 | |||
a7746cddda | |||
2c627b3d60 | |||
5f904b5c66 | |||
94ca903cec | |||
50936e2b50 | |||
4a35a63f31 | |||
4006ecd6b8 | |||
ce2d183446 | |||
1ff69f943e | |||
050ebba03b | |||
443a226943 | |||
7da9aa5fe3 | |||
e257f31ea5 | |||
87466ce2b6 | |||
291f39990d | |||
b637aed7ab | |||
3e2469fc45 | |||
d5c57da921 | |||
370dd7d841 | |||
d818ce251b | |||
4121de260e | |||
a8b7788d35 | |||
9aa3a5154d | |||
7a4c8239f6 | |||
0d67b5ff83 | |||
2deccfada4 | |||
d2e199e509 | |||
9b0fe3d32f | |||
af41ca5784 | |||
ad2d1e676c | |||
00e0ed0a50 | |||
5563eb681c | |||
3b74772949 | |||
ee69bf4c4f | |||
071c66ee10 | |||
1bee36d9b6 | |||
aa364b3f49 | |||
9a11491dcc | |||
a97071cd03 | |||
9c4c60765e | |||
d67d2f372b | |||
dd86fc1fcb | |||
341ae7ce45 | |||
7906c87733 | |||
daf24ff981 | |||
0dde05f102 | |||
3528a44d3c | |||
524593b7ef | |||
65ec9bfaed | |||
7038de2e25 | |||
c43575d8d2 | |||
8d6b352545 | |||
51eeffd0c5 | |||
42d57e7b42 | |||
edde41e1ab | |||
6ea212cdf8 | |||
![]() |
497bb054ee | ||
e9451ed62e | |||
![]() |
e87b84b028 | ||
22e88daf02 | |||
04508206bb | |||
8d09fd5389 | |||
9df34c22e0 | |||
d3d5484d0e | |||
62160e8440 | |||
1e6e6118a7 | |||
c1440687aa | |||
69e870f958 | |||
ddd12b684d | |||
eb2b861d48 | |||
9020f5551d | |||
ca462289a9 | |||
80b20f5290 | |||
dbe8c39b37 | |||
0aee5b9bdb | |||
aee7637fcf | |||
5bf8df0218 | |||
5853b243dd | |||
![]() |
5f87045b31 | ||
![]() |
36b261580c | ||
![]() |
3920ac72aa | ||
dc91ef571f | |||
f0fbd8021f | |||
3d035b994a | |||
db3dd39696 | |||
e0e1dfda41 | |||
![]() |
44766efe2a | ||
d129f8a764 | |||
5b330567f8 | |||
e6a21a5f1b | |||
042246e948 | |||
e224ee66a7 | |||
5ccb94d155 | |||
fa00652a69 | |||
036c68bc2a | |||
fcc2c7c374 | |||
1b755ad1f7 | |||
ad5a242f8d | |||
6186914a7c | |||
7a781e463f | |||
2dbbb588d0 | |||
eada7920f0 | |||
6a7e4b1a39 | |||
5883a5cd28 | |||
7e8092c30c | |||
f01a808ac2 | |||
c8dd54e8ba | |||
![]() |
f2825a97cf | ||
0f6f6a85b6 | |||
502588fd3a | |||
b4b6c7c0ce | |||
0e83f96318 | |||
e660a96df2 | |||
854c902322 | |||
024f8e0a80 | |||
bf726df117 | |||
227d438ebd | |||
71948383d2 | |||
6df9665af3 | |||
c1938c8ff7 | |||
4536c56a83 | |||
8156f7828e | |||
f5c2e22121 | |||
62a42675f8 | |||
a372aa1bc2 | |||
d0cb46b658 | |||
ac6c41cc88 | |||
1c146ac5c3 | |||
527a7b3ea6 | |||
e4a72940e8 | |||
7b3708d7ab | |||
c0825691a6 | |||
b606f03191 | |||
![]() |
461cfa4253 | ||
![]() |
a2517abade | ||
![]() |
51618e0d89 | ||
![]() |
9b14e4a333 | ||
![]() |
8283b530e9 | ||
![]() |
e10747aa9f | ||
![]() |
8ae19988b1 | ||
![]() |
2659d72d2e | ||
007332804e | |||
7f21d10c26 | |||
dc0ff80632 | |||
07d1505e2a | |||
9ca5967261 | |||
eb6eb2d6fb | |||
28fef9a393 | |||
f8b1f0978c | |||
5f931c49a5 | |||
![]() |
5c7710ed3a | ||
6cdc37e80b | |||
8fd582d194 | |||
27a16719be | |||
87a76b17ef | |||
![]() |
ad9a496cee | ||
![]() |
26d37d96f7 | ||
![]() |
062f70e947 | ||
5db14ea242 | |||
![]() |
92c05342fb | ||
b8f377b15d | |||
a6085a64f4 | |||
c71195fba1 | |||
9ee82f72a7 | |||
ce83247fe0 | |||
46a8f136fa | |||
e0dc75763c | |||
788e8d22a2 | |||
11eb3c3665 | |||
446515a52e | |||
![]() |
c7fe1cb386 | ||
![]() |
07e9c8b7e4 | ||
![]() |
10a824719b | ||
![]() |
d288fefecc | ||
![]() |
130907174d | ||
![]() |
33381b4307 | ||
c7910ed72a | |||
35fa97d828 | |||
35131c96ec | |||
acdadc06ab | |||
2ae906495d | |||
![]() |
49e93025c0 | ||
![]() |
d1172b9d38 | ||
![]() |
792a8fa4dc | ||
622b632773 | |||
91b6220f24 | |||
bb0cf871ec | |||
3db6231a77 | |||
d5d55d76a9 | |||
0423bce762 | |||
f9a28689b0 | |||
7108702e36 | |||
e443ecf33d | |||
8d846647f6 | |||
8ff66cb631 | |||
227b83b701 | |||
192f5d2ee7 | |||
77d158a3a7 | |||
05e6e5fb59 | |||
fbd5087c02 | |||
8dca676edc | |||
ffcc2e04a3 | |||
b491dcff7e | |||
592ae29d35 | |||
133c487637 | |||
9f421e9d77 | |||
e87bbe6048 | |||
6ec2a10bf5 | |||
c45bf88d40 | |||
733484b503 | |||
e250f1d5dc | |||
d8d37adc1f | |||
1b01fe54d2 | |||
b41b912aa4 | |||
348096024e | |||
d952ab13a5 | |||
bf748b55ee | |||
6a781323e0 | |||
0b0a939de5 | |||
c34716e134 | |||
85c3969c50 | |||
18364eb531 | |||
95ab0ee1dc | |||
731c795ee6 | |||
31b7cbb8d7 | |||
ba2ea74a04 | |||
a6eebb2d59 | |||
be8c9810e4 | |||
47894ce335 | |||
5f7ec853fa | |||
0cab9a8286 | |||
9920465f99 | |||
99a1fd9a9f | |||
431978e626 | |||
69635b4234 | |||
f0b642ca44 | |||
8dc3a2ba98 | |||
8fef21900c | |||
1d36cd0761 | |||
e21a93f9e7 | |||
ead2a4ede3 | |||
5f9bda9afe | |||
0817012130 | |||
7a6a7cb0f5 | |||
75344c2c3a | |||
350623c6ac | |||
2bb732959a | |||
d55199d6ae | |||
05a710185c | |||
4a3681b1a6 | |||
ccf3ec07f7 | |||
b44bdadb0a | |||
a6220e8d50 | |||
27beb34153 | |||
62a65af40e | |||
036af434c6 | |||
d1db1b952f | |||
ddda7052ae | |||
0fa2fb8e2b | |||
b094347b7c | |||
3188e024da | |||
69019baf4e | |||
ec474530e4 | |||
f564d4e145 | |||
49aea5b8b4 | |||
![]() |
ca8e8506b3 | ||
![]() |
2444e5f985 | ||
476f8263d4 | |||
1ce9cb445f | |||
6225630f9f | |||
0bebee5329 | |||
![]() |
3c3b9f755a | ||
40ca76d414 | |||
cf3c9f6f80 | |||
fad2c6940d | |||
491f91cf47 | |||
![]() |
2304a8282c | ||
![]() |
8a5659420d | ||
![]() |
d895cd0636 | ||
c0958d79db | |||
737c296da9 | |||
![]() |
067cd07352 | ||
![]() |
f75408e936 | ||
![]() |
c917655a22 | ||
![]() |
c78b932587 | ||
![]() |
381c5ca3de | ||
![]() |
15b09c23a7 | ||
7c1d9a0329 | |||
![]() |
e431e23ad4 | ||
![]() |
8dbb92d3a4 | ||
e06080ae31 | |||
![]() |
6165c5916b | ||
![]() |
bb1fb87665 | ||
![]() |
8949424f48 | ||
37f988f478 | |||
![]() |
a3a9c629d8 | ||
![]() |
607129a899 | ||
![]() |
b8328c0932 | ||
![]() |
2ce45b3d89 | ||
![]() |
e618d390de | ||
af9f244207 | |||
![]() |
7e6dd72722 | ||
![]() |
3be9578ec3 | ||
20691f483a | |||
64465a0471 | |||
![]() |
7569447baa | ||
![]() |
235bd096e0 | ||
![]() |
6c59c3c2ed | ||
![]() |
9f08ec332f | ||
![]() |
e075a9e749 | ||
![]() |
8c4bf4d19a | ||
![]() |
e3771f865d | ||
![]() |
cdc1472595 | ||
4d13b0eb25 | |||
6cc1b1fbe7 | |||
72f11a25ce | |||
3f1a570878 | |||
c21d040202 | |||
53caf7f73a | |||
ed703b10a1 | |||
![]() |
99c0095465 | ||
b8b0c5440f | |||
![]() |
676b94ca1b | ||
![]() |
6ab00392cc | ||
![]() |
5070a4d914 | ||
![]() |
77d392f14f | ||
![]() |
03589e484c | ||
![]() |
8ab25545a4 | ||
![]() |
4eb6746c75 | ||
48123a8ce2 | |||
d09a08f53f | |||
9a93f95490 | |||
fd736829c2 | |||
026efe2467 | |||
a301b122fd | |||
![]() |
51f730fe71 | ||
![]() |
e0d45ddf5d | ||
![]() |
9b12681e45 | ||
![]() |
d21ac37187 | ||
![]() |
49f9b05285 | ||
![]() |
a17914f49c | ||
![]() |
b4b41b9499 | ||
![]() |
1a3dd5d6b2 | ||
![]() |
54db53805a | ||
![]() |
b17b97e4e4 | ||
![]() |
9c1c393395 | ||
![]() |
858b5ce054 | ||
![]() |
ace30c931e | ||
![]() |
e083f74a83 | ||
![]() |
53f40e193d | ||
![]() |
9e21b2ca1a | ||
![]() |
1f0e6cccf6 | ||
![]() |
46f1d3d42d | ||
5eb936d891 | |||
![]() |
a23daf8b97 | ||
![]() |
457236c21a | ||
![]() |
4182bd542e | ||
![]() |
17b4a4764c | ||
![]() |
8cc5864257 | ||
df5ae2c12a | |||
![]() |
d4b92854c2 | ||
![]() |
559297240d | ||
![]() |
e3ce5efdd6 | ||
![]() |
a1c1b9f280 | ||
![]() |
b550857a8d | ||
![]() |
ae8040fb04 | ||
![]() |
7a34fced0a | ||
81494a7152 | |||
![]() |
a1000ad2bf | ||
![]() |
88ae103ec1 | ||
![]() |
213d3cc7b2 | ||
![]() |
4ecd2a7a61 | ||
![]() |
d2926bd1a7 | ||
![]() |
a59e2f9977 | ||
bd1d04802b | |||
8cd3250bb0 | |||
cc09980632 | |||
3363fbdc7c | |||
3f8756148d | |||
7b1e3ab58b | |||
ee7771bdb3 | |||
10c252cd16 | |||
a4a4af5f93 | |||
5048439aee | |||
14e8520b20 | |||
31ee8937f8 | |||
d469019c44 | |||
a1fa654bec | |||
81004d7cdc | |||
da705927c2 | |||
ce54684680 | |||
837986bad8 | |||
d7195a42f1 | |||
264f4d7646 | |||
5bf2df563b | |||
6d270b7af5 | |||
d41eb64ab5 | |||
805ed9204c | |||
3d2f0f08c3 | |||
9cca7beba5 | |||
c5b81871d2 | |||
52dc337a20 | |||
eec9abb9c1 | |||
c731af9ccd | |||
f5e8f5bb77 | |||
72c20d2b94 | |||
b2911d5e9f | |||
239a324a19 | |||
c0a3e3df8f | |||
b4c693a9ab | |||
c130ab8426 | |||
a72435dd72 | |||
8e1a03863f | |||
b8f2e1da3b | |||
824a4d9eb3 | |||
![]() |
39d618834b | ||
46fd51e7d9 | |||
![]() |
f41d5587fc | ||
8babbd988c | |||
ea5ee85e7a | |||
187ca0ec93 | |||
7a28649436 | |||
1802e90952 | |||
0f3874beb5 | |||
191177aea0 | |||
![]() |
37586d7433 | ||
3bfdde10e8 | |||
b5de60d681 | |||
0204bd2444 | |||
3fd0c7f917 | |||
6cb41a1263 | |||
![]() |
ca0bbb1247 | ||
![]() |
158c0e4d90 | ||
![]() |
f7382fb946 | ||
![]() |
0bbb860b16 | ||
![]() |
6a5390cdf6 | ||
![]() |
f197261271 | ||
![]() |
df2e4f086a | ||
ffa0c682f4 | |||
0fbfb1e3cd | |||
c55fbb9dca | |||
![]() |
7a4213a61e | ||
![]() |
37437b9674 | ||
2afa250df6 | |||
78866fbc93 | |||
![]() |
a9a426ca91 | ||
![]() |
b456b8c861 | ||
6fe9beb0f0 | |||
f457520d7d | |||
cda00bbc4c | |||
![]() |
668546c720 | ||
e889620ddb | |||
c673d04082 | |||
36124fa69e | |||
14b3caaa04 | |||
e9782c73e4 | |||
![]() |
93cfa504a8 | ||
29b5361545 | |||
e589564840 | |||
10c6f4be16 | |||
04e2007c3a | |||
1f7b770a5c | |||
b8eee44ed0 | |||
b36c030af5 | |||
dca7a7bedd | |||
c635b0a280 | |||
1aa389414d | |||
![]() |
aff9a39262 | ||
![]() |
2d416472e8 | ||
![]() |
7e1644d5c1 | ||
b69ebcd6b6 | |||
![]() |
002e33002c | ||
205409abc5 | |||
68d51a0bf1 | |||
0e24c1d9ad | |||
29b3271200 | |||
60346d6839 | |||
bb127832dc | |||
![]() |
1f0d70b31e | ||
0738aedc9e | |||
d006f6ebfa | |||
bfb7a75b97 | |||
![]() |
8a473a5097 | ||
![]() |
f14df7b579 | ||
![]() |
e182785e48 | ||
fb31b10d66 | |||
30ce5a0888 | |||
0c90c2bd06 | |||
![]() |
df657953ab | ||
527c06d91e | |||
![]() |
449a3db56b | ||
767358ca73 | |||
5b36650e6f | |||
24c790185e | |||
![]() |
14c6706bf3 | ||
![]() |
10b2d11249 | ||
![]() |
3eb9c7998d | ||
![]() |
36a7a5af5d | ||
![]() |
844c55d5a7 | ||
![]() |
2cf4d87c6b | ||
01ad1daba9 | |||
![]() |
feffa99d79 | ||
cefbd4df7a | |||
363776ba4f | |||
13c48ae1c2 | |||
0528dbbb9c | |||
37d29fcf58 | |||
baaaa0829a | |||
e641724eab | |||
205aa0b900 | |||
c64294099e | |||
94ea718c20 | |||
0bf309fd78 | |||
dae3864ba4 | |||
18f55153be | |||
50ca3ac71f | |||
a20d7c3c34 | |||
![]() |
5048f52ac6 | ||
bb2332dc27 | |||
b67525a11f | |||
b14395f91a | |||
07c465e6ca | |||
1a008dff19 | |||
e6d4bfe0f5 | |||
5e7f6c81bc | |||
cab40cc6ef | |||
5169c357aa | |||
ff7914fbb2 | |||
dce1de7a99 | |||
2ef3311bff | |||
727d0b2955 | |||
bed107aeac | |||
2ab6e76fbe | |||
1a63195b58 | |||
6f3fe7f0da | |||
4e1ff92bd8 | |||
f3b0079651 | |||
3640c756ac | |||
32141d457f | |||
03f0a6fd7a | |||
fc4fc87798 | |||
![]() |
a07dbf4ab3 | ||
4b6e82120d | |||
b2f0c47449 | |||
389a979f4c | |||
3c958c917b | |||
4a3f8c669d | |||
317cc3056e | |||
c3b42e09f2 | |||
![]() |
d304e46ceb | ||
![]() |
fe144e6de7 | ||
669255461b | |||
c93fa6c574 | |||
![]() |
86f6d47f10 | ||
831ed6c64c | |||
c7ce943fc0 | |||
0c5c923b06 | |||
74a26affa7 | |||
![]() |
bef932345c | ||
![]() |
468443e062 | ||
e26df01729 | |||
512f14ed4d | |||
![]() |
53032a49d8 | ||
![]() |
8f2aa72f6d | ||
![]() |
ed5e7a1d9f | ||
![]() |
96bc21a727 | ||
![]() |
659ad62b52 | ||
92cb8ec206 | |||
dee1b2bb2c | |||
![]() |
dd49c0e1ba | ||
![]() |
dd5d8886ee | ||
192ae6912f | |||
bbb85b3f6a | |||
b11429eaea | |||
a3526419a9 | |||
![]() |
61e71efcc4 | ||
e04c116b80 | |||
9ff223428b | |||
b8fc56773c | |||
ee1db52114 | |||
7e99466166 | |||
fbcfe7e93f | |||
ce4ee94fed | |||
93fa8c6f2e | |||
5b698cce42 | |||
0f5b2b128f | |||
951185c1d3 | |||
254e7949ef | |||
1521b9d192 | |||
397aacf899 | |||
b8a9d67cc2 | |||
cd9aa73a34 | |||
99161d016d | |||
c97a841041 | |||
c8023244bd | |||
![]() |
cfdbcc8ee1 | ||
1dd51afb11 | |||
e7a7dad50c | |||
ea46d09e53 | |||
27b38e6b4d | |||
84eecdae18 | |||
d63b5286a4 | |||
c0fa59a504 | |||
6e1b1ef4e8 | |||
9868bff329 | |||
a70d32a4ad | |||
bec500d61a | |||
2913ea27ab | |||
![]() |
e42b6abec5 | ||
c6ff17050b | |||
3dc6cdd7ed | |||
8c9dbb5143 | |||
![]() |
32dc97e1c4 | ||
![]() |
01f3537cef | ||
![]() |
d5cf81c32a | ||
6742ecdb8b | |||
d66effcd46 | |||
c8516d6eda | |||
13c8c29bb0 | |||
2b1c5e4e6e | |||
db16df391b | |||
4f7b64fae2 | |||
![]() |
e0eb12cf9e | ||
52ac8364eb | |||
6f49ab3cfa | |||
648084d1f9 | |||
cac034149f | |||
![]() |
fdbbc9c242 | ||
![]() |
04c3c6257c | ||
50bdb19e14 | |||
ec0174dcdd | |||
02fe280d4a | |||
fa688ec8f3 | |||
a6a57de3cf | |||
![]() |
f6cb669277 | ||
![]() |
65cd15ecbb | ||
![]() |
0956b0780a | ||
3dab396450 | |||
fad2a1bc47 | |||
4623adb249 | |||
![]() |
efe1b4bb5a | ||
![]() |
ff996c2924 | ||
![]() |
6994db438b | ||
![]() |
e6b8998edd | ||
![]() |
3a1aade3a2 | ||
![]() |
af6628367f | ||
a666a3fea4 | |||
0c7a411c1f | |||
87a209bf2a | |||
d9756d5f60 | |||
39da362586 | |||
57b7c6372d | |||
f96c24a474 | |||
c76fcb363a | |||
246f63d6e0 | |||
0e0bd76f28 | |||
72b72899fd | |||
![]() |
5977f472c7 | ||
![]() |
3c3047b548 | ||
ea7075f707 | |||
e10a8e0b6d | |||
3110eb92a5 | |||
09e2df75ce | |||
f2764a26f3 | |||
0b835ef9d4 | |||
5dedba2937 | |||
932ea700f3 | |||
98ac3f63bf | |||
abcfa996bd | |||
1f16f194f7 | |||
abdd2d65dd | |||
d14b6bb799 | |||
9bb0bcf3ca | |||
bebc120e8f | |||
58f05724e1 | |||
5690dc297e | |||
![]() |
485c4180da | ||
3b6e238323 | |||
![]() |
c2ad4c560d | ||
![]() |
4d97e21e96 | ||
![]() |
4378c05e3e | ||
![]() |
332e5e88d5 | ||
9a3f51ca6b | |||
711693c57b | |||
2393c76d63 | |||
0e99cf286f | |||
1200d77dbc | |||
2e06960f51 | |||
1b521049af | |||
baf08c4f04 | |||
52904575b0 | |||
5178d95a44 | |||
![]() |
4a0e8e61be | ||
![]() |
91cf18fa9e | ||
f9b0395be7 | |||
f86e6b6838 | |||
28e928a9f5 | |||
79fea4074e | |||
728de9be06 | |||
7b5db01377 | |||
![]() |
430430b460 | ||
![]() |
9fefbd4bba | ||
![]() |
fcd1320b45 | ||
![]() |
d8554ad70d | ||
e325d41f76 | |||
ad45b0a23b | |||
![]() |
1bfe8cee5e | ||
![]() |
55ffdf8941 | ||
062653e708 | |||
![]() |
4853a47899 | ||
![]() |
4549a91e06 | ||
![]() |
fc6f29bbf1 | ||
![]() |
61bb9786b3 | ||
![]() |
1b34c2dbc4 | ||
![]() |
fef51e2a75 | ||
![]() |
41c2ed0dee | ||
0d17b45011 | |||
![]() |
d186575712 | ||
![]() |
9c92ca6575 | ||
![]() |
5e26ac5e69 | ||
![]() |
dfede45535 | ||
d15a8f3880 | |||
c17afece9d | |||
4f773dbfe3 | |||
0dc0b1160e | |||
c0e065ad30 | |||
![]() |
d468108188 | ||
![]() |
6b306f0849 | ||
![]() |
66ce7d209d | ||
![]() |
5985c4940f | ||
![]() |
df9e473686 | ||
![]() |
5c97735948 | ||
![]() |
dfc1267119 | ||
![]() |
e612899dc2 | ||
![]() |
25fcddfba8 | ||
![]() |
6ee9c4e380 | ||
![]() |
2ffd3bf445 | ||
![]() |
bac44b41f8 | ||
![]() |
50eaaf9eb7 | ||
![]() |
a184871bf9 | ||
![]() |
3fcc03b769 | ||
![]() |
b1e6448c3c | ||
![]() |
34e751fd69 | ||
![]() |
1615e92159 | ||
![]() |
a390ef0329 | ||
![]() |
e4c2eda955 | ||
![]() |
5963089539 | ||
![]() |
28760e2c4d | ||
![]() |
e36410ee82 | ||
![]() |
ac9cb53185 | ||
![]() |
346079cee3 | ||
![]() |
d086501095 | ||
![]() |
1a56ba02f3 | ||
![]() |
31834b7f8a | ||
![]() |
4fd3a0c4f5 | ||
30853ecd77 | |||
38192db1de | |||
577860985a | |||
8cc1cf4d5b | |||
![]() |
914ec732af | ||
![]() |
e1be20c08b | ||
315dc97635 | |||
![]() |
e810d01b0e | ||
![]() |
7c90c1ef5e | ||
![]() |
5abd93d27f | ||
![]() |
5cfadf9236 | ||
![]() |
0458abb419 | ||
![]() |
f6d939fc31 | ||
![]() |
2a81dbe09d | ||
8c1f042ea0 | |||
2c9d283a64 | |||
b6ebb1eb5e | |||
23dde1263a | |||
17f2e22f5c | |||
![]() |
323477dbf2 | ||
![]() |
d80babfd73 | ||
![]() |
c08e6c87f5 | ||
![]() |
a9e7cd7af2 | ||
![]() |
2c9c1dc8e1 | ||
376cc0d7e5 | |||
c3728750f7 | |||
39c37c0c73 | |||
![]() |
4f7c4057ea | ||
9ee7ac78c4 | |||
e856859ffb | |||
f8667b8247 | |||
![]() |
657e73f2f0 | ||
![]() |
8b36e79f04 | ||
![]() |
9f78963e7f | ||
a8160214cb | |||
7e60791c33 | |||
![]() |
75f388ddfb | ||
![]() |
e3ebb925e1 | ||
32768aab10 | |||
f12c4ccb7a | |||
100e16030a | |||
3d1b2794e9 | |||
6eaa174d87 | |||
81ef3a8f53 | |||
313ee120ae | |||
51710892df | |||
046a6be790 | |||
58d6334ba5 | |||
a03c9a3369 | |||
009cd49f37 | |||
9daeeedda3 | |||
4b03a2d23c | |||
24bc671c21 | |||
3476198c27 | |||
7334fc5cc5 | |||
587d1b4714 | |||
c8cf67f920 | |||
e8e5cdc75f | |||
41971e8080 | |||
122bfc7436 | |||
6ca79ac342 | |||
694aa4d3d3 | |||
2882abd894 | |||
4aa67d6151 | |||
c04eb0eaa7 | |||
9bccb9d17d | |||
8d8cd9ed18 | |||
66447063a9 | |||
![]() |
81a8081c8e | ||
6e06f77239 | |||
e6842af2a8 | |||
d582c43de5 | |||
![]() |
176e601ec2 | ||
f5c260d79c | |||
ffab712aec | |||
ad1b0e238c | |||
8dceaec349 | |||
![]() |
f172a1e3ee | ||
![]() |
cb922ddd67 | ||
![]() |
da0cf2e4cc | ||
![]() |
e3318732be | ||
![]() |
907710f40b | ||
![]() |
1a4a88846e | ||
![]() |
c2d442ba39 | ||
![]() |
08f648345e | ||
![]() |
442d2a20f4 | ||
ef0f07d389 | |||
f68e452827 | |||
a01e58dc68 | |||
d013cc6844 | |||
b06642e4ba | |||
61f7f83641 | |||
f927303248 | |||
6b3cba10bb | |||
f720bf15e0 | |||
7608982c29 | |||
c2a38ece60 | |||
9e05e0dc0f | |||
e30ae81854 | |||
862ee994dc | |||
7d2d54d86e | |||
62186d638f | |||
fb959da242 | |||
ab5ccfce50 | |||
e3734b48df | |||
417f786bef | |||
353363af8d | |||
3dcaeee12c | |||
e9973ffff0 | |||
1f12f5c7ec | |||
32ac5188a6 | |||
f1d5beb5ab | |||
c7332119ac | |||
e442a87421 | |||
623124e833 | |||
0e92526a8a | |||
f54469e7af | |||
82024ad982 | |||
0d7ec1d90a | |||
af4b802354 | |||
e461fcaf78 | |||
b9875b5a1a | |||
d0a6e35298 | |||
96fb5dd16f | |||
750d02f2a7 | |||
0069382f51 | |||
320f7dac63 | |||
8d379d6dad | |||
00315ea288 | |||
382b482777 | |||
a4ef28465f | |||
894ba3128d | |||
34a82fc22f | |||
1ed7162cfe | |||
eed3ed4dd0 | |||
ba7e3409a2 | |||
79d9636c28 | |||
05047d547a | |||
261f2447e3 | |||
87e51ac744 | |||
d9912671ff | |||
e33a80b16d | |||
342c791700 | |||
ebe3bd8eda | |||
07b163389d | |||
6cda3f0a27 | |||
8c03c2e1d3 | |||
37f7619972 | |||
c6ad41606a | |||
f188442666 | |||
f5ac7e3aa5 | |||
4d9623d83e | |||
c19d7adf0a | |||
75f7d17f95 | |||
1ca9dfda63 | |||
571c875771 | |||
6346f0ec4a | |||
f28382eed9 | |||
c5a145070b | |||
20a11358eb | |||
550bf9811f | |||
6b64bcadfe | |||
dce5178fc2 | |||
fd3df6c344 | |||
7ccaf87dfc | |||
d7ef2e8044 | |||
![]() |
b80e73efb9 | ||
bd6838ba62 | |||
769a6d2dee | |||
6dcd53b68f | |||
8ad3c761be | |||
9975bbd2b0 | |||
c33896afec | |||
1e2ab81bce | |||
a263f82673 | |||
5ff32f1475 | |||
4dfe3bef7b | |||
e643174f5f | |||
57e1f22e9d | |||
3663e04452 | |||
54f16f358f | |||
5d7237b83f | |||
b7d61ee7c7 | |||
1a3e8aa242 | |||
ce3b535b01 | |||
72246867de | |||
![]() |
9bc7588980 | ||
20962cfdb4 | |||
d632b82e1d | |||
bf1e187d91 | |||
7d54198ce8 | |||
e282778623 | |||
![]() |
cf4cf31c75 | ||
35e77e69f8 | |||
7956a88568 | |||
87e2833a89 | |||
7f1d406242 | |||
a4270f775b | |||
5f5ad7029b | |||
ead67e4a82 | |||
e470aaedaa | |||
![]() |
a8af72df1d | ||
9a8bb26997 | |||
a15ba2e9b2 | |||
5881a9d506 | |||
5113a7adab | |||
cbf17f7709 | |||
5d61190695 | |||
ea582b6e14 | |||
6b3fb8f19c | |||
39c9eea11c | |||
3789836291 | |||
934a29a336 | |||
24da75c1f0 | |||
![]() |
31bf621b59 | ||
2259ebe434 | |||
![]() |
62b5e98812 | ||
28a39f0b8e | |||
![]() |
a7005be5ed | ||
c3f64ab1bf | |||
653bd98d1b | |||
b750a352dd | |||
f5d9d469ab | |||
![]() |
be1a0fc56a | ||
![]() |
d4717bb1d2 | ||
![]() |
f3077d4f6e | ||
![]() |
04975f4a8c | ||
c2b53f5cc5 | |||
![]() |
359613463f | ||
e6145b090a | |||
![]() |
57659aa16a | ||
![]() |
b6327b03d2 | ||
bc07d195bf | |||
![]() |
42d5ddc6fb | ||
f15dcf2f41 | |||
![]() |
882f8e2228 | ||
aaef35aaea | |||
0b28c09ef7 | |||
75ed3f0b1a | |||
0c6bae237f | |||
e5c80142c5 | |||
dfa665fe9e | |||
6ef3f5470c | |||
f43b0b4da7 | |||
2766bee5e7 | |||
c3963bcca1 | |||
f23d4f8483 | |||
62283df954 | |||
3a6518c92a | |||
c4e9a5d617 | |||
d68e2c58ae | |||
98d535a076 | |||
c0dadb0c2f | |||
cc1cff3bca | |||
![]() |
f2365ed930 | ||
9cee7f2c4d | |||
50db952581 | |||
e6427389c6 | |||
628cefa7b8 | |||
![]() |
4d234d9447 | ||
![]() |
ea3b1a7791 | ||
![]() |
e3fb3be0d7 | ||
![]() |
5a6a2eee93 | ||
![]() |
d60d2eee6e | ||
![]() |
62adb24a5f | ||
![]() |
bb58f29c86 | ||
![]() |
db6bd73563 | ||
453bc5da9e | |||
7f768ed197 | |||
fe55f94aec | |||
29d6fe385c | |||
![]() |
ac1dded4cc | ||
9f4be74e7e | |||
87bc673ee0 | |||
abc479b549 | |||
9cb5c8ca59 | |||
c75ab09ff2 | |||
7e48ce8c19 | |||
f3a4abb4fd | |||
f9aad67cda | |||
103691121e | |||
038e6b0950 | |||
905b51b4c0 | |||
e10944f7d8 | |||
fb6a7b59ab | |||
bc252aef03 | |||
4692ac36b7 | |||
b7908106ed | |||
7de5e06874 | |||
474ef989a9 | |||
c9fa4607a7 | |||
56f46d3d6f | |||
![]() |
1cd5310a32 | ||
![]() |
7950d3cd9d | ||
![]() |
9f30746e35 | ||
![]() |
4f55b408e7 | ||
![]() |
a0c511fca8 | ||
![]() |
0cd2e63b82 | ||
![]() |
6162d0d671 | ||
![]() |
7d795a1fe1 | ||
![]() |
1bdbacb6d2 | ||
![]() |
1254fa4ad7 | ||
![]() |
db6663d6f3 | ||
52c773a98f | |||
906e1bacd6 | |||
405b2ca147 | |||
ded971a590 | |||
9d1346ef3b | |||
b84fc5cd64 | |||
001e6eb7c3 | |||
bfc98e32f9 | |||
![]() |
4b4568160f | ||
217d6e9398 | |||
4705ac8397 | |||
ea5ff61438 | |||
a058229649 | |||
3e63e1c768 | |||
![]() |
5da1fe6db4 | ||
![]() |
bac96ca2be | ||
![]() |
ed565018a6 | ||
![]() |
a015520e41 | ||
1012f9b3c5 | |||
e42faa4ce8 | |||
26854d6fe2 | |||
bea7399fe2 | |||
f5570bdf6b | |||
0271b087b1 | |||
21817389eb | |||
2bcbf34d8e | |||
74a2fdceec | |||
50910817cb | |||
adc0c68977 | |||
![]() |
e90cc4e6b3 | ||
d9dbbbbbff | |||
50e887f3ce | |||
42a144abe4 | |||
ee40db6e25 | |||
c0f5f68b8a | |||
33ce4a5db5 | |||
f777252a96 | |||
0dba75203e | |||
843025d635 | |||
![]() |
93966ca2a9 | ||
![]() |
3f3f6ebb0f | ||
![]() |
72860fab5d | ||
14f2d15e20 | |||
643938ac69 | |||
0d5e016af7 | |||
d03911199f | |||
e02e5e937b | |||
![]() |
d2c782b075 | ||
348ee4da0d | |||
dd5ded0936 | |||
27776130e0 | |||
137ad8863c | |||
4009aedff0 | |||
970352322c | |||
babfd9c25d | |||
b6d22d2a3b | |||
![]() |
b230953173 | ||
![]() |
ee04a25a52 | ||
![]() |
a341eba928 | ||
![]() |
d0a7caa032 | ||
![]() |
abf493afe8 | ||
![]() |
c37f9fbab4 | ||
![]() |
60d63d6149 | ||
![]() |
5a98bc61ac | ||
![]() |
0f381a7529 | ||
![]() |
5e07412d92 | ||
![]() |
3b27b87e35 | ||
![]() |
843c00dd60 | ||
![]() |
223c4054f6 | ||
![]() |
542ae6b7ef | ||
![]() |
cbed53c65f | ||
7954d6d59f | |||
543265c7af | |||
1b3a04be14 | |||
0cd1c3ef1a | |||
61b6f4bfd9 | |||
ef68d3fb75 | |||
![]() |
4028ceb5b9 | ||
![]() |
0df3cb8509 | ||
![]() |
b42d18f0a4 | ||
![]() |
a11d7d011c | ||
![]() |
1d19f48ac7 | ||
![]() |
c9f0d60e7c | ||
![]() |
a0edc1e0a1 |
758 changed files with 69130 additions and 107030 deletions
24
.editorconfig
Normal file
24
.editorconfig
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Univerzální popis našich konvencí pro nastavení editorů.
|
||||||
|
# Vizte https://editorconfig.org pro detaily
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
# Unixové řádky
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{py,css}]
|
||||||
|
indent_style = tab
|
||||||
|
# Nenařizujeme konkrétní šířku tabulátoru
|
||||||
|
indent_size = unset
|
||||||
|
|
||||||
|
# Automaticky generované migrace dodržují PEP-8, nemá smysl s tím moc bojovat.
|
||||||
|
[*/migrations/*.py]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.html]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -31,5 +31,15 @@ TODO
|
||||||
# reversion kvůli historii objektů v reversion
|
# reversion kvůli historii objektů v reversion
|
||||||
**/reversion
|
**/reversion
|
||||||
|
|
||||||
|
# dokumentace
|
||||||
|
docs/_build
|
||||||
|
docs/modules
|
||||||
|
|
||||||
|
# logy týracího skriptu (./checklinks.sh)
|
||||||
|
/wget.log.*
|
||||||
|
|
||||||
# pro lidi, co programují v nástrojích od JetBrains
|
# pro lidi, co programují v nástrojích od JetBrains
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
# Mac users
|
||||||
|
.DS_Store
|
||||||
|
|
166
Makefile
166
Makefile
|
@ -1,161 +1,9 @@
|
||||||
PYTHON ?= python3
|
# Existence tohohle Makefile je tu jen proto, aby fungovala svalová paměť. Pokud můžete, použijte rovnou `make/…`
|
||||||
VENV ?= ${PYTHON} -m venv
|
%:
|
||||||
# Všechny flagy, které se s venvem/virtualenvem/... mají volat patří sem. Volá se "${VENV} cesta"
|
# Používání make jako příkazu je zastaralé, prosím používej radši skripty ze složky make. Spouštím následující příkaz:
|
||||||
VENV_PATH ?= env
|
make/$*
|
||||||
# Musí být definovaná, i kdyby to měla být "."
|
|
||||||
|
|
||||||
.PHONY: all venv_check clean install install_web install_venv clean_venv clean_schema run test deploy_test deploy_prod sync_test_media sync_test_db sync_test sync_local_media sync_local_db sync_local
|
default:
|
||||||
|
@cat make/README.md
|
||||||
|
|
||||||
# activate by mělo být předpokladem ke všemu, co volá webový python (i.e. python nasazený do ${VENV}u kvůli webu, např. manage.py)
|
.PHONY: default
|
||||||
all:
|
|
||||||
@# Just echo:
|
|
||||||
# Install je trochu magický:
|
|
||||||
# Spusť následující posloupnost příkazů:
|
|
||||||
# make install_venv
|
|
||||||
# . ${VENV_PATH}/bin/activate
|
|
||||||
# make install_web
|
|
||||||
#
|
|
||||||
# Pokud install_web říká Error: pg_config executable not found. nainstaluj si libpq-dev
|
|
||||||
# Pokud chybová hláška obsahuje #include <Python.h>, nainstaluj si python3-dev
|
|
||||||
#
|
|
||||||
# Až skončíš s vývojem webu, spusť "deactivate". Tím zmizí '(${VENV_PATH})' ze začátku promptu.
|
|
||||||
|
|
||||||
venv_check:
|
|
||||||
@# Pokud org nemá zapnutý venv, poradíme mu, aby si ho zapnul a spadneme. Jinak nic.
|
|
||||||
@expr $$PATH : ".*:*$(shell pwd)/${VENV_PATH}/bin" > /dev/null && exit 0 || echo 'Není zapnutý venv, spusť ". ${VENV_PATH}/bin/activate".\nPokud není venv nainstalovaný, spusť "make install_venv"' && false
|
|
||||||
|
|
||||||
clean: clean_venv clean_schema
|
|
||||||
|
|
||||||
install: install_web
|
|
||||||
|
|
||||||
install_web: venv_check
|
|
||||||
@# venv může být příšerně starý, takže nejdříve upgradujeme venvové věci
|
|
||||||
pip install --upgrade pip
|
|
||||||
pip install --upgrade setuptools
|
|
||||||
# Instalace závislostí webu
|
|
||||||
pip install -r requirements.txt --upgrade
|
|
||||||
# Po vygenerování testdat spusť ./manage.py loaddata data/*, ať máš menu a další modely
|
|
||||||
# Pro synchronizaci flatpages spusť make sync_prod_flatpages
|
|
||||||
|
|
||||||
install_venv:
|
|
||||||
${VENV} ${VENV_PATH}
|
|
||||||
|
|
||||||
clean_venv:
|
|
||||||
# Možná není 100% foolproof...
|
|
||||||
@test ! ${VENV_PATH} = . || ! echo "Smaž si prosím venv sám, nebudu mazat celý web"
|
|
||||||
rm -rfv ${VENV_PATH}
|
|
||||||
rm -f pip-selfcheck.json
|
|
||||||
clean_schema:
|
|
||||||
rm -f schema_seminar.pdf schema_all.pdf
|
|
||||||
|
|
||||||
run: venv_check
|
|
||||||
./manage.py runserver
|
|
||||||
|
|
||||||
test: venv_check
|
|
||||||
./manage.py test -v2 seminar mamweb
|
|
||||||
|
|
||||||
# DB schemata
|
|
||||||
|
|
||||||
schema: schema_seminar.pdf schema_all.pdf
|
|
||||||
|
|
||||||
schema_seminar.pdf: venv_check
|
|
||||||
./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf
|
|
||||||
|
|
||||||
schema_all.pdf: venv_check
|
|
||||||
./manage.py graph_models -a -g | dot -Tpdf > schema_all.pdf
|
|
||||||
|
|
||||||
# Deploy to current *mamweb-test* directory
|
|
||||||
deploy_test: venv_check
|
|
||||||
@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi
|
|
||||||
@if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in directory mamweb-test"; exit 1; fi
|
|
||||||
@echo "Installing version from origin/test ..."
|
|
||||||
git pull origin test
|
|
||||||
git clean -f
|
|
||||||
make install
|
|
||||||
./manage.py migrate
|
|
||||||
./manage.py collectstatic --noinput
|
|
||||||
(chown -R :mam . || true )
|
|
||||||
(chmod -R g+rX,go-w . || true )
|
|
||||||
@echo Restarting systemd unit
|
|
||||||
systemctl --user restart mamweb-test.service
|
|
||||||
@echo Done.
|
|
||||||
|
|
||||||
# Deploy to current *mamweb-prod* directory
|
|
||||||
deploy_prod: venv_check
|
|
||||||
@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi
|
|
||||||
@if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-prod" ]; then echo "Only possible in directory mamweb-prod"; exit 1; fi
|
|
||||||
@echo "Backing up production DB ..."
|
|
||||||
( cd -P .. && ./backup_prod_db.sh )
|
|
||||||
@echo "Installing version from origin/master ..."
|
|
||||||
git pull origin master
|
|
||||||
git clean -f
|
|
||||||
make install
|
|
||||||
./manage.py migrate
|
|
||||||
./manage.py collectstatic --noinput
|
|
||||||
(chown -R :mam . || true )
|
|
||||||
(chmod -R g+rX,go-w . || true )
|
|
||||||
@echo Restarting systemd user unit for MaM web
|
|
||||||
systemctl --user restart mamweb-prod.service
|
|
||||||
@echo Done.
|
|
||||||
|
|
||||||
|
|
||||||
sync_prod_flatpages: venv_check
|
|
||||||
@echo Downloading current version of flatpages from mamweb-prod.
|
|
||||||
ssh mam-web@gimli.ms.mff.cuni.cz \
|
|
||||||
"cd /akce/mam/www/mamweb-prod; ./manage.py dumpdata flatpages --indent=2 > flat.json"
|
|
||||||
rsync -ave ssh mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/flat.json ./flat.json
|
|
||||||
@echo "Applying downloaded flatpages."
|
|
||||||
./manage.py loaddata flat.json
|
|
||||||
@echo "Done."
|
|
||||||
|
|
||||||
# Sync test media directory with production
|
|
||||||
sync_test_media:
|
|
||||||
@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi
|
|
||||||
@if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/mamweb-test"; exit 1; fi
|
|
||||||
rsync -av --delete /akce/mam/www/mamweb-prod/media/ ./media
|
|
||||||
|
|
||||||
# Sync test database with production database
|
|
||||||
sync_test_db:
|
|
||||||
@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi
|
|
||||||
pg_dump mam_test > dump-test-`date +"%Y%m%d_%H%M"`.sql
|
|
||||||
pg_dump -Fc mam_prod > dump-prod.sql
|
|
||||||
pg_restore -c --if-exists -d mam_test dump-prod.sql
|
|
||||||
rm dump-prod.sql
|
|
||||||
@echo Done.
|
|
||||||
|
|
||||||
# Aggresive variant: destroy original mam_test db with 'DROP OWNED BY "mam-web";'
|
|
||||||
sync_test_db_aggressive:
|
|
||||||
@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi
|
|
||||||
pg_dump mam_test > dump-test-`date +"%Y%m%d_%H%M"`.sql
|
|
||||||
pg_dump -Fc mam_prod > dump-prod.sql
|
|
||||||
@# I am not sure which shell is used, so I am calling bash to make sure
|
|
||||||
bash -c "psql mam_test <<< 'DROP OWNED BY \"mam-web\";'"
|
|
||||||
pg_restore -c --if-exists -d mam_test dump-prod.sql
|
|
||||||
rm dump-prod.sql
|
|
||||||
@echo Done.
|
|
||||||
|
|
||||||
# Sync test with production
|
|
||||||
# HACK ALERT: using aggressive variant, due to the schemas being too different.
|
|
||||||
sync_test: sync_test_media sync_test_db_aggressive
|
|
||||||
|
|
||||||
|
|
||||||
# Sync media directory with atrey. Useful for local development with production database
|
|
||||||
# Does not sync Galerie and CACHE (too huge).
|
|
||||||
sync_local_media:
|
|
||||||
rsync -ave ssh --exclude Galerie --exclude CACHE\
|
|
||||||
mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/media/ ./media/
|
|
||||||
# Downloads and restores production database to local database. PostgreSQL only.
|
|
||||||
sync_local_db:
|
|
||||||
scp mam-web@gimli.ms.mff.cuni.cz:`ssh mam-web@gimli.ms.mff.cuni.cz 'ls -v /akce/mam/www/backups/mam_prod-*\.pgdump.xz | tail -n 1'` \
|
|
||||||
./last.pgdump.xz
|
|
||||||
xz -fd last.pgdump.xz
|
|
||||||
pg_restore -c -d mam-prod last.pgdump
|
|
||||||
|
|
||||||
# Sync database and media. See above lines
|
|
||||||
sync_local: sync_local_media sync_local_db
|
|
||||||
|
|
||||||
# Push local compiled Vue to gimli test site
|
|
||||||
push_compiled_vue_to_test:
|
|
||||||
scp vue_frontend/webpack-stats.json mam-web@gimli:/akce/mam/www/mamweb-test/vue_frontend/
|
|
||||||
rsync -ave ssh seminar/static/seminar/vue mam-web@gimli:/akce/mam/www/mamweb-test/seminar/static/seminar/
|
|
||||||
ssh mam-web@gimli.ms.mff.cuni.cz 'cd /akce/mam/www/mamweb-test/ && . env/bin/activate && ./manage.py collectstatic --noinput'
|
|
||||||
|
|
112
README.md
112
README.md
|
@ -1,74 +1,58 @@
|
||||||
Basic commands for web development
|
Web M&M
|
||||||
==================================
|
======
|
||||||
|
|
||||||
After you clone this repository, run `make`. It will download, locally install
|
Tohle je repozitář s kódem M&Mího webu. Pokud zde hledáte web samotný nebo
|
||||||
and setup virtualenv and pip, and then locally install all required packages
|
informace o semináři, najdete je na <https://mam.matfyz.cz> (a upřímně nechápu,
|
||||||
from `requirements.txt`.
|
jak jste se dostali k tomuhle textu :-D)
|
||||||
|
|
||||||
When working with the code, always use the binaries in `./bin/`, such as
|
Pokud jste tu zůstali, tak vás beztak zajímá vývoj webu (a jestli ne, tak
|
||||||
`bin/pip`, `bin/python`, ... never the global python, pip, ...
|
budeme rádi, když začne :-)).
|
||||||
Use `make` and `./manage.py` for most things.
|
|
||||||
|
|
||||||
Use git :-)
|
Co je M&Mweb uvnitř
|
||||||
|
------
|
||||||
|
Celý náš web je napsaný v [Pythonu](https://www.python.org) ve frameworku
|
||||||
|
[Django](https://www.djangoproject.com/). Web běží na serveru zvaném Gimli,
|
||||||
|
jako databázi používá PostgreSQL (pro lokální vývoj naopak SQLite) a všechen
|
||||||
|
náš kód je uložený v [Gitu](https://git-scm.com/) na [téhle
|
||||||
|
gitee](https://gitea.ks.matfyz.cz/). Pro dokumentaci používáme
|
||||||
|
[Sphinx](https://www.sphinx-doc.org).
|
||||||
|
|
||||||
Quickstart
|
<!--TODO: Z odstavce výše by ideálně měla být zachována jen první věta a zbytek
|
||||||
----------
|
by měl být někde v docs s podrobnějším popisem…-->
|
||||||
Run the following commands:
|
|
||||||
make install_venv
|
|
||||||
. env/bin/activate
|
|
||||||
make install_web
|
|
||||||
|
|
||||||
After finishing development, run "deactivate".
|
Jak si web pořídit
|
||||||
|
------
|
||||||
|
Prosím přečti si podrobnější návod v <docs/vyvoj.rst> (tady by bylo zbytečné
|
||||||
|
ho duplikovat).
|
||||||
|
|
||||||
Make commands
|
Jak web vyvíjet
|
||||||
-------------
|
----
|
||||||
|
<!--TODO: Napsat obšírněji, asi zase do docs/-->
|
||||||
|
|
||||||
* `make install` (or `make`) - locally install and setup virtualpy, install
|
Na webu je mnoho věcí k dělání, některé ani nevyžadují kódění (třeba uhánění
|
||||||
required packages. Ran again installs missing packages. Run after changing
|
orgů, aby si psali medailonky, aktualizace fotek, …), některé se naopak týkají
|
||||||
`requirements.txt`.
|
infrastruktury pod kódem (Gitea, Gimli, …). Je proto těžké mít na to úplně
|
||||||
|
obecný návod, tak tady je zhruba návod na úpravy kódu a pokud se něco z toho
|
||||||
|
nedá aplikovat, tak to prostě zkus nějak udělat jinak, po svém. (Omlouvám se
|
||||||
|
neinformatikům, ale líp to teď nesepíšu :-))
|
||||||
|
|
||||||
* `make clean` - remove local python packages.
|
1. Nejprve si stáhni repozitář a rozběhni si lokální web u sebe (viz <docs/vyvoj.rst>).
|
||||||
|
1. Najdi si problém v Kanboardu (klikni na „Issues“ na Gitee) a/nebo se domluv
|
||||||
* `make veryclean` - remove local packages and virtualpy enviroment and
|
s webaři, na čem bys tak mohl/a pracovat.
|
||||||
binaries.
|
1. Najdi místo, kde se to dá opravit a zkus to tam opravit. Uznávám, že tenhle
|
||||||
|
bod je otravně obecný, pokud tápeš, zkus se zeptat zkušenějších webařů nebo
|
||||||
* `make run` - runs "./manage.py runserver_plus"
|
podívat do dokumentace.
|
||||||
|
1. Vyzkoušej, že ti to lokálně funguje tak, jak má.
|
||||||
* `make push_test` - pushes the last commited version to test location.
|
1. Zvládneš-li a máš-li čas, zkus to i zdokumentovat a/nebo napsat testy (TODO: chybí návod)
|
||||||
Only git-commited changes are pushed! Rest is re-generated from scratch.
|
1. Po dohodě s webaři to vyzkoušej na testwebu
|
||||||
At test server, the media data and database are kept the same.
|
1. Pošli pull-request a případně zkus reagovat na komentáře
|
||||||
Everything else not in .gitignore is deleted/overwritten on the test server.
|
1. Až se změna začlení do hlavní větve (`master`) a nasadí se web na produkci,
|
||||||
|
můžeš mít radost, že se web bude používat lépe Tobě i ostatním orgům :-)
|
||||||
* `make schema` - generates graph of seminar and all schemas as PDF. Supercool!
|
|
||||||
|
|
||||||
* `make sync_prod_flatpages` - downloads and applies static/flat pages from mamweb-prod
|
|
||||||
|
|
||||||
./manage.py commands
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
* `./manage.py migrate` - update the database schema, initialise the database.
|
|
||||||
You need to run this in the beginning.
|
|
||||||
|
|
||||||
* `./manage.py runserver_plus` - run a debugging server for the web. Slightly
|
|
||||||
enhanced compared to `./manage.py runserver`.
|
|
||||||
Open [127.0.0.1:8000](127.0.0.1:8000).
|
|
||||||
|
|
||||||
* `./manage.py testdata` - create pseudo-random seminar data and admin/admin
|
|
||||||
user.
|
|
||||||
|
|
||||||
* `./manage.py test` - run the tests.
|
|
||||||
|
|
||||||
* `./manage.py shell` - run commands, list elemements of database, check syntax
|
|
||||||
by importing files, etc.
|
|
||||||
|
|
||||||
Configurations
|
|
||||||
--------------
|
|
||||||
|
|
||||||
* `mamweb/settings_common.py` contains most configuration options.
|
|
||||||
* `mamweb/settings.py` is used only for local development.
|
|
||||||
* `mamweb/settings_test.py` is used for testing on atrey.
|
|
||||||
* `mamweb/settings_prod.py` is used in production deployment.
|
|
||||||
|
|
||||||
These are automatically switched by `make`.
|
|
||||||
|
|
||||||
|
### Proč pull-requesty?
|
||||||
|
<!--FIXME: Tohle ale už úplně patří do docs a ne sem, jen je zatím nemám prozkoumané…-->
|
||||||
|
|
||||||
|
Účelů pull-requestů je několik. Jednak doufáme, že pomůže webařům se orientovat
|
||||||
|
v kódu, jednak tím umožňujeme dělat experimenty a dávat si zpětnou vazbu. V
|
||||||
|
neposlední řadě pomáhají držet aspoň trochu konzistentní kód, což má pomoci
|
||||||
|
pohodě při programování… (A asi jsem na něco zapomněl :-))
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
git hooks
|
|
||||||
=========
|
|
||||||
|
|
||||||
Kontrola stylu pythoních zdrojáků pomocí flake8. Kontrolujeme jen změny,
|
|
||||||
abychom nenutili lidi dělat nesouvisející úpravy, které by rozbíjely historii
|
|
||||||
(git blame).
|
|
||||||
|
|
||||||
pre-commit
|
|
||||||
----------
|
|
||||||
* kontrola změn před commitnutím
|
|
||||||
* instalace: lokálně zkopírovat do .git/hooks (musí být spustitelný)
|
|
||||||
|
|
||||||
update
|
|
||||||
------
|
|
||||||
* kontrola změn přicházejících s pushem
|
|
||||||
* instalace: na atreyi zkopírovat do /akce/MaM/MaMweb/mamweb.git/hooks
|
|
|
@ -1,30 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# Git hook script to verify what is about to be committed.
|
|
||||||
# Checks that the changes don't introduce new flake8 errors.
|
|
||||||
|
|
||||||
TMPDIFF=`tempfile`
|
|
||||||
FLAKE8="`git rev-parse --show-toplevel`/bin/flake8"
|
|
||||||
|
|
||||||
status=0
|
|
||||||
|
|
||||||
# select only changed python files which are not migrations
|
|
||||||
changed=`git diff --cached --name-only | grep 'py$' | grep -v 'migrations/[0-9]'`
|
|
||||||
if [ -z $changed ] ; then
|
|
||||||
# Nothing to check. Note the exit is necessary -- we would not pass any
|
|
||||||
# paths to git diff below and it would output the diff unfiltered.
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
git diff --unified=1 --cached HEAD -- $changed > $TMPDIFF
|
|
||||||
|
|
||||||
# only do the check when there are some changes to be commited
|
|
||||||
# otherwise flake8 would hang waiting for input
|
|
||||||
if [ -s $TMPDIFF ] ; then
|
|
||||||
cat $TMPDIFF | $FLAKE8 --diff
|
|
||||||
status=$?
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f $TMPDIFF
|
|
||||||
|
|
||||||
exit $status
|
|
|
@ -1,61 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# git update hook to check that pushed changes don't introduce new flake8
|
|
||||||
# errors
|
|
||||||
|
|
||||||
# --- Command line
|
|
||||||
refname="$1"
|
|
||||||
oldrev="$2"
|
|
||||||
newrev="$3"
|
|
||||||
|
|
||||||
# --- Safety check
|
|
||||||
if [ -z "$GIT_DIR" ]; then
|
|
||||||
echo "Don't run this script from the command line." >&2
|
|
||||||
echo " (if you want, you could supply GIT_DIR then run" >&2
|
|
||||||
echo " $0 <ref> <oldrev> <newrev>)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
|
|
||||||
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
TMPDIR=`mktemp -d`
|
|
||||||
TMPDIFF=`tempfile`
|
|
||||||
|
|
||||||
[ $refname != "refs/heads/master" -a $refname != "refs/heads/stable" ] && exit 0
|
|
||||||
|
|
||||||
# select only changed python files which are not migrations
|
|
||||||
changed=`git diff --name-only $oldrev $newrev | grep 'py$' | grep -v 'migrations/[0-9]'`
|
|
||||||
if [ -z $changed ] ; then
|
|
||||||
# Nothing to check. Note the exit is necessary -- we would not pass any
|
|
||||||
# paths to git diff below and it would output the diff unfiltered.
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
git diff --unified=1 $oldrev $newrev -- $changed >${TMPDIFF}
|
|
||||||
|
|
||||||
# there is no working tree in bare git repository, so we recreate it for flake8
|
|
||||||
git archive $newrev | tar -x -C ${TMPDIR}
|
|
||||||
|
|
||||||
cd ${TMPDIR}
|
|
||||||
# report only errors on lines in diff
|
|
||||||
# (if threre was flake8 installed on atrey, we could just call flake8)
|
|
||||||
/akce/MaM/WWW/mamweb-test/bin/flake8 --diff <${TMPDIFF}
|
|
||||||
status=$?
|
|
||||||
if [ $status != 0 ] ; then
|
|
||||||
echo
|
|
||||||
echo -n "Změny, které se snažíte pushnout, obsahují kód v pythonu "
|
|
||||||
echo -n "nevyhovující flake8 (viz výše). Opravte je a zkuste to znovu. "
|
|
||||||
echo -n "Nezapomeňte, že můžete editovat historii (git commit --amend, "
|
|
||||||
echo -n "git rebase -i). Pokud byste chybu příště raději odhalili už při "
|
|
||||||
echo "commitu, zkopírujte si pre-commit hook z _git_hooks do .git/hooks."
|
|
||||||
echo
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -rf ${TMPDIR}
|
|
||||||
rm -f ${TMPDIFF}
|
|
||||||
|
|
||||||
exit $status
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class AesopConfig(AppConfig):
|
class AesopConfig(AppConfig):
|
||||||
name = 'aesop'
|
name = 'aesop'
|
||||||
|
verbose_name = 'Export do AESOPa'
|
||||||
|
|
|
@ -1,81 +1,30 @@
|
||||||
# -*- coding: utf-8 -*-
|
from django.http import HttpResponse
|
||||||
|
from django.utils.encoding import force_str
|
||||||
try:
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.utils.encoding import force_text
|
|
||||||
except:
|
|
||||||
force_text = str
|
|
||||||
|
|
||||||
|
|
||||||
class OvvpFile(object):
|
class OvvpFile:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# { header: value, ... }
|
# { header: value, ... }
|
||||||
self.headers = {}
|
self.headers = {}
|
||||||
# [ 'column-name', ... ]
|
# [ 'column-name', ... ]
|
||||||
self.columns = []
|
self.columns = []
|
||||||
# [ { column: value, ...}, ...]
|
# [ { column: value, ...}, ...]
|
||||||
self.rows = []
|
self.rows = []
|
||||||
|
|
||||||
def to_lines(self):
|
def to_lines(self):
|
||||||
# header
|
# header
|
||||||
for hk in sorted(self.headers.keys()):
|
for hk in sorted(self.headers.keys()):
|
||||||
yield '%s\t%s\n' % (hk, self.headers[hk])
|
yield f'{hk}\t{self.headers[hk]}\n'
|
||||||
yield '\n'
|
yield '\n'
|
||||||
# columns
|
# columns
|
||||||
yield '\t'.join([c for c in self.columns]) + '\n'
|
yield '\t'.join(self.columns) + '\n'
|
||||||
# rows
|
# rows
|
||||||
for r in self.rows:
|
for r in self.rows:
|
||||||
yield '\t'.join([force_text(r[c]) for c in self.columns]) + '\n'
|
yield '\t'.join([force_str(r[c]) for c in self.columns]) + '\n'
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
return ''.join(self.to_lines())
|
return ''.join(self.to_lines())
|
||||||
|
|
||||||
def to_HttpResponse(self):
|
# Pozn: tohle je ta jediná funkce, která se reálně používá…
|
||||||
return HttpResponse(self.to_string(), content_type='text/plain; charset=utf-8')
|
def to_HttpResponse(self):
|
||||||
|
return HttpResponse(self.to_string(), content_type='text/plain; charset=utf-8')
|
||||||
def parse_from(self, source, with_headers=True):
|
|
||||||
"Parse data from file, string or line iterator, overwriting self"
|
|
||||||
if isinstance(source, str) or isinstance(source, unicode):
|
|
||||||
return self.parse_from(source.split('\n'))
|
|
||||||
|
|
||||||
it = iter(source)
|
|
||||||
|
|
||||||
# header
|
|
||||||
self.headers = {}
|
|
||||||
if with_headers:
|
|
||||||
for r in it:
|
|
||||||
if isinstance(r, str):
|
|
||||||
r = r.decode('utf8')
|
|
||||||
assert isinstance(r, unicode)
|
|
||||||
r = r.rstrip('\n')
|
|
||||||
if r == u"":
|
|
||||||
break
|
|
||||||
k, v = r.split(u'\t', 1)
|
|
||||||
self.headers[k] = v
|
|
||||||
|
|
||||||
# columns
|
|
||||||
r = it.next()
|
|
||||||
if isinstance(r, str):
|
|
||||||
r = r.decode('utf8')
|
|
||||||
self.columns = [cn.strip() for cn in r.split(u'\t') if cn.strip() != ""]
|
|
||||||
|
|
||||||
# rows
|
|
||||||
self.rows = []
|
|
||||||
for r in it:
|
|
||||||
if isinstance(r, str):
|
|
||||||
r = r.decode('utf8')
|
|
||||||
r = r.rstrip('\n')
|
|
||||||
if not r:
|
|
||||||
break
|
|
||||||
rtup = r.split(u'\t')
|
|
||||||
rdict = {}
|
|
||||||
for ci in range(len(self.columns)):
|
|
||||||
rdict[self.columns[ci]] = rtup[ci]
|
|
||||||
self.rows.append(rdict)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parse(source, with_headers=True):
|
|
||||||
o = OvvpFile()
|
|
||||||
o.parse_from(source, with_headers=with_headers)
|
|
||||||
return o
|
|
||||||
|
|
|
@ -5,16 +5,16 @@ urlpatterns = [
|
||||||
path(
|
path(
|
||||||
'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
|
'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
|
||||||
views.ExportRocnikView.as_view(),
|
views.ExportRocnikView.as_view(),
|
||||||
name='seminar_export_rocnik'
|
name='aesop_export_rocnik'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
|
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
|
||||||
views.ExportSousView.as_view(),
|
views.ExportSousView.as_view(),
|
||||||
name='seminar_export_sous'
|
name='aesop_export_sous'
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
'aesop-export/index.csv',
|
'aesop-export/index.csv',
|
||||||
views.ExportIndexView.as_view(),
|
views.ExportIndexView.as_view(),
|
||||||
name='seminar_export_index'
|
name='aesop_export_index'
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
|
|
||||||
from aesop.ovvpfile import OvvpFile
|
from aesop.ovvpfile import OvvpFile
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ def default_ovvpfile(event, rocnik):
|
||||||
of = OvvpFile()
|
of = OvvpFile()
|
||||||
of.headers['version'] = '1'
|
of.headers['version'] = '1'
|
||||||
of.headers['event'] = event
|
of.headers['event'] = event
|
||||||
of.headers['year'] = force_text(rocnik.prvni_rok)
|
of.headers['year'] = force_str(rocnik.prvni_rok)
|
||||||
of.headers['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
of.headers['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
of.headers['id-scope'] = 'mam'
|
of.headers['id-scope'] = 'mam'
|
||||||
of.headers['id-generation'] = '1'
|
of.headers['id-generation'] = '1'
|
||||||
|
|
|
@ -3,21 +3,22 @@ from django.shortcuts import get_object_or_404
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_str
|
||||||
|
|
||||||
from .utils import default_ovvpfile
|
from .utils import default_ovvpfile
|
||||||
from seminar.models import Rocnik, Soustredeni
|
from soustredeni.models import Soustredeni
|
||||||
from seminar.views import vysledkovka
|
from tvorba.models import Rocnik
|
||||||
from seminar.utils import aktivniResitele
|
from vysledkovky import utils
|
||||||
|
from tvorba.utils import aktivniResitele
|
||||||
|
|
||||||
class ExportIndexView(generic.View):
|
class ExportIndexView(generic.View):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
ls = []
|
ls = []
|
||||||
for r in Rocnik.objects.filter(exportovat = True):
|
for r in Rocnik.objects.filter(exportovat = True):
|
||||||
url = reverse('seminar_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
url = reverse('aesop_export_rocnik', kwargs={'prvni_rok': r.prvni_rok})
|
||||||
ls.append(url.split('/')[-1])
|
ls.append(url.split('/')[-1])
|
||||||
for s in Soustredeni.objects.filter(exportovat = True):
|
for s in Soustredeni.objects.filter(exportovat = True):
|
||||||
url = reverse('seminar_export_sous', kwargs={'datum_zacatku': s.datum_zacatku.isoformat()})
|
url = reverse('aesop_export_sous', kwargs={'datum_zacatku': s.datum_zacatku.isoformat()})
|
||||||
ls.append(url.split('/')[-1])
|
ls.append(url.split('/')[-1])
|
||||||
|
|
||||||
return HttpResponse('\n'.join(ls) + '\n', content_type='text/plain; charset=utf-8')
|
return HttpResponse('\n'.join(ls) + '\n', content_type='text/plain; charset=utf-8')
|
||||||
|
@ -66,8 +67,8 @@ class ExportRocnikView(generic.View):
|
||||||
rocnik = get_object_or_404(Rocnik, prvni_rok=pr, exportovat=True)
|
rocnik = get_object_or_404(Rocnik, prvni_rok=pr, exportovat=True)
|
||||||
cislo = rocnik.posledni_zverejnena_vysledkovka_cislo()
|
cislo = rocnik.posledni_zverejnena_vysledkovka_cislo()
|
||||||
resitele = aktivniResitele(cislo, True)
|
resitele = aktivniResitele(cislo, True)
|
||||||
slovnik_body = vysledkovka.secti_body_za_rocnik(cislo, resitele, False)
|
slovnik_body = utils.secti_body_za_rocnik(cislo, resitele, False)
|
||||||
setrizeni_resitele, body = vysledkovka.setrid_resitele_a_body(slovnik_body)
|
setrizeni_resitele, body = utils.setrid_resitele_a_body(slovnik_body)
|
||||||
|
|
||||||
of = default_ovvpfile('MaM.rocnik', rocnik)
|
of = default_ovvpfile('MaM.rocnik', rocnik)
|
||||||
of.headers['comment'] = u'MaM-Web export aktivnich resitelu rocniku {rocnik} do cisla {cislo}'.format(rocnik=rocnik, cislo=cislo)
|
of.headers['comment'] = u'MaM-Web export aktivnich resitelu rocniku {rocnik} do cisla {cislo}'.format(rocnik=rocnik, cislo=cislo)
|
||||||
|
|
|
@ -3,3 +3,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
class ApiConfig(AppConfig):
|
class ApiConfig(AppConfig):
|
||||||
name = 'api'
|
name = 'api'
|
||||||
|
verbose_name = 'Různá webová API'
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from django.test import TestCase
|
from django.test import TestCase, tag
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
import seminar.models as m
|
from personalni.models import Skola
|
||||||
import seminar.views as v
|
from personalni.utils import sync_skoly
|
||||||
from seminar.utils import sync_skoly
|
|
||||||
|
|
||||||
|
@tag('stejny-model-na-produkci')
|
||||||
class OrgSkolyAutocompleteTestCase(TestCase):
|
class OrgSkolyAutocompleteTestCase(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
@ -11,19 +11,20 @@ class OrgSkolyAutocompleteTestCase(TestCase):
|
||||||
sync_skoly('https://mam.mff.cuni.cz/')
|
sync_skoly('https://mam.mff.cuni.cz/')
|
||||||
# Správné školy podle toho, co orgové poslali: (prefix, ID školy)
|
# Správné školy podle toho, co orgové poslali: (prefix, ID školy)
|
||||||
# NOTE: Pozor, jedná se o databázové indexy. Pokud se to někdy rozbije, bude potřeba je přepsat nebo předělat na IZO
|
# NOTE: Pozor, jedná se o databázové indexy. Pokud se to někdy rozbije, bude potřeba je přepsat nebo předělat na IZO
|
||||||
|
# TODO: Opravit zakomentované školy.
|
||||||
cls.spravna_data = [
|
cls.spravna_data = [
|
||||||
('gymnázium kolín', 53),
|
('gymnázium kolín', 53),
|
||||||
('kolín', 53),
|
('kolín', 53),
|
||||||
('gasoš', 96),
|
#('gasoš', 96),
|
||||||
('Rokycany', 96),
|
('Rokycany', 96),
|
||||||
('gasoš Rokycany', 96),
|
#('gasoš Rokycany', 96),
|
||||||
('SPŠE Pardubice', 815),
|
#('SPŠE Pardubice', 815),
|
||||||
('Jaroše', 164),
|
('Jaroše', 164),
|
||||||
("Gymnázium, Brno, tř. Kpt. Jaroše", 164),
|
#("Gymnázium, Brno, tř. Kpt. Jaroše", 164),
|
||||||
("Jírovcova", 157),
|
("Jírovcova", 157),
|
||||||
('České Budějovice', 157),
|
('České Budějovice', 157),
|
||||||
("Gymnázium, České Budějovice, Jírovcova 8", 157),
|
("Gymnázium, České Budějovice, Jírovcova 8", 157),
|
||||||
("první soukromé", 2),
|
#("první soukromé", 2),
|
||||||
("Gymnázium Elgartova", 147),
|
("Gymnázium Elgartova", 147),
|
||||||
("Jihlava", 45),
|
("Jihlava", 45),
|
||||||
('Milevsko', 223),
|
('Milevsko', 223),
|
||||||
|
@ -47,7 +48,7 @@ class OrgSkolyAutocompleteTestCase(TestCase):
|
||||||
"""Testuje, že pro každého orga je jeho škola ve výsledném QuerySetu"""
|
"""Testuje, že pro každého orga je jeho škola ve výsledném QuerySetu"""
|
||||||
for pfx, id in self.spravna_data:
|
for pfx, id in self.spravna_data:
|
||||||
with self.subTest(prefix=pfx, spravne_id=id):
|
with self.subTest(prefix=pfx, spravne_id=id):
|
||||||
spravna_skola = m.Skola.objects.get(id=id)
|
spravna_skola = Skola.objects.get(id=id)
|
||||||
# Zeptáme se view, co si myslí
|
# Zeptáme se view, co si myslí
|
||||||
resp = self.client.get(reverse('autocomplete_skola')+'?q='+pfx).json()
|
resp = self.client.get(reverse('autocomplete_skola')+'?q='+pfx).json()
|
||||||
ids = [int(x['id']) for x in resp['results']]
|
ids = [int(x['id']) for x in resp['results']]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from . import views
|
from . import views
|
||||||
from seminar.utils import org_required
|
from personalni.utils import org_required
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# Export škol
|
# Export škol
|
||||||
|
@ -10,10 +10,12 @@ urlpatterns = [
|
||||||
# Autocomplete
|
# Autocomplete
|
||||||
path('api/autocomplete/skola/', views.SkolaAutocomplete.as_view(), name='autocomplete_skola'),
|
path('api/autocomplete/skola/', views.SkolaAutocomplete.as_view(), name='autocomplete_skola'),
|
||||||
path('api/autocomplete/resitel/', org_required(views.ResitelAutocomplete.as_view()), name='autocomplete_resitel'),
|
path('api/autocomplete/resitel/', org_required(views.ResitelAutocomplete.as_view()), name='autocomplete_resitel'),
|
||||||
|
path('api/autocomplete/resitel_public/', views.PublicResitelAutocomplete.as_view(), name='autocomplete_resitel_public'),
|
||||||
path('api/autocomplete/problem/odevzdatelny', views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'),
|
path('api/autocomplete/problem/odevzdatelny', views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'),
|
||||||
|
path('api/autocomplete/problem/vsechny', views.ProblemAutocomplete.as_view(), name='autocomplete_problem'),
|
||||||
|
|
||||||
# Ceka na autocomplete v3
|
# Ceka na autocomplete v3
|
||||||
# path('autocomplete/organizatori/',
|
# path('autocomplete/organizatori/',
|
||||||
# org_member_required(views.OrganizatorAutocomplete.as_view()),
|
# org_member_required(views.OrganizatorAutocomplete.as_view()),
|
||||||
# name='seminar_autocomplete_organizator')
|
# name='autocomplete_organizator')
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,19 +1,27 @@
|
||||||
|
"""
|
||||||
|
Views k :mod:`dal.autocomplete` pro vyhledávání objektů nějaké třídy v databázi.
|
||||||
|
"""
|
||||||
from dal import autocomplete
|
from dal import autocomplete
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
import seminar.models as m
|
from personalni.models import Skola, Resitel
|
||||||
|
from tvorba.models import Problem
|
||||||
|
from various.models import Nastaveni
|
||||||
from .helpers import LoginRequiredAjaxMixin
|
from .helpers import LoginRequiredAjaxMixin
|
||||||
|
|
||||||
# TODO filosofie - zkratky, jak v databázi, tak ve vyhledávání (SPŠE, GASOŠ, Kpt., soukr)
|
# TODO filosofie - zkratky, jak v databázi, tak ve vyhledávání (SPŠE, GASOŠ, Kpt., soukr)
|
||||||
class SkolaAutocomplete(autocomplete.Select2QuerySetView):
|
class SkolaAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
|
""" View k :mod:`dal.autocomplete` pro vyhledávání škol hlavně při registraci. """
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
# Don't forget to filter out results depending on the visitor !
|
# Don't forget to filter out results depending on the visitor !
|
||||||
qs = m.Skola.objects.all()
|
qs = Skola.objects.all()
|
||||||
if self.q:
|
if self.q:
|
||||||
words = self.q.split(' ') #TODO re split podle bileho znaku
|
words = self.q.split(' ') #TODO re split podle bileho znaku
|
||||||
partq = Q()
|
partq = Q()
|
||||||
for w in words: # Hledej po slovech, zahoď čárky a tečky z konců.
|
for w in words: # Hledej po slovech, zahoď čárky a tečky z konců.
|
||||||
|
if len(w) == 0:
|
||||||
|
continue
|
||||||
if w[-1] in (".",","):
|
if w[-1] in (".",","):
|
||||||
w = w[:-1]
|
w = w[:-1]
|
||||||
|
|
||||||
|
@ -23,32 +31,70 @@ class SkolaAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
class ResitelAutocomplete(LoginRequiredAjaxMixin,autocomplete.Select2QuerySetView):
|
class ResitelAutocomplete(LoginRequiredAjaxMixin,autocomplete.Select2QuerySetView):
|
||||||
|
""" View k :mod:`dal.autocomplete` pro vyhledávání řešitelů především v odevzdávátku. """
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = m.Resitel.objects.all()
|
qs = Resitel.objects.all()
|
||||||
if self.q:
|
if self.q:
|
||||||
qs = qs.filter(
|
parts = self.q.split()
|
||||||
Q(osoba__jmeno__istartswith=self.q)|
|
query = Q()
|
||||||
Q(osoba__prijmeni__istartswith=self.q)|
|
for part in parts:
|
||||||
Q(osoba__prezdivka__istartswith=self.q)
|
query &= (
|
||||||
|
Q(osoba__jmeno__istartswith=part)|
|
||||||
|
Q(osoba__prijmeni__istartswith=part)|
|
||||||
|
Q(osoba__prezdivka__istartswith=part)
|
||||||
)
|
)
|
||||||
|
qs = qs.filter(query)
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
class OdevzdatelnyProblemAutocomplete(autocomplete.Select2QuerySetView):
|
|
||||||
|
class PublicResitelAutocomplete(LoginRequiredAjaxMixin, autocomplete.Select2QuerySetView):
|
||||||
|
"""
|
||||||
|
View k :mod:`dal.autocomplete` pro vyhledávání řešitelů podle přezdívky
|
||||||
|
především v odevzdávátku.
|
||||||
|
"""
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
nastaveni = get_object_or_404(m.Nastaveni)
|
letos = Nastaveni.get_solo().aktualni_rocnik
|
||||||
|
qs = Resitel.objects.filter(
|
||||||
|
rok_maturity__gte=letos.druhy_rok()
|
||||||
|
).filter(
|
||||||
|
prezdivka_resitele__isnull=False
|
||||||
|
).exclude(
|
||||||
|
prezdivka_resitele=""
|
||||||
|
).filter(
|
||||||
|
prezdivka_resitele__icontains=self.q
|
||||||
|
).all()
|
||||||
|
return qs
|
||||||
|
|
||||||
|
def get_result_label(self, result):
|
||||||
|
return result.prezdivka_resitele
|
||||||
|
|
||||||
|
|
||||||
|
class OdevzdatelnyProblemAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
|
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
||||||
|
def get_queryset(self):
|
||||||
|
qs = Problem.objects.filter(stav=Problem.STAV_ZADANY)
|
||||||
|
if self.q:
|
||||||
|
qs = qs.filter(
|
||||||
|
Q(nazev__icontains=self.q))
|
||||||
|
|
||||||
|
nadproblem_id = int(self.forwarded.get("nadproblem_id", -1))
|
||||||
|
if nadproblem_id != -1:
|
||||||
|
# Seřadíme tak, aby ty s nadproblem==None byly dole (větší motivace tam naklikat konkrétní úlohy) a pak nějak rozumně.
|
||||||
|
# Tohle je řazení pro odevzdávátko, kde je definován nadproblém, proto je to v tomto ifu. (Jinde si to netroufám řadit)
|
||||||
|
qs = qs.order_by("nadproblem", "kod", "nazev")
|
||||||
|
qs = list(filter(lambda problem: problem.hlavni_problem.id == nadproblem_id, qs))
|
||||||
|
return qs
|
||||||
|
|
||||||
|
class ProblemAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
|
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
||||||
|
def get_queryset(self):
|
||||||
|
# FIXME i starší úlohy
|
||||||
|
nastaveni = get_object_or_404(Nastaveni)
|
||||||
rocnik = nastaveni.aktualni_rocnik
|
rocnik = nastaveni.aktualni_rocnik
|
||||||
# Od tohoto místa dál jsem zkoušel spoustu variací podle https://django-polymorphic.readthedocs.io/en/stable/advanced.html
|
temaQ = Q(Tema___rocnik = rocnik)
|
||||||
temaQ = Q(Tema___rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
ulohaQ = Q(Uloha___cislo_zadani__rocnik=rocnik)
|
||||||
ulohaQ = Q(Uloha___cislo_zadani__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
clanekQ = Q(Clanek___cislo__rocnik=rocnik)
|
||||||
clanekQ = Q(Clanek___cislo__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
qs = Problem.objects.filter(temaQ | ulohaQ | clanekQ).order_by("-stav", "nazev")
|
||||||
qs = m.Problem.objects.filter(temaQ | ulohaQ | clanekQ)
|
|
||||||
#print(temata, ulohy, clanky)
|
|
||||||
#ulohy.union(temata, all=True)
|
|
||||||
#print(ulohy)
|
|
||||||
#ulohy.union(clanky, all=True)
|
|
||||||
#print(ulohy)
|
|
||||||
#qs = ulohy
|
|
||||||
print(qs)
|
|
||||||
if self.q:
|
if self.q:
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
Q(nazev__icontains=self.q))
|
Q(nazev__icontains=self.q))
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import seminar.models as m
|
import personalni.models as m
|
||||||
from django.core import serializers as ser
|
from django.core import serializers as ser
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
def exportSkolView(request):
|
def exportSkolView(request):
|
||||||
|
"""
|
||||||
|
„view“, který vrací json se seznamem škol, u kterých je uvedeno: 'id', 'izo', 'nazev', 'kratky_nazev', 'ulice', 'mesto', 'psc', 'stat', 'je_zs', 'je_ss'
|
||||||
|
"""
|
||||||
# Některé fieldy nechceme: Kontaktní osoby, AESOP ID, org poznámky.
|
# Některé fieldy nechceme: Kontaktní osoby, AESOP ID, org poznámky.
|
||||||
fields = ('id', 'izo', 'nazev', 'kratky_nazev', 'ulice', 'mesto', 'psc', 'stat', 'je_zs', 'je_ss')
|
fields = ('id', 'izo', 'nazev', 'kratky_nazev', 'ulice', 'mesto', 'psc', 'stat', 'je_zs', 'je_ss')
|
||||||
# TODO: Použít JSONL, aby protistrana mohla číst po řádkách a nesežralo to tunu paměti úplně hned
|
# TODO: Použít JSONL, aby protistrana mohla číst po řádkách a nesežralo to tunu paměti úplně hned
|
||||||
|
|
|
@ -2,6 +2,9 @@ from django.http import JsonResponse
|
||||||
|
|
||||||
|
|
||||||
class LoginRequiredAjaxMixin(object):
|
class LoginRequiredAjaxMixin(object):
|
||||||
|
"""
|
||||||
|
Objekt přidávající povinnost být přihlášený k zobrazení daného view.
|
||||||
|
"""
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
#if request.is_ajax() and not request.user.is_authenticated: # Pokud to otevřu jako stránku, tak se omezení neuplatní, takže to asi nechceme
|
#if request.is_ajax() and not request.user.is_authenticated: # Pokud to otevřu jako stránku, tak se omezení neuplatní, takže to asi nechceme
|
||||||
if not request.user.is_authenticated:
|
if not request.user.is_authenticated:
|
||||||
|
|
|
@ -3,8 +3,16 @@
|
||||||
# Props to https://www.commandlinefu.com/commands/view/8234/check-broken-links-using-wget-as-a-spider
|
# Props to https://www.commandlinefu.com/commands/view/8234/check-broken-links-using-wget-as-a-spider
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
|
if test "$#" -lt 1; then
|
||||||
|
echo >&2 "Usage: $0 <wget parameters, especially URL to test>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
logfile="$(pwd)/wget.log.$(date +%FT%T)"
|
logfile="$(pwd)/wget.log.$(date +%FT%T)"
|
||||||
tmp=$(mktemp --directory)
|
tmp=$(mktemp --directory)
|
||||||
cd "$tmp"
|
cd "$tmp"
|
||||||
|
|
||||||
wget --spider -o "$logfile" -r -p -X '/soustredeni/*/fotogalerie/' "$@"
|
wget --spider -o "$logfile" -r -p -X '/soustredeni/*/fotogalerie/' "$@" || true # wget nejspíš skončí s chybou, že něco nestáhl…
|
||||||
|
|
||||||
|
echo "Result: (a last few lines of the file $logfile)"
|
||||||
|
sed -ne '/^Found [0-9]* broken link/,$ p' "$logfile"
|
||||||
|
|
File diff suppressed because one or more lines are too long
655
data/groups.json
Normal file
655
data/groups.json
Normal file
|
@ -0,0 +1,655 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"name": "org",
|
||||||
|
"permissions": [
|
||||||
|
[
|
||||||
|
"org",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_flatpage",
|
||||||
|
"flatpages",
|
||||||
|
"flatpage"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_flatpage",
|
||||||
|
"flatpages",
|
||||||
|
"flatpage"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_flatpage",
|
||||||
|
"flatpages",
|
||||||
|
"flatpage"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_flatpage",
|
||||||
|
"flatpages",
|
||||||
|
"flatpage"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_galerie",
|
||||||
|
"galerie",
|
||||||
|
"galerie"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_galerie",
|
||||||
|
"galerie",
|
||||||
|
"galerie"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_galerie",
|
||||||
|
"galerie",
|
||||||
|
"galerie"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_galerie",
|
||||||
|
"galerie",
|
||||||
|
"galerie"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_obrazek",
|
||||||
|
"galerie",
|
||||||
|
"obrazek"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_obrazek",
|
||||||
|
"galerie",
|
||||||
|
"obrazek"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_obrazek",
|
||||||
|
"galerie",
|
||||||
|
"obrazek"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_obrazek",
|
||||||
|
"galerie",
|
||||||
|
"obrazek"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_fotkaheader",
|
||||||
|
"header_fotky",
|
||||||
|
"fotkaheader"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_fotkaheader",
|
||||||
|
"header_fotky",
|
||||||
|
"fotkaheader"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_fotkaheader",
|
||||||
|
"header_fotky",
|
||||||
|
"fotkaheader"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_fotkaurlvazba",
|
||||||
|
"header_fotky",
|
||||||
|
"fotkaurlvazba"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_fotkaurlvazba",
|
||||||
|
"header_fotky",
|
||||||
|
"fotkaurlvazba"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_fotkaurlvazba",
|
||||||
|
"header_fotky",
|
||||||
|
"fotkaurlvazba"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_komentar",
|
||||||
|
"korektury",
|
||||||
|
"komentar"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_komentar",
|
||||||
|
"korektury",
|
||||||
|
"komentar"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_komentar",
|
||||||
|
"korektury",
|
||||||
|
"komentar"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_komentar",
|
||||||
|
"korektury",
|
||||||
|
"komentar"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_korekturovanepdf",
|
||||||
|
"korektury",
|
||||||
|
"korekturovanepdf"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_korekturovanepdf",
|
||||||
|
"korektury",
|
||||||
|
"korekturovanepdf"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_korekturovanepdf",
|
||||||
|
"korektury",
|
||||||
|
"korekturovanepdf"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_korekturovanepdf",
|
||||||
|
"korektury",
|
||||||
|
"korekturovanepdf"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_oprava",
|
||||||
|
"korektury",
|
||||||
|
"oprava"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_oprava",
|
||||||
|
"korektury",
|
||||||
|
"oprava"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_oprava",
|
||||||
|
"korektury",
|
||||||
|
"oprava"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_oprava",
|
||||||
|
"korektury",
|
||||||
|
"oprava"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_novinky",
|
||||||
|
"novinky",
|
||||||
|
"novinky"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_novinky",
|
||||||
|
"novinky",
|
||||||
|
"novinky"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_novinky",
|
||||||
|
"novinky",
|
||||||
|
"novinky"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_novinky",
|
||||||
|
"novinky",
|
||||||
|
"novinky"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_organizator",
|
||||||
|
"personalni",
|
||||||
|
"organizator"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_organizator",
|
||||||
|
"personalni",
|
||||||
|
"organizator"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_osoba",
|
||||||
|
"personalni",
|
||||||
|
"osoba"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_osoba",
|
||||||
|
"personalni",
|
||||||
|
"osoba"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_prijemce",
|
||||||
|
"personalni",
|
||||||
|
"prijemce"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_prijemce",
|
||||||
|
"personalni",
|
||||||
|
"prijemce"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_prijemce",
|
||||||
|
"personalni",
|
||||||
|
"prijemce"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_prijemce",
|
||||||
|
"personalni",
|
||||||
|
"prijemce"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_resitel",
|
||||||
|
"personalni",
|
||||||
|
"resitel"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_resitel",
|
||||||
|
"personalni",
|
||||||
|
"resitel"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_skola",
|
||||||
|
"personalni",
|
||||||
|
"skola"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_skola",
|
||||||
|
"personalni",
|
||||||
|
"skola"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_skola",
|
||||||
|
"personalni",
|
||||||
|
"skola"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_skola",
|
||||||
|
"personalni",
|
||||||
|
"skola"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_hlasovani",
|
||||||
|
"prednasky",
|
||||||
|
"hlasovani"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_hlasovanioznalostech",
|
||||||
|
"prednasky",
|
||||||
|
"hlasovanioznalostech"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_prednaska",
|
||||||
|
"prednasky",
|
||||||
|
"prednaska"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_prednaska",
|
||||||
|
"prednasky",
|
||||||
|
"prednaska"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_prednaska",
|
||||||
|
"prednasky",
|
||||||
|
"prednaska"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_prednaska",
|
||||||
|
"prednasky",
|
||||||
|
"prednaska"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_seznam",
|
||||||
|
"prednasky",
|
||||||
|
"seznam"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_seznam",
|
||||||
|
"prednasky",
|
||||||
|
"seznam"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_seznam",
|
||||||
|
"prednasky",
|
||||||
|
"seznam"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_seznam",
|
||||||
|
"prednasky",
|
||||||
|
"seznam"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_znalost",
|
||||||
|
"prednasky",
|
||||||
|
"znalost"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_znalost",
|
||||||
|
"prednasky",
|
||||||
|
"znalost"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_znalost",
|
||||||
|
"prednasky",
|
||||||
|
"znalost"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_znalost",
|
||||||
|
"prednasky",
|
||||||
|
"znalost"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_konfera",
|
||||||
|
"soustredeni",
|
||||||
|
"konfera"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_konfera",
|
||||||
|
"soustredeni",
|
||||||
|
"konfera"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_konfera",
|
||||||
|
"soustredeni",
|
||||||
|
"konfera"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_konfera",
|
||||||
|
"soustredeni",
|
||||||
|
"konfera"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_konfery_ucastnici",
|
||||||
|
"soustredeni",
|
||||||
|
"konfery_ucastnici"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_konfery_ucastnici",
|
||||||
|
"soustredeni",
|
||||||
|
"konfery_ucastnici"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_konfery_ucastnici",
|
||||||
|
"soustredeni",
|
||||||
|
"konfery_ucastnici"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_konfery_ucastnici",
|
||||||
|
"soustredeni",
|
||||||
|
"konfery_ucastnici"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_soustredeni",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_soustredeni",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_soustredeni",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_soustredeni",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_soustredeni_organizatori",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni_organizatori"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_soustredeni_organizatori",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni_organizatori"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_soustredeni_organizatori",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni_organizatori"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_soustredeni_organizatori",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni_organizatori"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_soustredeni_ucastnici",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni_ucastnici"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_soustredeni_ucastnici",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni_ucastnici"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_soustredeni_ucastnici",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni_ucastnici"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_soustredeni_ucastnici",
|
||||||
|
"soustredeni",
|
||||||
|
"soustredeni_ucastnici"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_tag",
|
||||||
|
"taggit",
|
||||||
|
"tag"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_tag",
|
||||||
|
"taggit",
|
||||||
|
"tag"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_tag",
|
||||||
|
"taggit",
|
||||||
|
"tag"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_tag",
|
||||||
|
"taggit",
|
||||||
|
"tag"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_taggeditem",
|
||||||
|
"taggit",
|
||||||
|
"taggeditem"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_taggeditem",
|
||||||
|
"taggit",
|
||||||
|
"taggeditem"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_taggeditem",
|
||||||
|
"taggit",
|
||||||
|
"taggeditem"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_taggeditem",
|
||||||
|
"taggit",
|
||||||
|
"taggeditem"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_cislo",
|
||||||
|
"tvorba",
|
||||||
|
"cislo"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_cislo",
|
||||||
|
"tvorba",
|
||||||
|
"cislo"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_cislo",
|
||||||
|
"tvorba",
|
||||||
|
"cislo"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_cislo",
|
||||||
|
"tvorba",
|
||||||
|
"cislo"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_clanek",
|
||||||
|
"tvorba",
|
||||||
|
"clanek"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_clanek",
|
||||||
|
"tvorba",
|
||||||
|
"clanek"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_clanek",
|
||||||
|
"tvorba",
|
||||||
|
"clanek"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_clanek",
|
||||||
|
"tvorba",
|
||||||
|
"clanek"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_deadline",
|
||||||
|
"tvorba",
|
||||||
|
"deadline"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_deadline",
|
||||||
|
"tvorba",
|
||||||
|
"deadline"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_deadline",
|
||||||
|
"tvorba",
|
||||||
|
"deadline"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_pohadka",
|
||||||
|
"tvorba",
|
||||||
|
"pohadka"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_pohadka",
|
||||||
|
"tvorba",
|
||||||
|
"pohadka"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_pohadka",
|
||||||
|
"tvorba",
|
||||||
|
"pohadka"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_pohadka",
|
||||||
|
"tvorba",
|
||||||
|
"pohadka"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_problem",
|
||||||
|
"tvorba",
|
||||||
|
"problem"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_problem",
|
||||||
|
"tvorba",
|
||||||
|
"problem"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_problem",
|
||||||
|
"tvorba",
|
||||||
|
"problem"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_problem",
|
||||||
|
"tvorba",
|
||||||
|
"problem"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_rocnik",
|
||||||
|
"tvorba",
|
||||||
|
"rocnik"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_rocnik",
|
||||||
|
"tvorba",
|
||||||
|
"rocnik"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_rocnik",
|
||||||
|
"tvorba",
|
||||||
|
"rocnik"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_rocnik",
|
||||||
|
"tvorba",
|
||||||
|
"rocnik"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_tema",
|
||||||
|
"tvorba",
|
||||||
|
"tema"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_tema",
|
||||||
|
"tvorba",
|
||||||
|
"tema"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_tema",
|
||||||
|
"tvorba",
|
||||||
|
"tema"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_tema",
|
||||||
|
"tvorba",
|
||||||
|
"tema"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_uloha",
|
||||||
|
"tvorba",
|
||||||
|
"uloha"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_uloha",
|
||||||
|
"tvorba",
|
||||||
|
"uloha"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_uloha",
|
||||||
|
"tvorba",
|
||||||
|
"uloha"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_uloha",
|
||||||
|
"tvorba",
|
||||||
|
"uloha"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_nastaveni",
|
||||||
|
"various",
|
||||||
|
"nastaveni"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_nastaveni",
|
||||||
|
"various",
|
||||||
|
"nastaveni"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_nastaveni",
|
||||||
|
"various",
|
||||||
|
"nastaveni"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"view_nastaveni",
|
||||||
|
"various",
|
||||||
|
"nastaveni"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"model": "auth.group",
|
||||||
|
"pk": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"name": "resitel",
|
||||||
|
"permissions": [
|
||||||
|
[
|
||||||
|
"resitel",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"model": "auth.group",
|
||||||
|
"pk": 2
|
||||||
|
}
|
||||||
|
]
|
|
@ -73,7 +73,7 @@
|
||||||
"sort_order": 3,
|
"sort_order": 3,
|
||||||
"title": "Aktuální<br/> ročník",
|
"title": "Aktuální<br/> ročník",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_aktualni_zadani",
|
"url": "tvorba_aktualni_zadani",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
"sort_order": 5,
|
"sort_order": 5,
|
||||||
"title": "Archiv",
|
"title": "Archiv",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_archiv_rocniky",
|
"url": "tvorba_archiv_rocniky",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -289,7 +289,7 @@
|
||||||
"sort_order": 43,
|
"sort_order": 43,
|
||||||
"title": "Výsledková listina",
|
"title": "Výsledková listina",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_aktualni_vysledky",
|
"url": "tvorba_aktualni_vysledky",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -361,7 +361,7 @@
|
||||||
"sort_order": 20,
|
"sort_order": 20,
|
||||||
"title": "Proběhlo",
|
"title": "Proběhlo",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_seznam_soustredeni",
|
"url": "soustredeni_seznam",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -409,7 +409,7 @@
|
||||||
"sort_order": 23,
|
"sort_order": 23,
|
||||||
"title": "Osobní údaje",
|
"title": "Osobní údaje",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_resitel_edit",
|
"url": "personalni_resitel_edit",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -421,7 +421,11 @@
|
||||||
"access_loggedin": false,
|
"access_loggedin": false,
|
||||||
"access_perm_type": 1,
|
"access_perm_type": 1,
|
||||||
"access_permissions": [
|
"access_permissions": [
|
||||||
162
|
[
|
||||||
|
"resitel",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
],
|
],
|
||||||
"access_restricted": true,
|
"access_restricted": true,
|
||||||
"alias": null,
|
"alias": null,
|
||||||
|
@ -433,9 +437,9 @@
|
||||||
"insitetree": true,
|
"insitetree": true,
|
||||||
"parent": 21,
|
"parent": 21,
|
||||||
"sort_order": 36,
|
"sort_order": 36,
|
||||||
"title": "Poslat řešení",
|
"title": "Nahrát řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_nahraj_reseni",
|
"url": "odevzdavatko_nahraj_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -459,7 +463,7 @@
|
||||||
"sort_order": 35,
|
"sort_order": 35,
|
||||||
"title": "Témata",
|
"title": "Témata",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_archiv_temata",
|
"url": "tvorba_archiv_temata",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -471,7 +475,11 @@
|
||||||
"access_loggedin": false,
|
"access_loggedin": false,
|
||||||
"access_perm_type": 1,
|
"access_perm_type": 1,
|
||||||
"access_permissions": [
|
"access_permissions": [
|
||||||
161
|
[
|
||||||
|
"org",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
],
|
],
|
||||||
"access_restricted": true,
|
"access_restricted": true,
|
||||||
"alias": null,
|
"alias": null,
|
||||||
|
@ -581,7 +589,7 @@
|
||||||
"sort_order": 15,
|
"sort_order": 15,
|
||||||
"title": "Aktuální číslo",
|
"title": "Aktuální číslo",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_aktualni_zadani",
|
"url": "tvorba_aktualni_zadani",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -605,7 +613,7 @@
|
||||||
"sort_order": 24,
|
"sort_order": 24,
|
||||||
"title": "Čísla",
|
"title": "Čísla",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_archiv_rocniky",
|
"url": "tvorba_archiv_rocniky",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -641,7 +649,11 @@
|
||||||
"access_loggedin": false,
|
"access_loggedin": false,
|
||||||
"access_perm_type": 1,
|
"access_perm_type": 1,
|
||||||
"access_permissions": [
|
"access_permissions": [
|
||||||
161
|
[
|
||||||
|
"org",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
],
|
],
|
||||||
"access_restricted": true,
|
"access_restricted": true,
|
||||||
"alias": null,
|
"alias": null,
|
||||||
|
@ -691,7 +703,11 @@
|
||||||
"access_loggedin": false,
|
"access_loggedin": false,
|
||||||
"access_perm_type": 1,
|
"access_perm_type": 1,
|
||||||
"access_permissions": [
|
"access_permissions": [
|
||||||
161
|
[
|
||||||
|
"org",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
],
|
],
|
||||||
"access_restricted": true,
|
"access_restricted": true,
|
||||||
"alias": null,
|
"alias": null,
|
||||||
|
@ -703,9 +719,9 @@
|
||||||
"insitetree": true,
|
"insitetree": true,
|
||||||
"parent": 21,
|
"parent": 21,
|
||||||
"sort_order": 36,
|
"sort_order": 36,
|
||||||
"title": "Nahrát řešení",
|
"title": "Vložit řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_vloz_reseni",
|
"url": "odevzdavatko_vloz_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -765,8 +781,16 @@
|
||||||
"access_loggedin": false,
|
"access_loggedin": false,
|
||||||
"access_perm_type": 1,
|
"access_perm_type": 1,
|
||||||
"access_permissions": [
|
"access_permissions": [
|
||||||
161,
|
[
|
||||||
162
|
"org",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"resitel",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
],
|
],
|
||||||
"access_restricted": true,
|
"access_restricted": true,
|
||||||
"alias": null,
|
"alias": null,
|
||||||
|
@ -780,7 +804,7 @@
|
||||||
"sort_order": 37,
|
"sort_order": 37,
|
||||||
"title": "Moje řešení",
|
"title": "Moje řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_resitel_odevzdana_reseni",
|
"url": "odevzdavatko_resitel_odevzdana_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -804,7 +828,7 @@
|
||||||
"sort_order": 33,
|
"sort_order": 33,
|
||||||
"title": "Aktuální ročník",
|
"title": "Aktuální ročník",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_aktualni_rocnik",
|
"url": "tvorba_aktualni_rocnik",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -876,7 +900,7 @@
|
||||||
"sort_order": 46,
|
"sort_order": 46,
|
||||||
"title": "Ročník {{rocnik.rocnik}}",
|
"title": "Ročník {{rocnik.rocnik}}",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_rocnik rocnik.rocnik",
|
"url": "tvorba_rocnik rocnik.rocnik",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -900,7 +924,7 @@
|
||||||
"sort_order": 47,
|
"sort_order": 47,
|
||||||
"title": "Číslo {{ cislo.rocnik.rocnik }}.{{ cislo.poradi }}",
|
"title": "Číslo {{ cislo.rocnik.rocnik }}.{{ cislo.poradi }}",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_cislo cislo.rocnik.rocnik cislo.poradi",
|
"url": "tvorba_cislo cislo.rocnik.rocnik cislo.poradi",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
|
@ -977,5 +1001,118 @@
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
"pk": 50
|
"pk": 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"access_guest": false,
|
||||||
|
"access_loggedin": false,
|
||||||
|
"access_perm_type": 1,
|
||||||
|
"access_permissions": [
|
||||||
|
[
|
||||||
|
"org",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"resitel",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"access_restricted": true,
|
||||||
|
"alias": null,
|
||||||
|
"description": "",
|
||||||
|
"hidden": false,
|
||||||
|
"hint": "",
|
||||||
|
"inbreadcrumbs": true,
|
||||||
|
"inmenu": true,
|
||||||
|
"insitetree": true,
|
||||||
|
"parent": 42,
|
||||||
|
"sort_order": 51,
|
||||||
|
"title": "Detail řešení {{ reseni.id }}",
|
||||||
|
"tree": 1,
|
||||||
|
"url": "odevzdavatko_resitel_reseni reseni.id",
|
||||||
|
"urlaspattern": true
|
||||||
|
},
|
||||||
|
"model": "sitetree.treeitem",
|
||||||
|
"pk": 51
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"access_guest": false,
|
||||||
|
"access_loggedin": false,
|
||||||
|
"access_perm_type": 1,
|
||||||
|
"access_permissions": [
|
||||||
|
[
|
||||||
|
"resitel",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"access_restricted": true,
|
||||||
|
"alias": null,
|
||||||
|
"description": "",
|
||||||
|
"hidden": false,
|
||||||
|
"hint": "",
|
||||||
|
"inbreadcrumbs": true,
|
||||||
|
"inmenu": true,
|
||||||
|
"insitetree": true,
|
||||||
|
"parent": 23,
|
||||||
|
"sort_order": 52,
|
||||||
|
"title": "Nahrát řešení k nadproblému {{nadproblem_id}}",
|
||||||
|
"tree": 1,
|
||||||
|
"url": "odevzdavatko_nahraj_reseni nadproblem_id",
|
||||||
|
"urlaspattern": true
|
||||||
|
},
|
||||||
|
"model": "sitetree.treeitem",
|
||||||
|
"pk": 52
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"access_guest": false,
|
||||||
|
"access_loggedin": false,
|
||||||
|
"access_perm_type": 1,
|
||||||
|
"access_permissions": [],
|
||||||
|
"access_restricted": false,
|
||||||
|
"alias": null,
|
||||||
|
"description": "",
|
||||||
|
"hidden": false,
|
||||||
|
"hint": "",
|
||||||
|
"inbreadcrumbs": true,
|
||||||
|
"inmenu": true,
|
||||||
|
"insitetree": true,
|
||||||
|
"parent": 28,
|
||||||
|
"sort_order": 53,
|
||||||
|
"title": "Přidat PDF",
|
||||||
|
"tree": 1,
|
||||||
|
"url": "/admin/korektury/korekturovanepdf/add/",
|
||||||
|
"urlaspattern": false
|
||||||
|
},
|
||||||
|
"model": "sitetree.treeitem",
|
||||||
|
"pk": 53
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"access_guest": false,
|
||||||
|
"access_loggedin": false,
|
||||||
|
"access_perm_type": 1,
|
||||||
|
"access_permissions": [],
|
||||||
|
"access_restricted": false,
|
||||||
|
"alias": null,
|
||||||
|
"description": "",
|
||||||
|
"hidden": false,
|
||||||
|
"hint": "",
|
||||||
|
"inbreadcrumbs": true,
|
||||||
|
"inmenu": true,
|
||||||
|
"insitetree": true,
|
||||||
|
"parent": 20,
|
||||||
|
"sort_order": 54,
|
||||||
|
"title": "Export do abstraktů sousu {{ soustredeni.id }}",
|
||||||
|
"tree": 1,
|
||||||
|
"url": "soustredeni_abstrakty soustredeni.id",
|
||||||
|
"urlaspattern": true
|
||||||
|
},
|
||||||
|
"model": "sitetree.treeitem",
|
||||||
|
"pk": 54
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,637 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"codename": "org",
|
|
||||||
"ct_app_label": "auth",
|
|
||||||
"ct_model": "user"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_flatpage",
|
|
||||||
"ct_app_label": "flatpages",
|
|
||||||
"ct_model": "flatpage"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_flatpage",
|
|
||||||
"ct_app_label": "flatpages",
|
|
||||||
"ct_model": "flatpage"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_flatpage",
|
|
||||||
"ct_app_label": "flatpages",
|
|
||||||
"ct_model": "flatpage"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_flatpage",
|
|
||||||
"ct_app_label": "flatpages",
|
|
||||||
"ct_model": "flatpage"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_galerie",
|
|
||||||
"ct_app_label": "galerie",
|
|
||||||
"ct_model": "galerie"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_galerie",
|
|
||||||
"ct_app_label": "galerie",
|
|
||||||
"ct_model": "galerie"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_galerie",
|
|
||||||
"ct_app_label": "galerie",
|
|
||||||
"ct_model": "galerie"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_galerie",
|
|
||||||
"ct_app_label": "galerie",
|
|
||||||
"ct_model": "galerie"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_obrazek",
|
|
||||||
"ct_app_label": "galerie",
|
|
||||||
"ct_model": "obrazek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_obrazek",
|
|
||||||
"ct_app_label": "galerie",
|
|
||||||
"ct_model": "obrazek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_obrazek",
|
|
||||||
"ct_app_label": "galerie",
|
|
||||||
"ct_model": "obrazek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_obrazek",
|
|
||||||
"ct_app_label": "galerie",
|
|
||||||
"ct_model": "obrazek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_komentar",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "komentar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_komentar",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "komentar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_komentar",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "komentar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_komentar",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "komentar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_korekturovanepdf",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "korekturovanepdf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_korekturovanepdf",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "korekturovanepdf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_korekturovanepdf",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "korekturovanepdf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_korekturovanepdf",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "korekturovanepdf"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_oprava",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "oprava"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_oprava",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "oprava"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_oprava",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "oprava"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_oprava",
|
|
||||||
"ct_app_label": "korektury",
|
|
||||||
"ct_model": "oprava"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_hlasovani",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "hlasovani"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_hlasovani",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "hlasovani"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_hlasovani",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "hlasovani"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_hlasovani",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "hlasovani"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_prednaska",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "prednaska"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_prednaska",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "prednaska"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_prednaska",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "prednaska"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_prednaska",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "prednaska"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_seznam",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "seznam"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_seznam",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "seznam"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_seznam",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "seznam"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_seznam",
|
|
||||||
"ct_app_label": "prednasky",
|
|
||||||
"ct_model": "seznam"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_cislo",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "cislo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_cislo",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "cislo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_cislo",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "cislo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_cislo",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "cislo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_clanek",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "clanek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_clanek",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "clanek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_clanek",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "clanek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_clanek",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "clanek"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_konfera",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "konfera"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_konfera",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "konfera"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_konfera",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "konfera"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_konfera",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "konfera"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_konfery_ucastnici",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "konfery_ucastnici"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_konfery_ucastnici",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "konfery_ucastnici"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_konfery_ucastnici",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "konfery_ucastnici"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_konfery_ucastnici",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "konfery_ucastnici"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_nastaveni",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "nastaveni"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_nastaveni",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "nastaveni"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_nastaveni",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "nastaveni"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_nastaveni",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "nastaveni"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_novinky",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "novinky"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_novinky",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "novinky"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_novinky",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "novinky"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_novinky",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "novinky"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_organizator",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "organizator"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_organizator",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "organizator"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_organizator",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "organizator"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_organizator",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "organizator"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_osoba",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "osoba"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_osoba",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "osoba"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_osoba",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "osoba"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_osoba",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "osoba"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_pohadka",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "pohadka"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_pohadka",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "pohadka"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_pohadka",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "pohadka"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_pohadka",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "pohadka"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_prijemce",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "prijemce"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_prijemce",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "prijemce"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_prijemce",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "prijemce"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_prijemce",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "prijemce"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_problem",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "problem"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_problem",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "problem"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_problem",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "problem"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_problem",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "problem"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_resitel",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "resitel"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_resitel",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "resitel"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_resitel",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "resitel"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_resitel",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "resitel"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_rocnik",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "rocnik"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_rocnik",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "rocnik"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_rocnik",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "rocnik"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_rocnik",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "rocnik"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_skola",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "skola"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_skola",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "skola"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_skola",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "skola"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_skola",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "skola"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_soustredeni",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_soustredeni",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_soustredeni",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_soustredeni",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_soustredeni_organizatori",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni_organizatori"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_soustredeni_organizatori",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni_organizatori"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_soustredeni_organizatori",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni_organizatori"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_soustredeni_organizatori",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni_organizatori"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_soustredeni_ucastnici",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni_ucastnici"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_soustredeni_ucastnici",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni_ucastnici"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_soustredeni_ucastnici",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni_ucastnici"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_soustredeni_ucastnici",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "soustredeni_ucastnici"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_tema",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "tema"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_tema",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "tema"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_tema",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "tema"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_tema",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "tema"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_uloha",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "uloha"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_uloha",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "uloha"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_uloha",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "uloha"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_uloha",
|
|
||||||
"ct_app_label": "seminar",
|
|
||||||
"ct_model": "uloha"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_tag",
|
|
||||||
"ct_app_label": "taggit",
|
|
||||||
"ct_model": "tag"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_tag",
|
|
||||||
"ct_app_label": "taggit",
|
|
||||||
"ct_model": "tag"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_tag",
|
|
||||||
"ct_app_label": "taggit",
|
|
||||||
"ct_model": "tag"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_tag",
|
|
||||||
"ct_app_label": "taggit",
|
|
||||||
"ct_model": "tag"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_taggeditem",
|
|
||||||
"ct_app_label": "taggit",
|
|
||||||
"ct_model": "taggeditem"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_taggeditem",
|
|
||||||
"ct_app_label": "taggit",
|
|
||||||
"ct_model": "taggeditem"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "delete_taggeditem",
|
|
||||||
"ct_app_label": "taggit",
|
|
||||||
"ct_model": "taggeditem"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_taggeditem",
|
|
||||||
"ct_app_label": "taggit",
|
|
||||||
"ct_model": "taggeditem"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_fotkaheader",
|
|
||||||
"ct_app_label": "header_fotky",
|
|
||||||
"ct_model": "fotkaheader"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_fotkaheader",
|
|
||||||
"ct_app_label": "header_fotky",
|
|
||||||
"ct_model": "fotkaheader"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_fotkaheader",
|
|
||||||
"ct_app_label": "header_fotky",
|
|
||||||
"ct_model": "fotkaheader"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "add_fotkaurlvazba",
|
|
||||||
"ct_app_label": "header_fotky",
|
|
||||||
"ct_model": "fotkaurlvazba"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "change_fotkaurlvazba",
|
|
||||||
"ct_app_label": "header_fotky",
|
|
||||||
"ct_model": "fotkaurlvazba"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"codename": "view_fotkaurlvazba",
|
|
||||||
"ct_app_label": "header_fotky",
|
|
||||||
"ct_model": "fotkaurlvazba"
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -13,7 +13,6 @@ make install_venv
|
||||||
make install
|
make install
|
||||||
deploy_v2/pre_migration.py
|
deploy_v2/pre_migration.py
|
||||||
make deploy_test
|
make deploy_test
|
||||||
./manage.py load_org_permissions admin_org_prava.json
|
|
||||||
./manage.py loaddata data/*
|
./manage.py loaddata data/*
|
||||||
systemctl --user start mamweb-test.service
|
systemctl --user start mamweb-test.service
|
||||||
./manage.py generate_thumbnails
|
./manage.py generate_thumbnails
|
||||||
|
|
21
docs/Makefile
Normal file
21
docs/Makefile
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Minimal makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line, and also
|
||||||
|
# from the environment for the first two.
|
||||||
|
SPHINXOPTS ?=
|
||||||
|
SPHINXBUILD ?= sphinx-build
|
||||||
|
SOURCEDIR = .
|
||||||
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
# Put it first so that "make" without argument is like "make help".
|
||||||
|
help:
|
||||||
|
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
|
|
||||||
|
.PHONY: help Makefile
|
||||||
|
|
||||||
|
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||||
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
|
%: Makefile
|
||||||
|
sphinx-apidoc --module-first -o modules .. ../*/migrations --templatedir _templates -f
|
||||||
|
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
8
docs/_templates/module.rst_t
vendored
Normal file
8
docs/_templates/module.rst_t
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{%- if show_headings %}
|
||||||
|
{{- [basename, ".py"] | join('') | e | heading }}
|
||||||
|
|
||||||
|
{% endif -%}
|
||||||
|
.. automodule:: {{ qualname }}
|
||||||
|
{%- for option in automodule_options %}
|
||||||
|
:{{ option }}:
|
||||||
|
{%- endfor %}
|
57
docs/_templates/package.rst_t
vendored
Normal file
57
docs/_templates/package.rst_t
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
{%- macro automodule(modname, options) -%}
|
||||||
|
.. automodule:: {{ modname }}
|
||||||
|
{%- for option in options %}
|
||||||
|
:{{ option }}:
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro toctree(docnames) -%}
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: {{ maxdepth }}
|
||||||
|
{% for docname in docnames %}
|
||||||
|
{{ docname }}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- if is_namespace %}
|
||||||
|
{{- pkgname | e | heading }}
|
||||||
|
{% else %}
|
||||||
|
{{- pkgname | e | heading }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{%- if is_namespace %}
|
||||||
|
.. py:module:: {{ pkgname }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{%- if modulefirst and not is_namespace %}
|
||||||
|
{{ automodule(pkgname, automodule_options) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{%- if subpackages %}
|
||||||
|
{# Subpackages #}
|
||||||
|
{# ----------- #}
|
||||||
|
|
||||||
|
{{ toctree(subpackages) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{%- if submodules %}
|
||||||
|
{# Submodules #}
|
||||||
|
{# ---------- #}
|
||||||
|
{% if separatemodules %}
|
||||||
|
{{ toctree(submodules) }}
|
||||||
|
{% else %}
|
||||||
|
{%- for submodule in submodules %}
|
||||||
|
{% if show_headings %}
|
||||||
|
{{- submodule | e | heading(2) }}
|
||||||
|
{% endif %}
|
||||||
|
{{ automodule(submodule, automodule_options) }}
|
||||||
|
{% endfor %}
|
||||||
|
{%- endif %}
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
{%- if not modulefirst and not is_namespace %}
|
||||||
|
Module contents
|
||||||
|
---------------
|
||||||
|
|
||||||
|
{{ automodule(pkgname, automodule_options) }}
|
||||||
|
{% endif %}
|
7
docs/_templates/toc.rst_t
vendored
Normal file
7
docs/_templates/toc.rst_t
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{{ "Seznam aplikací" | heading }}
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: {{ maxdepth }}
|
||||||
|
{% for docname in docnames %}
|
||||||
|
{{ docname }}
|
||||||
|
{%- endfor %}
|
5
docs/april.rst
Normal file
5
docs/april.rst
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
Aprílové nápad
|
||||||
|
==============
|
||||||
|
|
||||||
|
* aprílový easter-egg pro řešitele - vytvořit nějakou vtipnou testovací databázi a nasadit ji místo produkce
|
||||||
|
* změnit veškerý text na oranžovo
|
103
docs/conf.py
Normal file
103
docs/conf.py
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# This file only contains a selection of the most common options. For a full
|
||||||
|
# list see the documentation:
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
# -- Path setup --------------------------------------------------------------
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import django
|
||||||
|
from django.utils.version import get_docs_version
|
||||||
|
sys.path.insert(0, os.path.abspath('..'))
|
||||||
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'mamweb.settings'
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
|
project = 'Web M&M'
|
||||||
|
copyright = '2022, Orgové'
|
||||||
|
author = 'Orgové'
|
||||||
|
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.viewcode',
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
|
'sphinx.ext.autosectionlabel',
|
||||||
|
'myst_parser',
|
||||||
|
'sphinxcontrib_django',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#
|
||||||
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
|
# Usually you set "language" from the command line for these cases.
|
||||||
|
language = 'cs'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This pattern also affects html_static_path and html_extra_path.
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
import sphinx_rtd_theme
|
||||||
|
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
|
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Provázání s jinými dokumentacemi
|
||||||
|
intersphinx_mapping = {'python': ('https://docs.python.org/3', None),
|
||||||
|
'django': (f'http://docs.djangoproject.com/en/{get_docs_version()}/',
|
||||||
|
f'http://docs.djangoproject.com/en/{get_docs_version()}/_objects/'),}
|
||||||
|
|
||||||
|
# Generování tříd/funkcí/atributů v pořádí jak jsou naprogramované
|
||||||
|
autodoc_member_order = "bysource"
|
||||||
|
|
||||||
|
# Nezobrazování zděděné (ze super tříd) dokumentace TODO nefunguje?
|
||||||
|
autodoc_inherit_docstrings = False
|
||||||
|
|
||||||
|
source_suffix = {
|
||||||
|
'.rst': 'restructuredtext',
|
||||||
|
'.md': 'markdown',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Autodoc má ignorovat některé moduly
|
||||||
|
# Ref: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#event-autodoc-skip-member
|
||||||
|
# Kudos: https://stackoverflow.com/a/21449475/
|
||||||
|
def ignorovat(app, what, name, obj, skip, options):
|
||||||
|
blacklist = (
|
||||||
|
# typ (what), name
|
||||||
|
('module', 'settings.mamweb_prod'),
|
||||||
|
)
|
||||||
|
ignore = (what, name) in blacklist
|
||||||
|
return True if ignore else None
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.connect('autodoc-skip-member', ignorovat)
|
27
docs/css.rst
Normal file
27
docs/css.rst
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
CSS (a další styly na webu)
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Inspirován `css-trick článkem <https://css-tricks.com/methods-organize-css/>`_ jsem se rozhodl rozdělit
|
||||||
|
CSSka do
|
||||||
|
|
||||||
|
- Konstant (``constants.css``), které jsou využívány na mnoha místech CSSek
|
||||||
|
- Nastylování html tagů (``base.css``)
|
||||||
|
- Layoutu (``layout.css``), což je to, co určuje celkové rozložení stránky
|
||||||
|
- Jednotlivých prvků (``modules.css``)
|
||||||
|
|
||||||
|
Dále jsem separoval CSSka pro **galerii** (potřebuje hodně specifických stylů). Stejně tak **korekturovátko** má styly separátně.
|
||||||
|
|
||||||
|
Dále web (asi) používá externí frameworky (v separátních složkách – mají k sobě i JS a podobné věci):
|
||||||
|
|
||||||
|
- bootstrap: dělá nějaké basic stylování, *web je na něm hodně závislý* (například jsem zjistil, že bootstrap kdysi přidával ``font-size:14px``, bez čehož se web úplně rozpadnul) (také na něm běží mobilní meníčko, které navíc vyžaduje Popper, tedy bootstrap.bundle.js místo bootstrap.js)
|
||||||
|
|
||||||
|
Pak jsou tu ``mamweb-dev.css`` a ``printtable.css``, co jsem si ještě nerozmyslel, co s tím.
|
||||||
|
|
||||||
|
Pár myšlenek
|
||||||
|
------------
|
||||||
|
|
||||||
|
- Až na pár výjimek (galerii a korekturovátko) bych styly držel v jedné složce a málo souborech,
|
||||||
|
protože CSS šíleně dědí všechno možné
|
||||||
|
- Chce to dobře pojmenovávat třídy (speciálně aby bylo vidět, co ta třída dělá nebo kde se používá)
|
||||||
|
- Chce to hodně komentovat kód (speciálně tam, kde není splněn předchozí bod)
|
||||||
|
|
86
docs/dalsi_soubory.rst
Normal file
86
docs/dalsi_soubory.rst
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
Další soubory/složky v kořenovém adresáři
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
media
|
||||||
|
-----
|
||||||
|
Složka, kam django nahrává soubory „jako by je nahrávalo do databáze“.
|
||||||
|
|
||||||
|
static
|
||||||
|
------
|
||||||
|
Složka, kam django nakopíruje všechno ze složek static a pak na to z templatů / kódu jde ukazovat pomocí ``static``.
|
||||||
|
|
||||||
|
data
|
||||||
|
----
|
||||||
|
Obsahuje data, která patří do databáze, ale jsou přímo součástí webu jako
|
||||||
|
takového. Aktuálně jsou to statické stránky, meníčko a rozložení obrázků
|
||||||
|
v pozadí meníčka.
|
||||||
|
|
||||||
|
Generuje se za pomocí::
|
||||||
|
|
||||||
|
./manage.py dumpdata flatpages > data/flat_new.json
|
||||||
|
./fix_json.py data/flat_new.json data/flat.json
|
||||||
|
|
||||||
|
nebo (v případě meníčka)::
|
||||||
|
|
||||||
|
./manage.py dumpdata sitetree --natural-foreign > data/sitetree_new.json
|
||||||
|
./fix_json.py data/sitetree_new.json data/sitetree.json
|
||||||
|
|
||||||
|
deploy_v2
|
||||||
|
---------
|
||||||
|
Věci, které byly potřeba při nasazování nového (2021) webu.
|
||||||
|
|
||||||
|
docs
|
||||||
|
----
|
||||||
|
Zde je dokumentace webu. Viz :ref:`Sphinx na našem webu`.
|
||||||
|
|
||||||
|
setup
|
||||||
|
-----
|
||||||
|
Tato složka obsahuje různé konfiguráky potřebné k rozběhnutí webu na serveru.
|
||||||
|
|
||||||
|
vue_frontend
|
||||||
|
------------
|
||||||
|
Obsahuje první pokusy o editory treenodů ve vue.
|
||||||
|
|
||||||
|
.gitignore
|
||||||
|
----------
|
||||||
|
Klasické `.gitignore`_
|
||||||
|
|
||||||
|
.. _.gitignore: https://git-scm.com/docs/gitignore
|
||||||
|
|
||||||
|
checklinks.sh
|
||||||
|
-------------
|
||||||
|
„Týrací“ skript na kontrolu, že nic, kam se lze proklikat na webu, nehází chybu.
|
||||||
|
|
||||||
|
constraints.txt
|
||||||
|
---------------
|
||||||
|
Obsahuje omezení na :ref:`requirements.txt`.
|
||||||
|
|
||||||
|
convert_spaces_to_tabs.sh
|
||||||
|
-------------------------
|
||||||
|
Skript na změnu odsazování.
|
||||||
|
|
||||||
|
db-local.sqlite3
|
||||||
|
----------------
|
||||||
|
Lokální databáze (na serveru není).
|
||||||
|
|
||||||
|
diff_db_backup.sh
|
||||||
|
-----------------
|
||||||
|
Nevím. Typoval bych skript na diff záloh (resp. dumpů) databáze.
|
||||||
|
|
||||||
|
Makefile
|
||||||
|
--------
|
||||||
|
Klasické `Makefile`_. Obsahuje například vytvoření virtual_env, instalaci a nasazování webu.
|
||||||
|
|
||||||
|
.. _Makefile: https://www.gnu.org/software/make/manual/make.html
|
||||||
|
|
||||||
|
manage.py
|
||||||
|
---------
|
||||||
|
Základní soubor djanga.
|
||||||
|
|
||||||
|
README.md
|
||||||
|
---------
|
||||||
|
Většina je spíš zbytek po bývalých webařích.
|
||||||
|
|
||||||
|
requirements.txt
|
||||||
|
----------------
|
||||||
|
Seznam balíčků, které jsou potřeba pro běh mamwebu. (Cílem je vytvoření virtualenvu se všemi těmito balíčky, např. pomocí daného příkazu v :ref:`Makefile`.)
|
55
docs/default_doc.rst
Normal file
55
docs/default_doc.rst
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
Defaultní dokumentace speciálních souborů
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
Drobná nápověda k běžným django souborům. (Do nich jsem to vkládal copy-paste.)
|
||||||
|
|
||||||
|
admin.py
|
||||||
|
--------
|
||||||
|
Soubor sloužící k definici toho, co bude v adminu. Většinou pouhým zavoláním
|
||||||
|
funkce :func:`django.contrib.admin.site.register`, v případě, že chceme něco
|
||||||
|
upravit, tak jako třída rozšiřující :class:`django.contrib.admin.ModelAdmin`
|
||||||
|
s dekorátorem :func:`django.contrib.admin.register`.
|
||||||
|
|
||||||
|
Zde se definuje admin pro:
|
||||||
|
|
||||||
|
apps.py
|
||||||
|
-------
|
||||||
|
Soubor sloužící k pojmenování a jiným nastavením djangovské aplikace.
|
||||||
|
|
||||||
|
forms.py
|
||||||
|
--------
|
||||||
|
Formuláře (:class:`django.forms.Form`) umožňují jednoduchou tvorbu formulářů,
|
||||||
|
které lze pak jednoduše dát do frontendu i zpracovat na backendu.
|
||||||
|
|
||||||
|
Pro přidání políčka do formuláře je potřeba
|
||||||
|
- mít v modelu tu položku, kterou chci upravovat
|
||||||
|
- přidat do views (prihlaskaView, resitelEditView)
|
||||||
|
- přidat do forms
|
||||||
|
- includovat do html
|
||||||
|
|
||||||
|
models.py
|
||||||
|
---------
|
||||||
|
Tento soubor slouží k definici databázového modelu.
|
||||||
|
|
||||||
|
Třídy rozšiřují většinou :class:`django.db.models.Model` a jejich atributy jsou
|
||||||
|
většinou sloupce v databázi (tj. nastaví se na hodnotu něčeho z :mod:`django.db.models`).
|
||||||
|
Na výběr jsou:
|
||||||
|
|
||||||
|
- :class:`django.db.models.TextField`
|
||||||
|
- :class:`django.db.models.ForeignKey`
|
||||||
|
- :class:`django.db.models.DateField`
|
||||||
|
- :class:`django.db.models.DateTimeField`
|
||||||
|
- :class:`django.db.models.ImageField`
|
||||||
|
- :class:`django.db.models.CharField`
|
||||||
|
|
||||||
|
testutils.py
|
||||||
|
------------
|
||||||
|
Soubor sloužící ke generování testdat.
|
||||||
|
|
||||||
|
urls.py
|
||||||
|
-------
|
||||||
|
Soubor sloužící jako „router“, tj. zde se definují url adresy a na co ukazují:
|
||||||
|
|
||||||
|
views.py
|
||||||
|
--------
|
||||||
|
|
45
docs/index.rst
Normal file
45
docs/index.rst
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
.. Web M&M documentation master file, created by
|
||||||
|
sphinx-quickstart on Mon Jan 31 21:56:04 2022.
|
||||||
|
You can adapt this file completely to your liking, but it should at least
|
||||||
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
|
Vítejte v dokumentaci M&Mího webu!
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Tzv. produkce (tedy to, co vidí uživatelé) běží na `<mam.mff.cuni.cz>`_ (resp.
|
||||||
|
`<mam.matfyz.cz>`_), menu, obrázky v pozadí menu a spousta stránek (ty pouze se
|
||||||
|
statickým textem/obrázky) se mění přímo na produkci. Testovací verze běží na
|
||||||
|
`<https://mam-test.ks.matfyz.cz/>`_.
|
||||||
|
|
||||||
|
Abychom uměli web vyvíjet, musíme ho většinou nejdřív umět
|
||||||
|
:doc:`naklonovat a spustit lokálně <vyvoj>`.
|
||||||
|
|
||||||
|
:doc:`struktura mamwebu <struktura>` se řídí hlavně djangem, ale snažíme se
|
||||||
|
také o oddělení jednotlivých částí do :doc:`samostatných aplikací
|
||||||
|
<modules/modules>`.
|
||||||
|
|
||||||
|
Dokumentace (jak v ``docs/``, tak přímo v kódu) je psaná ve
|
||||||
|
:doc:`sphinxu <sphinx>`.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: M&M web
|
||||||
|
:maxdepth: 2
|
||||||
|
:titlesonly:
|
||||||
|
|
||||||
|
vyvoj
|
||||||
|
zavislosti
|
||||||
|
sphinx
|
||||||
|
skripty
|
||||||
|
zkratky
|
||||||
|
modules/modules
|
||||||
|
dalsi_soubory
|
||||||
|
zapisy/zapisy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Rejstříky a vyhledávání
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
|
@ -1,3 +1,4 @@
|
||||||
|
FIXME přepsat do rst, přidat i další věci a případně přesunout na wiki
|
||||||
Přidání obrázků do odměn:
|
Přidání obrázků do odměn:
|
||||||
admin -> flatpage odměn -> ikona přidat obrázek
|
admin -> flatpage odměn -> ikona přidat obrázek
|
||||||
záložka odeslat, vybrat obrázek, odeslat
|
záložka odeslat, vybrat obrázek, odeslat
|
108
docs/skripty.rst
Normal file
108
docs/skripty.rst
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
Skripty pro práci s repozitářem
|
||||||
|
===================
|
||||||
|
|
||||||
|
Máme dvě hlavní sady skriptů/příkazů na ovládání webu a repozitáře. Skripty pro
|
||||||
|
práci s webem psané v Pythonu jsou uložené ve složkách
|
||||||
|
``<aplikace>/management/commands/``, případně vestavěné, a volají se pomocí
|
||||||
|
``./manage.py <příkaz>``. Oproti tomu skripty pro práci s repozitářem a pro
|
||||||
|
úpravy databáze a souborů „zvenčí“ se nejčastěji nacházejí ve složce ``make/``
|
||||||
|
a volají se pomocí cesty: ``make/<příkaz>``.
|
||||||
|
|
||||||
|
Občas existují i nějaké další skripty na různých jiných místech. Všechny by
|
||||||
|
měly být ideálně popsány asi tady.
|
||||||
|
|
||||||
|
Make skripty
|
||||||
|
----
|
||||||
|
|
||||||
|
Skripty v ``make/`` se označují jako „Make skripty“. Slouží často k velkým
|
||||||
|
úkonům s repozitářem, jako je nasazení celého webu, zprovoznění lokálního webu
|
||||||
|
a podobně.
|
||||||
|
|
||||||
|
.. note:: Označení pro tyto skripty je dáno tím, že byly původně volány pomocí
|
||||||
|
make (tj. z Makefile). Ve skutečnosti je lze stále volat i jako ``make
|
||||||
|
<skript>``, ale pak není možné předávat parametry a obecně je tato cesta
|
||||||
|
zastaralá a existuje jen pro zpětnou kompatibilitu se svalovou pamětí.
|
||||||
|
|
||||||
|
Tyto skripty jsou samonosné, dají se spustit rovnou a v případě problémů si
|
||||||
|
budou hlasitě stěžovat. Pro účely debugování různých věcí jsou ale (bohužel?)
|
||||||
|
hlasité i při normálním spuštění, konkrétně vypisují všechny příkazy, které se
|
||||||
|
spouštějí (\ ``set -x``). Tyto příkazy jsou vidět za jedním či více plusky (\ ``+``).
|
||||||
|
|
||||||
|
.. tip:: Pokud některý make skript selže, tak by na konci měl vypsat, že se něco nepovedlo.
|
||||||
|
|
||||||
|
|
||||||
|
Knihovna ``make/lib.sh``
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
Pro pohodlí při psaní velká část z nich využívá knihovnu uloženou
|
||||||
|
v ``make/lib.sh``. Jsou zde definované užitečné proměnné, kontroly a společný
|
||||||
|
kód. Kromě toho při inicializaci otestuje, že je skript spuštěn z kořene
|
||||||
|
repozitáře (takže to pak není potřeba zkoumat v ostatních skriptech).
|
||||||
|
|
||||||
|
Proměnné
|
||||||
|
"""""
|
||||||
|
|
||||||
|
Popsány jsou jen užitečné proměnné, ve skutečnosti jich je definovaných víc,
|
||||||
|
ale jsou triviální a samopopisné.
|
||||||
|
|
||||||
|
``VENV_PATH``
|
||||||
|
Cesta virtuálního prostředí. Též lze přepsat.
|
||||||
|
``REPO``
|
||||||
|
Cesta ke gitovému repozitáři na serveru, rovnou použitelná v ``git clone``
|
||||||
|
``GIMLI_LOGIN``
|
||||||
|
Přihlašovací údaje ke Gimlimu
|
||||||
|
``PRODWEB`` a ``TESTWEB``
|
||||||
|
Cesty ke složkám s produkčním a testovacím webem
|
||||||
|
|
||||||
|
Funkce a další zkratky
|
||||||
|
""""""
|
||||||
|
|
||||||
|
``ensure_venv``
|
||||||
|
Zajistí, že se zbytek skriptu spustí ve virtuálním prostředí, a pokud neexistuje, tak jej založí.
|
||||||
|
``ensure_web_installed``
|
||||||
|
Vyzkouší, že je web (django) aspoň elementárně zprovozněno a pokud ne, tak vyzve uživatele, aby to spravil.
|
||||||
|
``gimli_only``
|
||||||
|
Otestuje, že je příkaz spuštěn na Gimlim, pokud tomu tak není, zeptá se, jestli si uživatel skutečně přeje zbytek skriptu vykonat
|
||||||
|
``only_in_directory <složka>``
|
||||||
|
Otestuje, že skript běží z konkrétní složky. Zejména použitelné s ``gimli_only`` a ``$TESTWEB``
|
||||||
|
``safe_checkout_branch <větev>``
|
||||||
|
Bezpečně přepne repozitář na jinou větev. Pokud by mělo dojít k přepsání
|
||||||
|
knihovny nebo volajícího make skriptu, vyzve uživatele, aby přepnul ručně.
|
||||||
|
``install_everything``
|
||||||
|
Společná část kódu pro nasazování produkce a testwebu.
|
||||||
|
|
||||||
|
Skripty pro lokální vývoj
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
``make/install_web`` (nebo ekvivalentně ``make/install``)
|
||||||
|
Vytvoří virtualenv a nainstaluje do něj závislosti webu podle ``requirements.txt``. Následně popíše, jak vyrobit zbytek lokálního webu.
|
||||||
|
``make/run``
|
||||||
|
Spustí lokální web (ekvivalentní s ``./manage.py runserver``)
|
||||||
|
``make/schema``
|
||||||
|
Vykreslí závislosti a atributy modelů
|
||||||
|
``make/sync_prod_flatpages``
|
||||||
|
Stáhne z produkce aktuální statické stránky a uloží je do složky ``data/``
|
||||||
|
``make/test``
|
||||||
|
Spustí testy (ekvivalentní s ``./manage.py test -v2``)
|
||||||
|
``make/init_local``
|
||||||
|
Zkratka za posloupnost ``make/install_web``, ``./manage.py testdata``, ``./manage.py loaddata data/*``, ``make/sync_prod_flatpages``
|
||||||
|
|
||||||
|
Práce s testwebem
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
``make/deploy``
|
||||||
|
Nasadí testweb. Volitelně bere jako parametr jméno větve, kterou má nasadit.
|
||||||
|
Rovnou nastaví přihlašování a vygeneruje příslušnou verzi dokumentace `sem <https://mam-test.ks.matfyz.cz/docs>`_.
|
||||||
|
``make/push_compiled_vue_to_test``
|
||||||
|
**Neotestováno** Nahraje Vue z lokálního počítače na testweb. (Gimli často má moc starou verzi Node.js, takže nejde zkompilovat tam)
|
||||||
|
``make/sync_test_db_aggressive``
|
||||||
|
Zkopíruje databázi z produkčního webu.
|
||||||
|
``make/sync_test_media``
|
||||||
|
Zkopíruje média (obrázky, nahrané soubory) z produkčního webu.
|
||||||
|
``make/sync_test``
|
||||||
|
Zkratka za ``make/sync_test_db_aggressive`` + ``make/sync_test_media``.
|
||||||
|
|
||||||
|
Nasazení produkce
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
``make/deploy_prod``. Před samotným nasazením zálohuje databázi a zkontroluje, že se nasazuje větev ``master``.
|
41
docs/sphinx.rst
Normal file
41
docs/sphinx.rst
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
Sphinx na našem webu
|
||||||
|
====================
|
||||||
|
|
||||||
|
Dokumentace se zkompiluje příkazem ``make html`` ve složce ``docs``. (Musíte mít zapnutý virtualenv)
|
||||||
|
|
||||||
|
Složka ``modules`` je automaticiky generována a přegenerovávána. (**Nic v ní neupravovat!**)
|
||||||
|
Jinak všechny rst, co jsou ve složce ``docs`` a jejích podsložkách nezačínajících podtržítkem, budou v dokumentaci a to je přesně to, co editovat pro změnu dokumentace (kromě dokumentace přímo v Pythonu).
|
||||||
|
|
||||||
|
Sphinx se píše v rst: `Návod na syntaxi rst`_ `Cheat sheet`_
|
||||||
|
|
||||||
|
Pokud něco chcete protlačit do bočního meníčka, je potřeba to připsat do souboru ``docs/index.rst`` (Zatím není úplně konsensus nad tím, co tam má a nemá být, takže pokud si nejste jistí, cpěte tam *všechno* ☺)
|
||||||
|
|
||||||
|
To je snad vše, co je potřeba vědět k dokumentaci mamwebu. Následující sekce jsou o tom, co jsem provedl Sphinxu, aby to fungovalo:
|
||||||
|
|
||||||
|
.. _Návod na syntaxi rst: https://sphinx-tutorial.readthedocs.io/step-1/#sections
|
||||||
|
.. _Cheat sheet: https://sphinx-tutorial.readthedocs.io/cheatsheet/
|
||||||
|
|
||||||
|
make html
|
||||||
|
---------
|
||||||
|
``make html`` dělá následující: Vygenerují se rst soubory do modules z pythoní dokumentace pomocí::
|
||||||
|
|
||||||
|
sphinx-apidoc --module-first -o modules .. ../*/migrations --templatedir _templates -f
|
||||||
|
|
||||||
|
- ``--module-first`` říká, že dokumentace modulu má být dřív než to, co obsahuje,
|
||||||
|
- ``-o`` je výstupní složka příkazu,
|
||||||
|
- ``..`` prochází složku mamweb,
|
||||||
|
- ``../*/migrations`` ignoruje migrace
|
||||||
|
- ``--templatedir _templates`` určuje templaty, podle kterých se vyrábí rst z Pythoní dokumentace a struktury složek a souborů,
|
||||||
|
- ``-f`` donutí phinx znovu přegenerovat soubory, protože nepozná, že se nějaká dokumentace změnila)
|
||||||
|
|
||||||
|
Poté se spustí „samotný sphinx“ a vygenerují se soubory v ``_build/html``.
|
||||||
|
|
||||||
|
Templates
|
||||||
|
---------
|
||||||
|
Templaty jsou originální s pár změnami:
|
||||||
|
|
||||||
|
- Změnil jsem nadpisy
|
||||||
|
- Odstranil jsem některá slova v nadpisech (module, package, …)
|
||||||
|
- Odstranil jsem nadpis Subpackages
|
||||||
|
|
||||||
|
přišlo mi to takhle lepší. Ale stále nejsem moc spokojen, protože je to pořád nepřehledné.
|
32
docs/struktura.rst
Normal file
32
docs/struktura.rst
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
Co kde najít (mamweb + django)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Nejdůležitější aplikace z pohledu djanga je ``mamweb``. Tu totiž django pouští
|
||||||
|
a obsahuje tedy nastavení (tam se přidávají ostatní aplikace, včetně těch
|
||||||
|
importovaných z djanga, a nastavují se tam různé věci jak v djangu, tak i naše,
|
||||||
|
například složky, kam se budou věci přidané uživateli ukládat). Dále obsahuje
|
||||||
|
základní urls, udávající, „na jaké adrese co je“. A nakonec obsahuje obecné
|
||||||
|
věci jako chybové hlášky a vzhled M&M stránek (menu, patička, atd.). Aktuálně
|
||||||
|
i veškeré csv.
|
||||||
|
|
||||||
|
Další jsou pak jednotlivé aplikace (pokud něco hledáte, tak zřejmě chcete najít
|
||||||
|
tu aplikaci, která tomu odpovídá, respektive se k ní dostat přes url).
|
||||||
|
|
||||||
|
**TLDR: Nevšímejte si složek data/ seminar/ a souborů přímo v kořenové složce.**
|
||||||
|
Kromě věcí potřebných ke gitu, :doc:`ke spuštění <vyvoj>` a fukci djanga,
|
||||||
|
dalších drobností, lokální databáze a již zmíněných aplikací jsou tu ``data``,
|
||||||
|
kde je takový ten obsah webu, co by se měl dát snadno měnit (tudíž musí být v
|
||||||
|
databázi), tj. statické stránky, menu a obrázky v pozadí menu. Ten je třeba
|
||||||
|
měnit hlavně na produkci a sekundárně tady (může to dělat i newebař a nechcete
|
||||||
|
přepsat jeho práci). Vše, co nejsou aplikace je popsáno :doc:`tady <dalsi_soubory>`.
|
||||||
|
|
||||||
|
Ještě je tu aplikace ``seminar/``, kde bylo původně skoro všechno, a tak nám
|
||||||
|
tam zbývá spoustu historických migrací (čehož se jen tak nezbavíme).
|
||||||
|
|
||||||
|
Základy djanga
|
||||||
|
--------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mamweb je psaný téměř čistě v djangu. Což znamená, že to „co je vidět na stránkách“
|
||||||
|
jsou views.
|
184
docs/vyvoj.rst
Normal file
184
docs/vyvoj.rst
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
Lokální vývoj mamwebu
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Asi hlavní část vývoje většiny webu probíhá lokálně. Každý tak může pracovat na
|
||||||
|
vlastních úpravách nezávisle na ostatních.
|
||||||
|
|
||||||
|
Potřebné vybavení
|
||||||
|
-------
|
||||||
|
|
||||||
|
Tento soupis cílí na Linuxáky. Jistě je
|
||||||
|
spousta dalších možností, které zde nejsou postihnuty – poraď se s webaři,
|
||||||
|
pokud si nejsi jistý. (Speciálně lze nějak vyvíjet na Windows, leč lze často
|
||||||
|
narazit na odlišné chování od Linuxu.)
|
||||||
|
|
||||||
|
Motivace cílení na Linux je to, že Gimli je Linuxový stroj, takže je vývojové
|
||||||
|
prostředí pak podobné produkci a zmenšuje to množství odlišného chování.
|
||||||
|
|
||||||
|
.. TODO: Na dokumentaci odlišného chování (Postgres vs. SQLite, Win vs. Linux, …)
|
||||||
|
by to asi chtělo výhledově separátní stránku, ale teď píšu tuhle :-)
|
||||||
|
|
||||||
|
Nutné
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
- `Git <https://git-scm.com>`_
|
||||||
|
- `Python <https://python.org>`_
|
||||||
|
|
||||||
|
- Ideálně ve verzi 3.9 (to je to, co je aktuálně (2022) na Gimlim)
|
||||||
|
- Včetně pip-u (na Ubuntu balíček ``python3-pip``), venvu (``python3-venv``) a knihoven pro kompilaci
|
||||||
|
Cčkových rozšíření (``python3-dev``)
|
||||||
|
- Knihovna pro práci s PostgreSQL (``libpq-dev``, protože jsou potřeba všechny db backendy)
|
||||||
|
- Webový prohlížeč
|
||||||
|
- \*NIXový shell (typicky ``bash``)
|
||||||
|
|
||||||
|
.. TODO: Pokud tu něco chybí, tak to dopiš :-)
|
||||||
|
|
||||||
|
Kromě toho je potřeba mít účet na `Gitee <https://gitea.ks.matfyz.cz>`_, kde
|
||||||
|
bydlí gitový repozitář s kódem.
|
||||||
|
|
||||||
|
.. tip:: Potřebné balíčky v různých distribucích jsou sepsané v :ref:`tabulce
|
||||||
|
prerekvizit <Alternativní jména balíčků>`.
|
||||||
|
|
||||||
|
Doporučené
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
- Python wheel (možná řeší problémy s potřebou ``-dev`` balíčků…)
|
||||||
|
- Editor / IDE podporující `Editorconfig <https://editorconfig.org/>`_
|
||||||
|
- Uživatelská zkušenost s `produkční verzí webu <https://mam.matfyz.cz>`_
|
||||||
|
- Účet v `Kanci <https://kanboard.ledoian.cz>`_
|
||||||
|
|
||||||
|
.. TODO: A nejspíš další věci, na které jsem si teď nevzpomněl.
|
||||||
|
|
||||||
|
|
||||||
|
Zprovoznění
|
||||||
|
-------
|
||||||
|
|
||||||
|
Nejprve je potřeba stáhnout si repozitář. To se provede příkazem ``git clone
|
||||||
|
https://gitea.ks.matfyz.cz/mam/mamweb.git``, případně ``git clone
|
||||||
|
git@gitea.ks.matfyz.cz:mam/mamweb.git``, pokud už máš nahraný SSH klíč na
|
||||||
|
Giteu. (Obě adresy se dají zkopírovat ze `stránky repozitáře
|
||||||
|
<https://gitea.ks.matfyz.cz/mam/mamweb>`_.) To vyrobí složku ``mamweb``, přepni
|
||||||
|
se do ní (``cd mamweb``)
|
||||||
|
|
||||||
|
O zprovoznění webu se stará skript ``make/install_web``, stačí ho spustit. Ten
|
||||||
|
vytvoří virtualenv (neexistuje-li) a nainstaluje do něj závislosti webu (podle
|
||||||
|
souboru ``requirements.txt``).
|
||||||
|
|
||||||
|
.. FIXME: Novowebaři zmínka o requirements.txt tady moc nepomůže, to má být na
|
||||||
|
stránce o celkové stavbě repozitáře a stacku…
|
||||||
|
|
||||||
|
Následně je potřeba nahrát další data do databáze, což uděláš pomocí příkazů
|
||||||
|
``./manage.py testdata`` a ``./manage.py loaddata data/*``. Skript
|
||||||
|
``make/install_web`` to kdyžtak na konci připomene.
|
||||||
|
|
||||||
|
.. caution:: Zatímco skripty v ``make/`` to nepotřebují, pro použití skriptu
|
||||||
|
``./manage.py`` (a dalších) se potřebuješ přepnout do virtuálního prostředí.
|
||||||
|
To uděláš velmi pravděpodobně spuštěním ``source env/bin/activate``, před
|
||||||
|
začátkem *promptu* by se mělo objevit ``(env)``. Pro opuštění spusť
|
||||||
|
``deactivate``.
|
||||||
|
|
||||||
|
Samotný web se spustí třeba pomocí ``make/run``, nebo ekvivalentně
|
||||||
|
``./manage.py runserver`` a pak je vidět na `<http://127.0.0.1:8000>`_.
|
||||||
|
|
||||||
|
Časté problémy
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
- ``make/install_web`` vypíše ``Error: pg_config executable not found.``:
|
||||||
|
Chybí ``libpq-dev``
|
||||||
|
- Chybová hláška obsahuje ``#include <Python.h>``: chybí ``python3-dev``
|
||||||
|
- Na webu není vidět meníčko: spusť ``./manage.py loaddata data/*``
|
||||||
|
- ``locale.Error: unsupported locale setting``: Chybí podpora pro příslušný
|
||||||
|
jazyk ve tvém systému. Odkomentuj příslušnou lokalizaci v ``/etc/locale.gen``
|
||||||
|
a spusť ``locale-gen`` jako root, tím se to spraví.
|
||||||
|
|
||||||
|
S dalšími problémy se zkus obrátit na další webaře, třeba někdo bude vědět :-)
|
||||||
|
|
||||||
|
Příkazy pro ovládání webu
|
||||||
|
-------
|
||||||
|
|
||||||
|
Příkazy se dělí do několika skupin. Některé souvisí přímo s webem, Djangem,
|
||||||
|
databází a podobně, ty typicky používají ``./manage.py``. Skripty pro
|
||||||
|
obhospodařování repozitáře a webu „zvenku“ typicky bydlí ve složce ``make/``.
|
||||||
|
Ostatní skripty jsou na náhodných místech :-)
|
||||||
|
|
||||||
|
Tady jsou rozebrány jen příkazy relevantní pro lokální web a univerzálně
|
||||||
|
užitečné, ostatní najdeš v :ref:`Skripty pro práci s repozitářem`.
|
||||||
|
|
||||||
|
Make skripty
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
- ``make/install_web`` nainstaluje závislosti webu
|
||||||
|
- ``make/run`` spustí web (ekvivalentní s ``./manage.py runserver``)
|
||||||
|
- ``make/schema`` nakreslí schéma vazeb modelů (může se hodit pro referenci a představu)
|
||||||
|
- ``make/test`` spustí testy (ale moc jich zatím není; ekvivalentní s ``./manage.py test``)
|
||||||
|
- ``make/sync_prod_flatpages`` stáhne statické stránky z produkčního webu a
|
||||||
|
uloží je do souboru v gitu, což umožňuje jejich verzování
|
||||||
|
|
||||||
|
Manage.py skripty
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
.. note:: Je potřeba je spouštět ve virtuálním prostředí, viz výše.
|
||||||
|
|
||||||
|
Všechny skripty kdyžtak mají ``--help``, dá se tak zjistit, co všechno umějí.
|
||||||
|
|
||||||
|
- ``./manage.py testdata`` vygeneruje spíše chudá testovací data, aby bylo na
|
||||||
|
čem testovat web.
|
||||||
|
- ``./manage.py loaddata <soubor/y>`` nahraje data ze souborů do databáze
|
||||||
|
- ``./manage.py dumpdata <model>`` naopak z databáze vyrobí textovou reprezentaci
|
||||||
|
- ``./manage.py shell`` spustí interaktivní pythoní shell, ze kterého lze
|
||||||
|
interagovat s webem / Djangem.
|
||||||
|
- ``./manage.py dbshell`` spustí databázový shell (typicky používá SQL)
|
||||||
|
|
||||||
|
- ``./manage.py makemigrations`` vyrobí popis migrací, ``./manage.py migrate``
|
||||||
|
je spustí, ``showmigrations`` ukáže, které migrace jsou aplikované a které
|
||||||
|
ne.
|
||||||
|
- ``./manage.py runserver_plus`` spouští o něco lepší vývojový server (ale
|
||||||
|
nikdy jsem asi ty lepší featury nepoužil)
|
||||||
|
|
||||||
|
Může se hodit vědět, že spuštění ``./manage.py`` bez parametrů vypíše seznam
|
||||||
|
všech příkazů, které lze spustit.
|
||||||
|
|
||||||
|
Dokumentace djangových příkazů je v `dokumentaci Djanga
|
||||||
|
<https://docs.djangoproject.com/en/3.2/ref/django-admin/#available-commands>`_
|
||||||
|
|
||||||
|
Ostatní užitečné příkazy
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
- ``git status`` je univerzální nápověda na aktuální stav repozitáře a co s tím
|
||||||
|
lze dělat.
|
||||||
|
- ``git clean -fxd`` smaže všechny soubory, které nejsou uložené v gitu (včetně
|
||||||
|
ignorovaných). **Nebezpečný příkaz**, zamysli se, než ho spustíš
|
||||||
|
|
||||||
|
Specifika lokálního webu
|
||||||
|
-------
|
||||||
|
|
||||||
|
Lokální uživatelé
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
Přihlašovací údaje jsou psány jako ``login:heslo``
|
||||||
|
|
||||||
|
- Superuživatel: ``admin:admin``
|
||||||
|
- Orgovské účty: ``o:o``, ``o1:o`` až ``o3:o``
|
||||||
|
- Řešitelské účty: ``r:r``, ``r1:r`` až ``r3:r``
|
||||||
|
|
||||||
|
Všechny tyto účty jsou (?) svázané s nějakými fiktivními osobami, není ale zřejmé se
|
||||||
|
kterými, budeš to muset vyzkoušet a pak tady zdokumentovat :-)
|
||||||
|
|
||||||
|
E-maily
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
Posílání e-mailů se lokálně dá zkoušet, e-mail se vypíše do terminálu, kde je
|
||||||
|
web spuštěn (e.g. pomocí ``make/run``).
|
||||||
|
|
||||||
|
Pruhy
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
To, že má lokální web po stranách zelené pruhy je normální a správně, slouží to
|
||||||
|
k vizuálnímu odlišení lokálního webu.
|
||||||
|
|
||||||
|
.. TODO: Mít někde popis všech tří instancí a tady na něj pak odkázat.
|
||||||
|
.. - Tahák k používání gitových větví: do workflow, ne sem…
|
||||||
|
.. - Užitečné odkazy – kam se kouknout
|
||||||
|
(dohledávání views podle URL, settings_*, )
|
||||||
|
.. - Zpříjemnění práce (ssh-klíče, tea, --help, …)
|
||||||
|
|
173
docs/zapisy/2021-12-06-testovani_dokumentace_codereview.md
Normal file
173
docs/zapisy/2021-12-06-testovani_dokumentace_codereview.md
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# Postup zkrášlení kódu M&Mího webu
|
||||||
|
|
||||||
|
## Obecně o webu
|
||||||
|
|
||||||
|
- Python, Django, spousta nějakých rozšíření, frontend HTML + CSS + trocha JS
|
||||||
|
- Velké břímě historie, kterou nejspíš nechceme zahodit
|
||||||
|
- Změny v M&M někdy dost zamotají potřebný kód (tituly)
|
||||||
|
- Občas je potřeba dělat opravy rychle
|
||||||
|
|
||||||
|
## Aktuální stav
|
||||||
|
|
||||||
|
- Zběsile zbastlený kód
|
||||||
|
- „Co je to ‚single responsibility principle‘?“ ☺
|
||||||
|
- Dost netriviální množství objektů a jejich vazeb
|
||||||
|
- Dost možná do velké míry inherentní složitost
|
||||||
|
- Webaři aktuálně relativně zběhlí v programování (ale je potřeba myslet na to, že to tak být nemusí)
|
||||||
|
- Webaři stárnou (Jethro, Kristý, Anet) a mizí (Pavel, Káťa), je potřeba web připravit na předání
|
||||||
|
- Kód je rozdělený mezi orgy a jeden „nerozumí“ tomu, co druhý napsal (musí to vyčíst z kódu, nezná souvislosti, …)
|
||||||
|
- Noví orgové se aktuálně musí ptát, což je jim nepříjemné a nutí je umět formulovat dotazy
|
||||||
|
|
||||||
|
### Invarianty
|
||||||
|
|
||||||
|
- Není to práce, ale zábava-ish → libovolný proces nesmí být (moc) na obtíž.
|
||||||
|
- I malé nepohodlí je potřeba vyvážit relativně velkým přínosem
|
||||||
|
- nebo dostatečně zřejmou vidinou budoucího pohodlí / minimalizace nepohodlí
|
||||||
|
- Nejsme programátoři, spíš jsme bastlíři kódu (kteří znají rozumnou podmnožinu syntaxe Pythonu)
|
||||||
|
- Zvlášť noví orgové
|
||||||
|
- Nechceme cílit na mega-profi kód, je to nedosažitelný cíl
|
||||||
|
- Nejspíš to do nějaké míry ubastlené bude pořád, ta míra závisí na zkušenosti aktuálních webařů
|
||||||
|
- Nástroje nás nesmí moc mást.
|
||||||
|
- Děláme to zadarmo jeden večer v týdnu
|
||||||
|
- Vývoj jde pomalu, často pomaleji než vývoj knihoven
|
||||||
|
- → kód se rozbíjí i sám
|
||||||
|
- Běží to na Gimlim
|
||||||
|
- Debian (old)stable → nemůžeme používat moc nové featury Pythonu
|
||||||
|
- Aktuálně Python 3.7.3
|
||||||
|
- Webaři jsou náhodně vzniklá skupina lidí.
|
||||||
|
- Různé nástroje, různé operační systémy
|
||||||
|
- Nechceme vynucovat konkrétní metody, multiplatformní nástroje asi požadovat můžeme
|
||||||
|
- Na serveru může běžet cokoliv, co tam jde rozběhnout
|
||||||
|
- Kód by neměl být moc složitý / matoucí / kompaktní (?)
|
||||||
|
- případně fakt hodně okomentovaný
|
||||||
|
|
||||||
|
## O co se snažíme
|
||||||
|
|
||||||
|
- Zpřístupnit vývoj novým webařům
|
||||||
|
- Umožnit chápání i cizího kódu co nejjednodušeji
|
||||||
|
- Nevzít si s sebou implementační tajemství ~~do hrobu~~ pryč z M&Mka
|
||||||
|
|
||||||
|
```graphviz
|
||||||
|
digraph "Závislosti věcí" {
|
||||||
|
ss -> sdil -> doku -> cs;
|
||||||
|
ss -> cit ->ref -> cs;
|
||||||
|
ref -> nrt -> tst -> cs;
|
||||||
|
sdil -> cr -> cs
|
||||||
|
ss -> nrt;
|
||||||
|
ss[label="Současný stav",shape=box];
|
||||||
|
cit[label="čitelný kód"];
|
||||||
|
cs[label="Cílový stav",shape=box];
|
||||||
|
ref[label="refactoring"];
|
||||||
|
nrt[label="nerozbít to"];
|
||||||
|
tst[label="testy"];
|
||||||
|
doku[label="dokumentace (vývojářská)"];
|
||||||
|
sdil[label="chápání kódu ostatních / stávajícího"];
|
||||||
|
cr[label="code review"];
|
||||||
|
nrt,sdil,cit[shape=hexagon];
|
||||||
|
tst,doku,cr[color=blue];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code review
|
||||||
|
|
||||||
|
Aktuálně: Pavel občas z rozmaru čte diffy; párkrát jsme zkoušeli [programovat v páru](https://mam.mff.cuni.cz/wiki/Web/Tipy/PairProgramming), je to relativně časově náročné.
|
||||||
|
|
||||||
|
- Nevynucovat
|
||||||
|
- Primární motivace je umožnit nějak vidět změny a případně k nim dávat komentáře, jak stylu „tohle mi není jasné“, tak i „tohle by chtělo přepsat“.
|
||||||
|
- Chceme hlavně vytvořit příležitost ke čtení cizího kódu a seznamování se s ním (i v zájmu zaučování nových webařů)
|
||||||
|
|
||||||
|
### Názory
|
||||||
|
|
||||||
|
- spíš post-hoc
|
||||||
|
- Možná code-review toho, co jde na produkci
|
||||||
|
- Chceme umět komentovat konkrétní řádky kódu
|
||||||
|
|
||||||
|
- Gitea/gitlab?
|
||||||
|
- Klikátko a barevný řádky a vyhledávání jsou fajn (gitlab, gitea)
|
||||||
|
- Jethro: je fajn umět skočit na definici
|
||||||
|
- Kombinace s CI
|
||||||
|
- Pokud bude gitea v něčem nedostatečná, tak hrozí, že bude potřeba migrovat znovu, což je nepraktické
|
||||||
|
- Gitlab je asi častější než gitea → je lepší názor si na to zvyknout
|
||||||
|
|
||||||
|
__Závěr:__ Zkusíme to hodit do GitLabu (nejspíš veřejného\*), zavedeme pull-requesty do `master` větve, náhodně se budeme přiřazovat a používat ho nějak intuitivně.
|
||||||
|
|
||||||
|
\*: Ve fakultním neumíme přidávat další uživatele, v KAMím zas možná není CI.
|
||||||
|
|
||||||
|
## Testy
|
||||||
|
|
||||||
|
Aktuálně: pár testů na dohromady řádově 4 funkce, drobný pokus o TDD, jenž narazil na úskalí reálného světa. Lokální spuštění testů trvá relativně dlouho, nejspíš kvůli spoustě migrací.
|
||||||
|
|
||||||
|
- Potřebujeme ověřit, že to funguje a že to _pořád_ funguje
|
||||||
|
|
||||||
|
- CI? Coverage?
|
||||||
|
|
||||||
|
### Názory
|
||||||
|
|
||||||
|
- PyTest je fajn
|
||||||
|
- Testovat frontend?
|
||||||
|
- Jethro: při nasazení by se mohly dělat screenshoty celých vybraných stránek přes Selenium (nebo obdobné) a hlásit rozdíly
|
||||||
|
|
||||||
|
__Závěr:__ Backend testujeme PyTestem (`./manage.py test`), u frontendu výhledově zkusíme ty vizuální diffy a pak se uvidí, CI podle webového klikátka na code review. Bylo by dobré mít rozumná testdata, ať se nemusí mockovat moc věcí.
|
||||||
|
|
||||||
|
## Formát kódu
|
||||||
|
|
||||||
|
Aktuálně: Jakýsi coding style zhruba existuje, není popsaný, šíří se lidovou slovesností.
|
||||||
|
|
||||||
|
- Nesmí být striktně vynucovaný
|
||||||
|
- Musel by být hodně nastavitelný
|
||||||
|
- Nechceme mít kód plný `#NOQA: WTF42`
|
||||||
|
- Nejspíš vždycky bude mít false positives (`tvorba.utils.roman_numerals`) i false negatives (`tvorba.models.Cislo.posli_cislo_mailem`)
|
||||||
|
- Možná dobrý sluha, ale určitě špatný pán (also: špatná zkušenost ☺)
|
||||||
|
- __Důsledek:__ Hrozí, že těch falešných varování bude moc, čímž to ztratí smysl úplně
|
||||||
|
- Potenciálně by šlo aplikovat jen lokálně na změny?
|
||||||
|
|
||||||
|
### Názory
|
||||||
|
|
||||||
|
- P: nemyslím si, že zvládneme mít „průhledný kód“ (dostatečně konzistentní kód, aby ho člověk přestal vnímat a spíš viděl myšlenky).
|
||||||
|
|
||||||
|
- P: Kecadla do kódu trochu zavání větším peklem než užitkem (takže black a flake8 jsou ze hry); isort možná dává smysl; je otázka, jestli použít mypy, ale typové značky v kódu spíš chceme (zvlášť u věcí, které nejsou prostě django view – typicky utils.)
|
||||||
|
- J: Divné (=Pavlovo) groupování importů je spíš matoucí, spíš moc nepomáhalo
|
||||||
|
|
||||||
|
- P (doplněno zpětně): pydocstyle vynucuje PEP-257, který se možná tluče se sphinxem…
|
||||||
|
- P (též zpětně): Možná by se mohl dát použít pylint, tomu jde aspoň vysvětlit coding style a nerazí tupě PEP-8, ale nastavovat ho je asi větší porod, než jak moc pomůže…
|
||||||
|
|
||||||
|
__Závěr:__ Kecadla na formát spíš nechceme; isort by mohl být fajn, ale bylo by dobré mít rozdělené bloky „náš kód“, „standardní knihovna“ a „Django a další balíčky z PyPA“; u našeho kódu (utils, obecně ne-Django věci) chceme držet záměr (na úrovni dohody) psát signatury funkcí a v případě jejich přítomnosti se nechat varovat při porušení signatury.
|
||||||
|
|
||||||
|
- P (večerní prokrastinace): Bandit vypadá, že hlásí jen strašně obvious věci by default, nepřijde mi jako moc úžasné vylepšení. Do CI možná dobrý
|
||||||
|
|
||||||
|
## Dokumentace
|
||||||
|
|
||||||
|
Aktuálně: něco málo je na wiki (`/Web/`), občas má nějaká funkce docstring, obecně je toho málo
|
||||||
|
|
||||||
|
### Požadavky
|
||||||
|
|
||||||
|
- Jedno autoritativní místo a dá se najít
|
||||||
|
- Dostatečně „blízko“ kódu
|
||||||
|
- nastavit mindset na psaní dokumentace „rovnou“?
|
||||||
|
- Umožnit i obecný text, ne jen komentáře kódu (modulů, funkcí)
|
||||||
|
|
||||||
|
|
||||||
|
### Bonusy
|
||||||
|
|
||||||
|
- Zajišťování konzistence s uživatelskou dokumentací
|
||||||
|
- aktuálně wiki
|
||||||
|
- Podpora i dalších jazyků (Vue, Javascript, CSS, možná django-templates)
|
||||||
|
|
||||||
|
### Názory
|
||||||
|
|
||||||
|
- Jde to dělat sphinxem
|
||||||
|
- Stínovlas by mohl vědět v CZ.NICu se sphinx jede. Případně zkusit zjistit, co umí jejich Akademie
|
||||||
|
- Free-textová dokumentace (architektura ap.) má být nezávislá na dokumentaci konkrétního kódu, ale je fajn, když se to pak spojí dohromady, jde-li to.
|
||||||
|
- Lepší, když se obojí dá dělat stejným nástrojem
|
||||||
|
- Káťa má někdy pocit, že tráví spoustu času tím, že hledá který soubor vůbec upravit; to má v naší dokumentaci být.
|
||||||
|
|
||||||
|
__Závěr:__ Zkusíme použít sphinx (z nedostatku vlastních zkušeností a kvůli jeho popularitě), když se nám to nebude líbit, tak budeme řešit dál. Bylo by fajn najít nějaký workshop, bude to rychlejší nalejvárna než číst dokumentaci. V krátkodobém výhledu stáhneme vývojovou dokumentaci z webu do repozitáře a zprovozníme někde automatické buildy (aby se dala číst jako člověk a ne jako stroj).
|
||||||
|
|
||||||
|
## Uživatelská dokumentace
|
||||||
|
|
||||||
|
- K: Dělat ji ve spolupráci s těma uživatelema
|
||||||
|
- P: Dávný Hedgedoc může případně sloužit jako základ osnovy
|
||||||
|
- K: Dost možná nevíme, co bolí víc a co míň
|
||||||
|
- Jethro: Musí být na wiki, jinak tím zmateme oržstvo
|
||||||
|
|
||||||
|
__Závěr:__ Dokumentace bude na wiki (<https://mam.mff.cuni.cz/wiki/Web_user/Dokumentace>, výhledově možná ve stejné složce v dalších souborech), bude vznikat podle našich pocitů a dotazů od ostatních; výhledově bude schůzka na ukázání featur nového webu a tam se dosbírají náměty na to, co sepsat.
|
8
docs/zapisy/zapisy.rst
Normal file
8
docs/zapisy/zapisy.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Zápisy
|
||||||
|
======
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: Importy zápisů z Markdownu
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
2021-12-06-testovani_dokumentace_codereview
|
97
docs/zavislosti.rst
Normal file
97
docs/zavislosti.rst
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
Závislosti webu
|
||||||
|
@@@@@@@@@@@@@@@
|
||||||
|
|
||||||
|
Web ke svému běhu potřebuje různé další programy. Tahle stránka se snaží je pokrýt.
|
||||||
|
|
||||||
|
Stránka je koncipována jako odrážkový seznam balíčků pro Ubuntu s případnými
|
||||||
|
komentáři, na konci stránky jsou uvedena :ref:`jména balíčků <Alternativní jména
|
||||||
|
balíčků>` v různých dalších distribucích. (Seznam mj. cílí na lokální
|
||||||
|
rozchození, proto popisuji Ubuntu a ne Debian. I tak se ale snažíme popsat web
|
||||||
|
v úplnosti.)
|
||||||
|
|
||||||
|
.. I use Arch, btw.
|
||||||
|
|
||||||
|
|
||||||
|
Základ webu
|
||||||
|
===========
|
||||||
|
|
||||||
|
- ``python3`` – Ideálně Python 3.9, jenž je na Gimlim
|
||||||
|
- ``python3-pip`` pro instalaci dalších Pythoních balíčků podle ``requirements.txt``
|
||||||
|
- ``python3-venv``
|
||||||
|
- ``gcc`` – kompilace Pythoních knihoven ze zdrojových distribucí (sdist), možná (neotestováno) jde jako alternativu použít ``python3-wheel`` a stahovat bdists
|
||||||
|
- ``python3-dev`` – taktéž
|
||||||
|
- ``libpq-dev`` do třetice…
|
||||||
|
- ``ghostscript`` TODO konverze PDF v korekturovátku
|
||||||
|
- ``pdflatex`` FIXME! generování obálek a stvrzenek
|
||||||
|
- ``git`` – používán :ref:`Make skripty`
|
||||||
|
- ``locales`` pro české formáty
|
||||||
|
|
||||||
|
Nasazení na produkci / testweb
|
||||||
|
==============================
|
||||||
|
|
||||||
|
(nejsou nutně potřeba k provozu lokální instance)
|
||||||
|
|
||||||
|
- ``rsync``
|
||||||
|
- ``pg_utils`` FIXME
|
||||||
|
- ``htpasswd`` FIXME – aby testweb nepoužívali náhodní kolemjdoucí
|
||||||
|
- ``postgresql-server`` TODO
|
||||||
|
- ``acl`` pro nastavování práv přes ``setfacl``
|
||||||
|
|
||||||
|
Pro testweb je potřeba i všechno pro :ref:`dokumentaci <Dokumentace>`, vizte níž.
|
||||||
|
|
||||||
|
Předpokládá se nasazení v uWSGI pod Nginxem a služba běžící pod systemd, nicméně to už je spíš záležitost infrastruktury a ne specifikum mamwebu.
|
||||||
|
|
||||||
|
Dokumentace
|
||||||
|
===========
|
||||||
|
|
||||||
|
- ``make`` pro zbuildění
|
||||||
|
- Pythoní balíčky podle příslušné části ``requirements.txt``
|
||||||
|
|
||||||
|
Vývojové nástroje
|
||||||
|
=================
|
||||||
|
|
||||||
|
(Nejsou nezbytně nutné, ale předpokládáme jejich užitečnost. Mohou se hodit i na produkci.)
|
||||||
|
|
||||||
|
- ``psql`` TODO pro manuální dotazy do PostgreSQL
|
||||||
|
- ``sqlite3`` TODO totéž pro SQLite3
|
||||||
|
- ``ssh``
|
||||||
|
- ``graphviz`` pro vygenerování schématu
|
||||||
|
- ``rsync``
|
||||||
|
- ``ipython3`` – hezčí interaktivní shell (stačí z ``requirements.txt``)
|
||||||
|
|
||||||
|
Potenciální usnadnění života
|
||||||
|
============================
|
||||||
|
|
||||||
|
(Úplně zbytečné, ale sdílíme pozitivní zkušenosti :-))
|
||||||
|
|
||||||
|
- ``tea`` – CLI klient pro Giteu, aby člověk nepotřeboval otevírat web pro založení PR
|
||||||
|
|
||||||
|
|
||||||
|
Alternativní jména balíčků
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Různé distribuce balí SW různě, takže to, co je v jedné distribuci jeden
|
||||||
|
balíček může být v jiné rozděleno do víc. Pro usnadnění nasazení je tady
|
||||||
|
přehled známých alternativních jmen.
|
||||||
|
|
||||||
|
TODO: tabulka není úplná. Pokud na něco narazíte, tak ji prosím doplňte.
|
||||||
|
|
||||||
|
.. admonition:: Jak se pozná, že web funguje, pro účely tabulky?
|
||||||
|
|
||||||
|
Na čistém repozitáři (``git clean -fxd``) a čistém systému spouštíme
|
||||||
|
``make/init_local``. Když to spadne, tak do tabulky zapíšeme, co jsme
|
||||||
|
přiinstalovali. Protože nefunguje synchronizace flatpages (nemáme SSH klíč),
|
||||||
|
``make/init_local`` sestřelíme při pokusu o synchronizaci a vyzkoušíme, že
|
||||||
|
``make/test`` spustí testy.
|
||||||
|
|
||||||
|
.. Grafické tabulky (grid-tables, simple-tables) jsou strašný porod vyrábět, dlabu na to a cpu to do CSV…
|
||||||
|
|
||||||
|
.. csv-table:: Prerekvizity v jednotlivých distribucích
|
||||||
|
:header: Distribuce / OS, Repozitář s Py3.9, venv, py knihovny, PostgreSQL knihovna, poznámky
|
||||||
|
|
||||||
|
Ubuntu 22.10, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, "Je potřeba zapnout zdroj ``universe`` a nainstalovat kompilátor C (``gcc``)?"
|
||||||
|
Linux Mint 21, ??, ``python3-venv``, ``python3-dev``, ``libpq-dev``, ""
|
||||||
|
Archlinux 2022.11.01, AUR, vestavěný, vestavěné, ``postgresql-libs``, "Je potřeba céčkový kompilátor (``gcc``)"
|
||||||
|
openSUSE Leap 15.4, oficiální (``python39``), předinstalovaný?, ``python39-devel``, ??FIXME!!, "Výchozí verze pythonu je 3.6 a ta je moc stará, potřeba instalovat ``gcc``. Nevím jak sehnat pg_config."
|
||||||
|
Debian 11, "oficiální, výchozí", ??, ??, ??, "Určitě to tam rozběhat jde, protože Gimli. Nejspíš bude relativně podobné Ubuntu."
|
||||||
|
|
86
docs/zkratky.rst
Normal file
86
docs/zkratky.rst
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
Zkratky aplikací ve zdrojácích
|
||||||
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||||
|
|
||||||
|
Ve zdrojácích (zejména různé ``models.py``, ``views.py`` ap.) používáme spoustu
|
||||||
|
modelů. Někdy je praktičtější / někdo preferuje importovat celou aplikaci jako
|
||||||
|
jedno jméno a používat modely bez explicitních importů, tj::
|
||||||
|
|
||||||
|
# „hromadné“ importy:
|
||||||
|
import personalni.models as p
|
||||||
|
...
|
||||||
|
p.Organizator.objects.all()
|
||||||
|
|
||||||
|
# „explicitní“ importy:
|
||||||
|
from personalni.models import Organizator
|
||||||
|
...
|
||||||
|
Organizator.objects.all()
|
||||||
|
|
||||||
|
Na webschůzce 2024-11-05 jsme na toto téma otevřeli diskusi, tady je její závěr.
|
||||||
|
|
||||||
|
.. admonition:: Historické okénko
|
||||||
|
:class: note
|
||||||
|
|
||||||
|
Kdysi jsme měli (prakticky) všechny modely v jedné aplikaci, ``seminar``. Na
|
||||||
|
různých místech se pak ``seminar.models`` importovalo typicky jako ``s``
|
||||||
|
nebo jako ``m``.
|
||||||
|
|
||||||
|
Přirozeně, toto už nejde tak snadno, protože už neexistuje jedno místo, ze
|
||||||
|
kterého chceme tahat modely v kódu.
|
||||||
|
|
||||||
|
Konvence
|
||||||
|
========
|
||||||
|
|
||||||
|
Shodli jsme se, že nám rozhodně nevadí explicitní importy a z pohledu
|
||||||
|
čitelnosti je preferujeme. Nicméně při psaní kódu to některým webařům přijde
|
||||||
|
nepohodlné, takže očekáváme, že bude existovat spousta kódu, která bude chtít
|
||||||
|
importovat hromadně. Usnesli jsme se proto na následujících kanonických
|
||||||
|
zkratkách, aby se aplikace alespoň zkracovaly konzistentně.
|
||||||
|
|
||||||
|
V závorkách je uvedené případné jméno, ale nepředpokládáme, že někdo bude danou
|
||||||
|
aplikaci chtít importovat hromadně. Některé aplikace zkratku nemají, ty se
|
||||||
|
importují vždy pod plným jménem nebo explicitně.
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Model
|
||||||
|
- Zkratka
|
||||||
|
* - ``aesop``
|
||||||
|
- ---
|
||||||
|
* - ``api``
|
||||||
|
- --- (``api``)
|
||||||
|
* - ``galerie``
|
||||||
|
- ``g``
|
||||||
|
* - ``header_fotky``
|
||||||
|
- --- (``hdr``)
|
||||||
|
* - ``korektury``
|
||||||
|
- ``kor``
|
||||||
|
* - ``novinky``
|
||||||
|
- ``nov``
|
||||||
|
* - ``odevzdavatko``
|
||||||
|
- ``odev``
|
||||||
|
* - ``personální``
|
||||||
|
- ``pers``/``p``
|
||||||
|
* - ``sifrovacka``
|
||||||
|
- (``sifr``)
|
||||||
|
* - ``soustredeni``
|
||||||
|
- ``sou``
|
||||||
|
* - ``treenode``
|
||||||
|
- ``tn``
|
||||||
|
* - ``tvorba``
|
||||||
|
- ``tv``
|
||||||
|
* - ``various``
|
||||||
|
- ``v``/``var``
|
||||||
|
* - ``vyroci``
|
||||||
|
- ---
|
||||||
|
* - ``vysledkovky``
|
||||||
|
- ``vysl``
|
||||||
|
|
||||||
|
|
||||||
|
.. admonition:: O všech modelech pod jedním jménem
|
||||||
|
:class: warning
|
||||||
|
|
||||||
|
Historické okénko výš zatajuje jeden detail: Při práci v shellu se hodí mít
|
||||||
|
modely k dispozici a nemuset přemýšlet nad dělením do aplikací, takže ve
|
||||||
|
skutečnosti existuje ``mamweb.vsechno``, jenž všechny modely obsahuje.
|
||||||
|
Z čitelnostních důvodů je ale *zakázáno* tento modul používat v kódu.
|
|
@ -1,3 +0,0 @@
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
# Register your models here.
|
|
|
@ -1,5 +0,0 @@
|
||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class FanikConfig(AppConfig):
|
|
||||||
name = 'fanik'
|
|
|
@ -1,31 +0,0 @@
|
||||||
from random import choices
|
|
||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
def fanik_middleware(get_response):
|
|
||||||
# Mapování uživatelských jmen na blbý kecy (+ váhy), obsah odkazu ap.
|
|
||||||
config = {
|
|
||||||
'fanik': {
|
|
||||||
'kecy': [
|
|
||||||
(r'<h1>Co je web?</h1><p>– 8. 11. 2021</p>', 10),
|
|
||||||
(r'<h1>Mě to nezajímá.</h1><p>– 8. 11. 2021</p>', 5),
|
|
||||||
],
|
|
||||||
'link': r'<a href="mailto:web@mam.mff.cuni.cz?subject=Omluva%20webařům&body=Převelice%20se%20omlouvám.">Svůj postoj jsem přehodnotil</a>',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
def middleware(request):
|
|
||||||
if request.user.is_authenticated:
|
|
||||||
username = request.user.username
|
|
||||||
if username in config:
|
|
||||||
kecy = config[username]['kecy']
|
|
||||||
vahy = [x[1] for x in kecy]
|
|
||||||
kec = choices([x[0] for x in kecy], weights=vahy, k=1)[0]
|
|
||||||
template_name = 'universal.html'
|
|
||||||
context = {}
|
|
||||||
context['raw_html'] = kec + config[username]['link']
|
|
||||||
return render(request,template_name,context)
|
|
||||||
|
|
||||||
# Ve všech ostatních případech vrátíme výsledek původního dotazu
|
|
||||||
return get_response(request)
|
|
||||||
|
|
||||||
return middleware
|
|
|
@ -1,3 +0,0 @@
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
# Create your models here.
|
|
|
@ -1,3 +0,0 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
|
@ -1,3 +0,0 @@
|
||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
# Create your views here.
|
|
25
galerie/TODO
25
galerie/TODO
|
@ -1,25 +0,0 @@
|
||||||
========
|
|
||||||
| TODO |
|
|
||||||
|======|
|
|
||||||
|
|
||||||
Aktualni
|
|
||||||
* co s titulni fotkou
|
|
||||||
* do CSS
|
|
||||||
* nahledy
|
|
||||||
* nastylovat tabulku s nahledy
|
|
||||||
* komentare uz na nahledy?
|
|
||||||
* detail
|
|
||||||
* nahledy pred a po
|
|
||||||
* opravit prechodove sipky
|
|
||||||
* vyrobit prechodove sipky ve M&M-stylu
|
|
||||||
|
|
||||||
Dlouhodobe
|
|
||||||
* sipky na prechazeni mezi fotkami
|
|
||||||
* hromadne PRIDANI fotek do jiz existujici galerie
|
|
||||||
|
|
||||||
Fylozoficke
|
|
||||||
* zvolit velikosti velke a male fotky
|
|
||||||
* je potreba i jine razeni nez automaticky podle casu nebo staci podgalerie?
|
|
||||||
* napr. dve hry na dvou ruznych mistech ve stejny cas
|
|
||||||
* fotky od ucastniku ze hry (skupinky se pohybuji ve stejny cas, ale maji sled fotek) -- nestaci to pripadne vrazit do podgalerii?
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#coding: utf-8
|
|
||||||
|
|
||||||
from galerie.models import Obrazek, Galerie
|
from galerie.models import Obrazek, Galerie
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from autocomplete_light import shortcuts as autocomplete_light
|
|
||||||
|
|
||||||
from .models import Obrazek, Galerie
|
|
||||||
from .views import cesta_od_korene
|
|
||||||
|
|
||||||
|
|
||||||
class ObrazekAutocomplete(autocomplete_light.AutocompleteModelBase):
|
|
||||||
|
|
||||||
model = Obrazek
|
|
||||||
search_fields = ['nazev', 'popis']
|
|
||||||
split_words = True
|
|
||||||
limit_choices = 15
|
|
||||||
attrs = {
|
|
||||||
# This will set the input placeholder attribute:
|
|
||||||
'placeholder': u'Obrázek',
|
|
||||||
# This will set the yourlabs.Autocomplete.minimumCharacters
|
|
||||||
# options, the naming conversion is handled by jQuery
|
|
||||||
'data-autocomplete-minimum-characters': 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
choice_html_format = '''
|
|
||||||
<span class="block" data-value="{}">
|
|
||||||
<span class="block">
|
|
||||||
{}
|
|
||||||
<span class="block">{}</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
'''
|
|
||||||
|
|
||||||
def choice_label(self, obrazek):
|
|
||||||
cesta = "/".join(g.nazev for g in cesta_od_korene(obrazek.galerie))
|
|
||||||
popis = "{}<br>".format(obrazek.popis) if obrazek.popis else ""
|
|
||||||
return '{}<br>{}{}'.format(obrazek.nazev, popis, cesta)
|
|
||||||
|
|
||||||
def choice_html(self, obrazek):
|
|
||||||
"""Vrátí kus html i s obrázkem, které se pak ukazuje v nabídce"""
|
|
||||||
return self.choice_html_format.format(self.choice_value(obrazek),
|
|
||||||
obrazek.obrazek_maly_tag(), self.choice_label(obrazek))
|
|
||||||
|
|
||||||
widget_attrs={
|
|
||||||
'data-widget-maximum-values': 15,
|
|
||||||
'class': 'modern-style',
|
|
||||||
}
|
|
||||||
|
|
||||||
autocomplete_light.register(ObrazekAutocomplete)
|
|
|
@ -1,7 +1,4 @@
|
||||||
#coding: utf-8
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from seminar.models import Soustredeni
|
|
||||||
|
|
||||||
class KomentarForm(forms.Form):
|
class KomentarForm(forms.Form):
|
||||||
komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False)
|
komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.11.20 on 2019-04-30 21:40
|
# Generated by Django 1.11.20 on 2019-04-30 21:40
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.11.21 on 2019-06-10 21:58
|
# Generated by Django 1.11.21 on 2019-06-10 21:58
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
13
galerie/migrations/0011_pre_split_soustredeni.py
Normal file
13
galerie/migrations/0011_pre_split_soustredeni.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Generated by Django 4.2.11 on 2024-04-30 21:53
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('galerie', '0010_auto_20200819_0947'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
]
|
20
galerie/migrations/0012_soustredeni_relink.py
Normal file
20
galerie/migrations/0012_soustredeni_relink.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 4.2.11 on 2024-05-01 13:07
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('soustredeni', '0001_split_from_seminar'),
|
||||||
|
('galerie', '0011_pre_split_soustredeni'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='galerie',
|
||||||
|
name='soustredeni',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='soustredeni.soustredeni'),
|
||||||
|
),
|
||||||
|
]
|
14
galerie/migrations/0013_post_split_soustredeni.py
Normal file
14
galerie/migrations/0013_post_split_soustredeni.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Generated by Django 4.2.11 on 2024-05-01 13:35
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('galerie', '0012_soustredeni_relink'),
|
||||||
|
('soustredeni', '0003_post_split_soustredeni'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
]
|
|
@ -1,14 +1,11 @@
|
||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
#from django.db.models import Q
|
#from django.db.models import Q
|
||||||
from django.utils.encoding import force_text
|
|
||||||
from imagekit.models import ImageSpecField
|
from imagekit.models import ImageSpecField
|
||||||
from imagekit.processors import ResizeToFit, Transpose
|
from imagekit.processors import ResizeToFit, Transpose
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from seminar.models import Soustredeni
|
from soustredeni.models import Soustredeni
|
||||||
|
|
||||||
VZDY=0
|
VZDY=0
|
||||||
ORG=1
|
ORG=1
|
||||||
|
|
186
galerie/static/css/galerie.css
Normal file
186
galerie/static/css/galerie.css
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
@charset "utf-8"; /* vynuť utf-8 */
|
||||||
|
|
||||||
|
/* Galerie */
|
||||||
|
|
||||||
|
|
||||||
|
/* velká fotka */
|
||||||
|
/* zmenšování spolu s oknem prohlížeče */
|
||||||
|
.galerie .obrazek, .titulni_obrazek {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
width: auto\9; /* ie8 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.predchozi_obrazek{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
width: 33%;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.predchozi_obrazek:hover{
|
||||||
|
background-image: url("/static/galerie/prvky/predchozi.svg");
|
||||||
|
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
|
||||||
|
background-position: left center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
.dalsi_obrazek{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
width: 33%;
|
||||||
|
height: 100%;
|
||||||
|
left: 67%;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.dalsi_obrazek:hover{
|
||||||
|
background-image: url("/static/galerie/prvky/dalsi.svg");
|
||||||
|
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
|
||||||
|
background-position: right center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
margin: 20px auto 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie h1 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie_hlavicka {
|
||||||
|
margin: 30px auto 30px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popis {
|
||||||
|
margin: 10px 10px 30px 0px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nahoru {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* titulní obrázek hlavní galerie soustředění */
|
||||||
|
|
||||||
|
.galerie_nahledy{
|
||||||
|
/*margin: 1em 0;*/
|
||||||
|
margin: auto;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie_nahledy img {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie_nahledy div.navigace {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie_nahled, .podgalerie_nahled { /* frame */
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
text-align: center;
|
||||||
|
border: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-color: var(--svetla-oranzova);
|
||||||
|
background-color: var(--barva-pozadi);
|
||||||
|
white-space: nowrap;
|
||||||
|
margin: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie_nahled:hover, .podgalerie_nahled:hover {
|
||||||
|
background-color: var(--svetla-oranzova);
|
||||||
|
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
|
||||||
|
color: var(--tmava-oranzova);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vystredeno{ /* helper */
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie_nahled img {
|
||||||
|
vertical-align: middle;
|
||||||
|
max-height: 180px;
|
||||||
|
max-width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie_nahled div {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.podgalerie_nahled img {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
max-height: 125px;
|
||||||
|
max-width: 167px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.podgalerie_nahled .nazev_galerie {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Odkazy na předchozí a následující podgalerii */
|
||||||
|
.galerie_predchozi_nasledujici {
|
||||||
|
overflow: auto;
|
||||||
|
margin: 10px auto 10px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie_predchozi_nasledujici .predchozi {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galerie_predchozi_nasledujici .nasledujici {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* posune kotvu obrázku v galerii o oranžový pruh dolu, aby se pod ním obrázek neschovával */
|
||||||
|
/* https://stackoverflow.com/questions/10732690/offsetting-an-html-anchor-to-adjust-for-fixed-header */
|
||||||
|
.kotva_obrazku {
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 55px; /* viz #title */
|
||||||
|
margin-top: -55px; /* viz #title */
|
||||||
|
}
|
||||||
|
@media(max-width: 860px) {
|
||||||
|
.kotva_obrazku {
|
||||||
|
height: 3em; /* #FIXME nemám páru, jak zjistit výšku toho elementu */
|
||||||
|
margin-top: -3em; /* #FIXME */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* plus a minus tlacitka */
|
||||||
|
.mam-org-only-galerie {
|
||||||
|
background: var(--orgovska-svetla-fialova);
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 10px 10px -20px;
|
||||||
|
border: #333 2px dashed;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mam-org-only-galerie a{
|
||||||
|
padding: 3px 5px;
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background-color: var(--tmava-oranzova);;
|
||||||
|
color: var(--barva-pozadi);
|
||||||
|
float: left;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base.html" %}
|
{% extends "galerie/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
{% block nadpis1a %}
|
{% block nadpis1a %}
|
||||||
|
@ -62,11 +62,12 @@
|
||||||
</div>
|
</div>
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endif%}
|
{% endif%}
|
||||||
|
<span id="nahoru" class="kotva_obrazku"></span>
|
||||||
<img src="{{obrazek.obrazek_stredni.url}}"
|
<img src="{{obrazek.obrazek_stredni.url}}"
|
||||||
height="{{vyska}}"
|
height="{{vyska}}"
|
||||||
width="{{sirka}}"
|
width="{{sirka}}"
|
||||||
alt="{{obrazek.popis}}"
|
alt="{{obrazek.popis}}"
|
||||||
class="obrazek" id="nahoru">
|
class="obrazek">
|
||||||
|
|
||||||
{% if obrazky_dalsi %}
|
{% if obrazky_dalsi %}
|
||||||
{% with obrazky_dalsi|first as dalsi_obrazek %}
|
{% with obrazky_dalsi|first as dalsi_obrazek %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base.html" %}
|
{% extends "galerie/base.html" %}
|
||||||
|
|
||||||
{% block nadpis1a %}
|
{% block nadpis1a %}
|
||||||
Galerie {{galerie.nazev}}
|
Galerie {{galerie.nazev}}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
{% extends "base.html" %}
|
{% extends "galerie/base.html" %}
|
||||||
|
|
||||||
{% block title %}{% block nadpis1a %}
|
|
||||||
Vytvářím novou galerii
|
|
||||||
{% endblock %}{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h2> Vytváření nové galerie </h2>
|
<h2>
|
||||||
|
{% block nadpis1a %}
|
||||||
|
Vytváření nové galerie
|
||||||
|
{% endblock %}
|
||||||
|
</h2>
|
||||||
|
|
||||||
<h3> Vytvářím galerii k soustředění {{soustredeni}} jako {{galerie_text}}</h3>
|
<h3> Vytvářím galerii k soustředění {{soustredeni}} jako {{galerie_text}}</h3>
|
||||||
|
|
||||||
|
|
6
galerie/templates/galerie/base.html
Normal file
6
galerie/templates/galerie/base.html
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block custom_css %}
|
||||||
|
<link href="{% static 'css/galerie.css' %}?version=1" rel="stylesheet">
|
||||||
|
{% endblock %}
|
|
@ -1,7 +1,5 @@
|
||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from seminar.utils import org_required
|
from personalni.utils import org_required
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
# coding: utf-8
|
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from django.http import HttpResponse, Http404
|
from django.http import HttpResponse, Http404
|
||||||
|
@ -8,7 +6,7 @@ from django.template import RequestContext
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from galerie.models import Obrazek, Galerie
|
from galerie.models import Obrazek, Galerie
|
||||||
from seminar.models import Soustredeni
|
from soustredeni.models import Soustredeni
|
||||||
from galerie.forms import KomentarForm, NewGalerieForm
|
from galerie.forms import KomentarForm, NewGalerieForm
|
||||||
|
|
||||||
def zobrazit(galerie, request):
|
def zobrazit(galerie, request):
|
||||||
|
@ -24,7 +22,7 @@ def zobrazit(galerie, request):
|
||||||
def cesta_od_korene(g):
|
def cesta_od_korene(g):
|
||||||
"""Vrátí seznam galerií od kořene ke g"""
|
"""Vrátí seznam galerií od kořene ke g"""
|
||||||
cesta = []
|
cesta = []
|
||||||
while g != None:
|
while g is not None:
|
||||||
cesta.append(g)
|
cesta.append(g)
|
||||||
g = g.galerie_up
|
g = g.galerie_up
|
||||||
return reversed(cesta)
|
return reversed(cesta)
|
||||||
|
@ -53,7 +51,7 @@ def nahled(request, pk, soustredeni):
|
||||||
for g in sourozenci:
|
for g in sourozenci:
|
||||||
if g.pk == galerie.pk:
|
if g.pk == galerie.pk:
|
||||||
predchozi = minuly
|
predchozi = minuly
|
||||||
if minuly != None and minuly.pk == galerie.pk:
|
if minuly is not None and minuly.pk == galerie.pk:
|
||||||
nasledujici = g
|
nasledujici = g
|
||||||
break
|
break
|
||||||
minuly = g
|
minuly = g
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
"""
|
||||||
|
Aplikace umožňující „na uživatelské úrovni“ měnit obrázek v pozadí meníčka.
|
||||||
|
|
||||||
|
Umožňuje uložit obrázek a následně popsat, na kterých stránkách (podle url)
|
||||||
|
a v který čas (den/noc) se má zobrazovat.
|
||||||
|
"""
|
|
@ -4,7 +4,11 @@ import header_fotky.models as m
|
||||||
|
|
||||||
|
|
||||||
class FotkaPozadiAdmin(ModelAdmin):
|
class FotkaPozadiAdmin(ModelAdmin):
|
||||||
|
"""
|
||||||
|
Nastaví čas vložení (:attr:`~header_fotky.models.FotkaHeader.cas`) jako
|
||||||
|
readonly = neměnitelný
|
||||||
|
"""
|
||||||
readonly_fields = ['cas']
|
readonly_fields = ['cas']
|
||||||
|
|
||||||
admin.site.register(m.FotkaHeader, FotkaPozadiAdmin)
|
admin.site.register(m.FotkaHeader, FotkaPozadiAdmin)
|
||||||
admin.site.register(m.FotkaUrlVazba)
|
admin.site.register(m.FotkaUrlVazba)
|
||||||
|
|
|
@ -3,3 +3,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
class HeaderFotkyConfig(AppConfig):
|
class HeaderFotkyConfig(AppConfig):
|
||||||
name = 'header_fotky'
|
name = 'header_fotky'
|
||||||
|
verbose_name = 'Fotky v záhlaví'
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
"""
|
||||||
|
Context processory lze přidat do djanga v :mod:`~mamweb.settings` a dělají to,
|
||||||
|
že do contextu (tj. to, z čeho se např. berou proměnné v templatech) libovolné
|
||||||
|
stránky přidají další věci.
|
||||||
|
"""
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
@ -8,38 +12,46 @@ from header_fotky.models import FotkaUrlVazba
|
||||||
|
|
||||||
|
|
||||||
def vzhled(request):
|
def vzhled(request):
|
||||||
''' Podle casu prida do templatu, zdali je nebo neni noc '''
|
"""
|
||||||
hodin = datetime.now().hour
|
Podle času přidá do contextu, zdali je nebo není noc. Dále podle dení
|
||||||
if (hodin <= 6) or (hodin >= 20):
|
doby a url přidá do contextu správnou fotku.
|
||||||
noc = True
|
|
||||||
nedoba = 'den'
|
|
||||||
doba = 'noc'
|
|
||||||
else:
|
|
||||||
noc = False
|
|
||||||
nedoba = 'noc'
|
|
||||||
doba = 'den'
|
|
||||||
url = request.path
|
|
||||||
|
|
||||||
fotky = FotkaUrlVazba.objects.exclude(denni_doba=nedoba)
|
url adresu nejprve vyzkouší celou, pak postupně odřezává věci za
|
||||||
fotka = None
|
lomítkem, dokud nenajde url, pro kterou existuje alespoň jedna fotka.
|
||||||
|
Z fotek pro toto url zkusí vybrat tu ve správné denní době a až poté
|
||||||
|
libovolnou. (Z více možných fotek pro 1 url a 1 dobu vybírá náhodně.)
|
||||||
|
"""
|
||||||
|
hodin = datetime.now().hour
|
||||||
|
if (hodin <= 6) or (hodin >= 20):
|
||||||
|
noc = True
|
||||||
|
nedoba = 'den'
|
||||||
|
doba = 'noc'
|
||||||
|
else:
|
||||||
|
noc = False
|
||||||
|
nedoba = 'noc'
|
||||||
|
doba = 'den'
|
||||||
|
url = request.path
|
||||||
|
|
||||||
# TODO rychlejší patternmatch?
|
fotky = FotkaUrlVazba.objects.exclude(denni_doba=nedoba)
|
||||||
while (fotka is None) and (url != ''):
|
fotka = None
|
||||||
presne = fotky.filter(url__exact=url)
|
|
||||||
if presne.count() > 0:
|
|
||||||
presne_doba = presne.filter(denni_doba=doba)
|
|
||||||
if presne_doba.count() > 0:
|
|
||||||
fotka = random.choice(presne_doba).url_fotky()
|
|
||||||
else:
|
|
||||||
fotka = random.choice(presne).url_fotky()
|
|
||||||
|
|
||||||
url = url[:-1]
|
# TODO rychlejší patternmatch?
|
||||||
index = url.rfind('/')
|
while (fotka is None) and (url != ''):
|
||||||
if index != -1:
|
presne = fotky.filter(url__exact=url)
|
||||||
url = url[:index+1]
|
if presne.count() > 0:
|
||||||
|
presne_doba = presne.filter(denni_doba=doba)
|
||||||
|
if presne_doba.count() > 0:
|
||||||
|
fotka = random.choice(presne_doba).url_fotky()
|
||||||
|
else:
|
||||||
|
fotka = random.choice(presne).url_fotky()
|
||||||
|
|
||||||
if fotka is None:
|
url = url[:-1]
|
||||||
fotka = settings.STATIC_URL + "images/header/vikendovka.jpg"
|
index = url.rfind('/')
|
||||||
|
if index != -1:
|
||||||
|
url = url[:index+1]
|
||||||
|
|
||||||
return {'noc': noc, 'fotka': fotka}
|
if fotka is None:
|
||||||
|
fotka = settings.STATIC_URL + "images/header/vikendovka.jpg"
|
||||||
|
|
||||||
|
return {'noc': noc, 'fotka': fotka}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.utils import timezone
|
||||||
|
|
||||||
|
|
||||||
class FotkaHeader(models.Model):
|
class FotkaHeader(models.Model):
|
||||||
|
""" fotka pro :mod:`fotka_header`, konkrétně :class:`~fotka_header.models.FotkaUrlVazba` """
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['-cas']
|
ordering = ['-cas']
|
||||||
db_table = 'fotky_header'
|
db_table = 'fotky_header'
|
||||||
|
@ -11,27 +12,34 @@ class FotkaHeader(models.Model):
|
||||||
verbose_name_plural = u'fotky do pozadí menu'
|
verbose_name_plural = u'fotky do pozadí menu'
|
||||||
|
|
||||||
cas = models.DateTimeField(u'čas vložení fotky', default=timezone.now, help_text='Čas vložení fotky')
|
cas = models.DateTimeField(u'čas vložení fotky', default=timezone.now, help_text='Čas vložení fotky')
|
||||||
|
""" čas vložení fotky """
|
||||||
|
|
||||||
nazev = models.CharField(
|
nazev = models.CharField(
|
||||||
u'název fotky', null=False, blank=False, unique=True, primary_key=True,
|
u'název fotky', null=False, blank=False, unique=True, primary_key=True,
|
||||||
max_length=50, help_text='Název např. archiv_noc'
|
max_length=50, help_text='Název např. archiv_noc'
|
||||||
)
|
)
|
||||||
|
""" jméno fotky na webu """
|
||||||
|
|
||||||
fotka = models.ImageField(upload_to='header', null=False, blank=False)
|
fotka = models.ImageField(upload_to='header', null=False, blank=False)
|
||||||
|
""" soubor fotky (Nahrává se automaticky do složky ``media``.) """
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.nazev
|
return self.nazev
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
""" kontroluje, zda sedí poměr stran """
|
||||||
if not self.fotka:
|
if not self.fotka:
|
||||||
raise ValidationError("Chybí obrázek")
|
raise ValidationError("Chybí obrázek")
|
||||||
""" Kontroluje, zda sedí poměr stran """
|
|
||||||
if abs(self.fotka.width - (self.fotka.height * 970 / 350)) > 2:
|
if abs(self.fotka.width - (self.fotka.height * 970 / 350)) > 2:
|
||||||
raise ValidationError("Obrázek by měl mít rozměry 970w na 350h, nebo alespoň podobný poměr stran.")
|
raise ValidationError("Obrázek by měl mít rozměry 970w na 350h, nebo alespoň podobný poměr stran.")
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
|
|
||||||
class FotkaUrlVazba(models.Model):
|
class FotkaUrlVazba(models.Model):
|
||||||
|
"""
|
||||||
|
spojení :class:`~fotka_header.models.FotkaHeader` a url
|
||||||
|
(resp. „prefixu“ url), na které má být zobrazována
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['url']
|
ordering = ['url']
|
||||||
db_table = 'fotky_url_vazby'
|
db_table = 'fotky_url_vazby'
|
||||||
|
@ -42,11 +50,13 @@ class FotkaUrlVazba(models.Model):
|
||||||
u'URL', blank=True, null=False, max_length=100,
|
u'URL', blank=True, null=False, max_length=100,
|
||||||
help_text='url prefix stránek např: /archiv/ nebo /'
|
help_text='url prefix stránek např: /archiv/ nebo /'
|
||||||
)
|
)
|
||||||
|
""" url prefix stránek, kde má být fotka zobrazena, např: /archiv/ nebo / """
|
||||||
|
|
||||||
fotka = models.ForeignKey(
|
fotka = models.ForeignKey(
|
||||||
FotkaHeader, blank=False, null=False, verbose_name='fotka',
|
FotkaHeader, blank=False, null=False, verbose_name='fotka',
|
||||||
on_delete=models.CASCADE
|
on_delete=models.CASCADE
|
||||||
)
|
)
|
||||||
|
""" :class:`~fotka_header.models.FotkaHeader`, která má být zobrazována """
|
||||||
|
|
||||||
DOBA_DEN = 'den'
|
DOBA_DEN = 'den'
|
||||||
DOBA_NOC = 'noc'
|
DOBA_NOC = 'noc'
|
||||||
|
@ -57,9 +67,11 @@ class FotkaUrlVazba(models.Model):
|
||||||
(DOBA_OBOJI, 'Zobrazovat pořád')]
|
(DOBA_OBOJI, 'Zobrazovat pořád')]
|
||||||
|
|
||||||
denni_doba = models.CharField('denní doba', max_length=16, choices=DOBA_CHOICES, blank=False, default=DOBA_OBOJI)
|
denni_doba = models.CharField('denní doba', max_length=16, choices=DOBA_CHOICES, blank=False, default=DOBA_OBOJI)
|
||||||
|
""" dení doba, kdy tam má být zobrazována """
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.url
|
return self.url
|
||||||
|
|
||||||
def url_fotky(self):
|
def url_fotky(self):
|
||||||
|
""" vrací url fotky (tj. url, kde reálně získám soubor fotky) """
|
||||||
return self.fotka.fotka.url
|
return self.fotka.fotka.url
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
- korektura potrebuje reakci
|
|
||||||
+ komentáře fixně na username
|
|
||||||
- používat skutečné jméno?
|
|
||||||
- vyžádat pozornost autora obsahu
|
|
||||||
- zvednout upload limit na 5MB
|
|
||||||
- sbalit a rozbalit korekturu
|
|
||||||
- nahrávání jiných věcí než PDF - kontrolovat?
|
|
||||||
- stylování
|
|
||||||
- seznam PDF - co zobrazovat?
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
"""
|
||||||
|
Seznam pdf k opravě a `opraf`_ v djangu místo PHP.
|
||||||
|
|
||||||
|
.. _opraf: https://github.com/vitstradal/opraf
|
||||||
|
"""
|
|
@ -1,14 +1,23 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from reversion.admin import VersionAdmin
|
from reversion.admin import VersionAdmin
|
||||||
from korektury.models import KorekturovanePDF
|
from korektury.models import KorekturovanePDF, Oprava, KorekturaTag
|
||||||
|
|
||||||
|
from django.core.mail import EmailMessage
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
# Register your models here.
|
|
||||||
class KorekturovanePDFAdmin(VersionAdmin):
|
class KorekturovanePDFAdmin(VersionAdmin):
|
||||||
|
"""
|
||||||
|
nastaví čas vložení (:attr:`~koretkury.models.KorekturovanePDF.cas`) a počet
|
||||||
|
stran (:attr:`~koretkury.models.KorekturovanePDF.stran`) jako readonly =
|
||||||
|
neměnitelný
|
||||||
|
|
||||||
|
Při prvním uložení pošle e-mail.
|
||||||
|
"""
|
||||||
|
|
||||||
readonly_fields = ['cas', 'stran']
|
readonly_fields = ['cas', 'stran']
|
||||||
|
|
||||||
def get_readonly_fields(self, request, obj=None):
|
def get_readonly_fields(self, request, obj=None):
|
||||||
|
""" Když pdf existuje, tak nedovolím měnit ani pdf."""
|
||||||
if obj:
|
if obj:
|
||||||
return self.readonly_fields + ['pdf']
|
return self.readonly_fields + ['pdf']
|
||||||
return self.readonly_fields
|
return self.readonly_fields
|
||||||
|
@ -16,11 +25,48 @@ class KorekturovanePDFAdmin(VersionAdmin):
|
||||||
fieldsets = [
|
fieldsets = [
|
||||||
(None,
|
(None,
|
||||||
{'fields':
|
{'fields':
|
||||||
['pdf', 'cas', 'org', 'stran', 'nazev', 'komentar']}),
|
['pdf', 'cas', 'stran', 'nazev', 'orgove', 'komentar', 'poslat_mail']}),
|
||||||
# (u'PDF', {'fields': ['pdf']}),
|
# (u'PDF', {'fields': ['pdf']}),
|
||||||
]
|
]
|
||||||
list_display = ['nazev', 'cas', 'stran', 'org']
|
list_display = ['nazev', 'cas', 'stran']
|
||||||
list_filter = []
|
list_filter = []
|
||||||
search_fields = []
|
search_fields = []
|
||||||
|
autocomplete_fields = ['orgove']
|
||||||
|
|
||||||
|
def save_model(self, request, obj, form, change):
|
||||||
|
"""
|
||||||
|
Pokud je soubor nový a má se poslat e-mail, tak pošle e-mail o novém pdf.
|
||||||
|
"""
|
||||||
|
super().save_model(request, obj, form, change)
|
||||||
|
if not change and obj.poslat_mail: # Je nový a má se poslat mail
|
||||||
|
odkaz = request.build_absolute_uri(reverse('korektury', kwargs={'pdf': obj.id}))
|
||||||
|
odesilatel = 'korekturovatko-nove-pdf@mam.mff.cuni.cz'
|
||||||
|
prijemce = 'org@mam.mff.cuni.cz'
|
||||||
|
predmet = f'Nové korektury: {obj.nazev}'
|
||||||
|
text = f'''\
|
||||||
|
V korekturovátku se objevil nový soubor: {obj.nazev}
|
||||||
|
{odkaz}
|
||||||
|
|
||||||
|
Popis souboru:
|
||||||
|
{obj.komentar}
|
||||||
|
|
||||||
|
---
|
||||||
|
S pozdravem a korekturám zdar!
|
||||||
|
Korekturovátko
|
||||||
|
'''
|
||||||
|
EmailMessage(
|
||||||
|
subject=predmet,
|
||||||
|
body=text,
|
||||||
|
from_email=odesilatel,
|
||||||
|
to=[prijemce],
|
||||||
|
).send()
|
||||||
|
|
||||||
admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin)
|
admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin)
|
||||||
|
|
||||||
|
|
||||||
|
class OpravaAdmin(admin.ModelAdmin):
|
||||||
|
model = Oprava
|
||||||
|
filter_horizontal = ("informovani_orgove", "tagy",)
|
||||||
|
|
||||||
|
admin.site.register(Oprava, OpravaAdmin)
|
||||||
|
admin.site.register(KorekturaTag)
|
||||||
|
|
7
korektury/api/apps.py
Normal file
7
korektury/api/apps.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ApiConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'korektury.api'
|
||||||
|
label = 'korektury_api' # Protože jedno api už máme.
|
11
korektury/api/urls.py
Normal file
11
korektury/api/urls.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from django.urls import path
|
||||||
|
from personalni.utils import org_required
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('<int:pdf_id>/stav', org_required(views.korektury_stav_view), name='korektury_api_pdf_stav'),
|
||||||
|
path('oprava/stav', org_required(views.oprava_stav_view), name='korektury_api_oprava_stav'),
|
||||||
|
path('<int:pdf_id>/opravy_a_komentare', org_required(views.opravy_a_komentare_view), name='korektury_api_opravy_a_komentare'),
|
||||||
|
path('oprava/smaz', org_required(views.oprava_smaz_view), name='korektury_api_oprava_smaz'),
|
||||||
|
path('komentar/smaz', org_required(views.komentar_smaz_view), name='korektury_api_komentar_smaz'),
|
||||||
|
]
|
129
korektury/api/views.py
Normal file
129
korektury/api/views.py
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
|
from django.http import JsonResponse, HttpResponse
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.utils.html import linebreaks
|
||||||
|
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from korektury.utils import send_email_notification_komentar
|
||||||
|
from korektury.models import Oprava, KorekturovanePDF, Komentar, KorekturaTag
|
||||||
|
from personalni.models import Organizator
|
||||||
|
|
||||||
|
|
||||||
|
def korektury_stav_view(request, pdf_id: int, **kwargs):
|
||||||
|
q = request.POST
|
||||||
|
pdf = get_object_or_404(KorekturovanePDF, id=pdf_id)
|
||||||
|
status = q.get('state')
|
||||||
|
if status is not None:
|
||||||
|
assert status in KorekturovanePDF.STATUS.values
|
||||||
|
pdf.status = status
|
||||||
|
pdf.save()
|
||||||
|
return JsonResponse({'status': pdf.status})
|
||||||
|
|
||||||
|
|
||||||
|
def oprava_stav_view(request, **kwargs):
|
||||||
|
q = request.POST
|
||||||
|
op_id_str = q.get('id')
|
||||||
|
assert op_id_str is not None
|
||||||
|
op_id = int(op_id_str)
|
||||||
|
op = get_object_or_404(Oprava, id=op_id)
|
||||||
|
status = q.get('action')
|
||||||
|
if status is not None:
|
||||||
|
assert status in Oprava.STATUS.values
|
||||||
|
op.status = status
|
||||||
|
op.save()
|
||||||
|
return JsonResponse({'status': op.status})
|
||||||
|
|
||||||
|
def oprava_smaz_view(request, **kwargs):
|
||||||
|
q = request.POST
|
||||||
|
op_id_str = q.get('oprava_id')
|
||||||
|
assert op_id_str is not None
|
||||||
|
op_id = int(op_id_str)
|
||||||
|
oprava = get_object_or_404(Oprava, id=op_id)
|
||||||
|
oprava.delete()
|
||||||
|
return HttpResponse(status=HTTPStatus.NO_CONTENT)
|
||||||
|
|
||||||
|
def komentar_smaz_view(request, **kwargs):
|
||||||
|
q = request.POST
|
||||||
|
kom_id_str = q.get('komentar_id')
|
||||||
|
assert kom_id_str is not None
|
||||||
|
kom_id = int(kom_id_str)
|
||||||
|
komentar = get_object_or_404(Komentar, id=kom_id)
|
||||||
|
komentar.delete()
|
||||||
|
return HttpResponse(status=HTTPStatus.NO_CONTENT)
|
||||||
|
|
||||||
|
class KomentarSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Komentar
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
ret = super().to_representation(instance)
|
||||||
|
ret["autor"] = str(instance.autor)
|
||||||
|
ret["text"] = linebreaks(ret["text"], autoescape=True) # Autora není třeba escapovat, ten se vkládá jako text.
|
||||||
|
return ret
|
||||||
|
|
||||||
|
class KorekturaTagSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = KorekturaTag
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class OpravaSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Oprava
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
ret = super().to_representation(instance)
|
||||||
|
ret["komentare"] = [KomentarSerializer(komentar).data for komentar in instance.komentar_set.all()]
|
||||||
|
ret["tagy"] = [KorekturaTagSerializer(tag).data for tag in instance.tagy.all()]
|
||||||
|
return ret
|
||||||
|
|
||||||
|
# komentar_set = serializers.ListField(child=KomentarSerializer())
|
||||||
|
|
||||||
|
def opravy_a_komentare_view(request, pdf_id: int, **kwargs):
|
||||||
|
if request.method == 'POST':
|
||||||
|
q = request.POST
|
||||||
|
|
||||||
|
x = int(q.get('x'))
|
||||||
|
y = int(q.get('y'))
|
||||||
|
img_id = int(q.get('img_id'))
|
||||||
|
oprava_id = int(q.get('oprava_id'))
|
||||||
|
komentar_id = int(q.get('komentar_id'))
|
||||||
|
text = q.get('text')
|
||||||
|
|
||||||
|
# prirazeni autora podle prihlaseni
|
||||||
|
autor_user = request.user
|
||||||
|
# pokud existuje ucet (user), ale neni to organizator = 403
|
||||||
|
autor = Organizator.objects.filter(osoba__user=autor_user).first()
|
||||||
|
|
||||||
|
if komentar_id != -1:
|
||||||
|
komentar = get_object_or_404(Komentar, id=komentar_id)
|
||||||
|
komentar.text = text
|
||||||
|
komentar.autor = autor
|
||||||
|
komentar.save()
|
||||||
|
else:
|
||||||
|
if oprava_id != -1:
|
||||||
|
oprava = get_object_or_404(Oprava, id=oprava_id)
|
||||||
|
else:
|
||||||
|
pdf = get_object_or_404(KorekturovanePDF, id=pdf_id)
|
||||||
|
oprava = Oprava.objects.create(
|
||||||
|
pdf=pdf,
|
||||||
|
strana=img_id,
|
||||||
|
x=x,
|
||||||
|
y=y,
|
||||||
|
)
|
||||||
|
|
||||||
|
tagy_raw = q.get('tagy')
|
||||||
|
if tagy_raw != "":
|
||||||
|
tagy = list(map(int, tagy_raw.split(",")))
|
||||||
|
oprava.tagy.add(*KorekturaTag.objects.filter(id__in=tagy))
|
||||||
|
Komentar.objects.create(oprava=oprava, autor=autor, text=text)
|
||||||
|
send_email_notification_komentar(oprava, autor, request)
|
||||||
|
|
||||||
|
|
||||||
|
opravy = Oprava.objects.filter(pdf=pdf_id).all()
|
||||||
|
# Serializovat list je prý security vulnerability, tedy je přidán slovník pro bezpečnost
|
||||||
|
return JsonResponse({"context": [OpravaSerializer(oprava).data for oprava in opravy]})
|
|
@ -1,13 +0,0 @@
|
||||||
from django import forms
|
|
||||||
|
|
||||||
class OpravaForm(forms.Form):
|
|
||||||
text = forms.CharField(max_length=256)
|
|
||||||
autor = forms.CharField(max_length=20)
|
|
||||||
x = forms.IntegerField()
|
|
||||||
y = forms.IntegerField()
|
|
||||||
scroll = forms.CharField(max_length=256)
|
|
||||||
pdf = forms.CharField(max_length=256)
|
|
||||||
img_id = forms.CharField(max_length=256)
|
|
||||||
id = forms.CharField(max_length=256)
|
|
||||||
action = forms.CharField(max_length=256)
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
def transform_autor(apps, schema_editor):
|
def transform_autor(apps, schema_editor):
|
||||||
print
|
|
||||||
Organizator = apps.get_model('seminar', 'Organizator')
|
Organizator = apps.get_model('seminar', 'Organizator')
|
||||||
|
|
||||||
# preorgovani oprav
|
# preorgovani oprav
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue