Compare commits
860 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 | |||
315dc97635 | |||
![]() |
7c90c1ef5e | ||
![]() |
5abd93d27f | ||
![]() |
5cfadf9236 | ||
![]() |
0458abb419 | ||
![]() |
f6d939fc31 | ||
![]() |
323477dbf2 | ||
![]() |
d80babfd73 | ||
![]() |
a9e7cd7af2 | ||
376cc0d7e5 | |||
c3728750f7 | |||
39c37c0c73 | |||
![]() |
4f7c4057ea | ||
![]() |
657e73f2f0 | ||
![]() |
8b36e79f04 | ||
![]() |
9f78963e7f | ||
![]() |
75f388ddfb | ||
![]() |
e3ebb925e1 | ||
fd3df6c344 | |||
7ccaf87dfc |
665 changed files with 62490 additions and 101999 deletions
|
@ -1,17 +1,20 @@
|
|||
# Univerzální popis našich konvencí pro nastavení editorů.
|
||||
# Vizte https://editorconfig.org pro detaily
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
# Unix-y lines
|
||||
# Unixové řádky
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{py,css}]
|
||||
indent_style = tab
|
||||
# I do not think we prescribe, how big a tab is.
|
||||
# Nenařizujeme konkrétní šířku tabulátoru
|
||||
indent_size = unset
|
||||
|
||||
# Migrations are auto-generated and thus follow PEP-8, let's not fight with that
|
||||
# Automaticky generované migrace dodržují PEP-8, nemá smysl s tím moc bojovat.
|
||||
[*/migrations/*.py]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
|
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -31,9 +31,15 @@ TODO
|
|||
# reversion kvůli historii objektů v 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
|
||||
.idea
|
||||
|
||||
# dokumentace
|
||||
docs/_build
|
||||
docs/modules
|
||||
# Mac users
|
||||
.DS_Store
|
||||
|
|
159
Makefile
159
Makefile
|
@ -1,154 +1,9 @@
|
|||
PYTHON ?= python3
|
||||
VENV ?= ${PYTHON} -m venv
|
||||
# Všechny flagy, které se s venvem/virtualenvem/... mají volat patří sem. Volá se "${VENV} cesta"
|
||||
VENV_PATH ?= env
|
||||
# Musí být definovaná, i kdyby to měla být "."
|
||||
# Existence tohohle Makefile je tu jen proto, aby fungovala svalová paměť. Pokud můžete, použijte rovnou `make/…`
|
||||
%:
|
||||
# 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:
|
||||
make/$*
|
||||
|
||||
.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)
|
||||
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
|
||||
# Pro vygenerování tesdat spusť ./manage.py testdata
|
||||
# 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; . env/bin/activate; ./manage.py dumpdata flatpages --indent=2 > flat.json; ./fix_json.py flat.json flat_fixed.json"
|
||||
rsync -ave ssh mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/flat_fixed.json data/flat.json
|
||||
@echo "Applying downloaded flatpages."
|
||||
./manage.py loaddata data/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 (with drop) test database with production database
|
||||
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
|
||||
psql mam_test -c 'DROP OWNED BY "mam-web";'
|
||||
pg_restore -c --if-exists -d mam_test dump-prod.sql
|
||||
rm dump-prod.sql
|
||||
psql mam_test -c "UPDATE django_site SET name='MaMweb (test)', domain='mam-test.ks.matfyz.cz' WHERE id=1"
|
||||
@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'
|
||||
.PHONY: default
|
||||
|
|
115
README.md
115
README.md
|
@ -1,77 +1,58 @@
|
|||
Basic commands for web development
|
||||
==================================
|
||||
Web M&M
|
||||
======
|
||||
|
||||
After you clone this repository, run `make`. It will download, locally install
|
||||
and setup virtualenv and pip, and then locally install all required packages
|
||||
from `requirements.txt`.
|
||||
Tohle je repozitář s kódem M&Mího webu. Pokud zde hledáte web samotný nebo
|
||||
informace o semináři, najdete je na <https://mam.matfyz.cz> (a upřímně nechápu,
|
||||
jak jste se dostali k tomuhle textu :-D)
|
||||
|
||||
When working with the code, always use the binaries in `./bin/`, such as
|
||||
`bin/pip`, `bin/python`, ... never the global python, pip, ...
|
||||
Use `make` and `./manage.py` for most things.
|
||||
Pokud jste tu zůstali, tak vás beztak zajímá vývoj webu (a jestli ne, tak
|
||||
budeme rádi, když začne :-)).
|
||||
|
||||
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
|
||||
----------
|
||||
Run the following commands:
|
||||
make install_venv
|
||||
. env/bin/activate
|
||||
make install_web
|
||||
<!--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…-->
|
||||
|
||||
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
|
||||
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).
|
||||
|
||||
After finishing development, run "deactivate".
|
||||
Jak web vyvíjet
|
||||
----
|
||||
<!--TODO: Napsat obšírněji, asi zase do docs/-->
|
||||
|
||||
Make commands
|
||||
-------------
|
||||
Na webu je mnoho věcí k dělání, některé ani nevyžadují kódění (třeba uhánění
|
||||
orgů, aby si psali medailonky, aktualizace fotek, …), některé se naopak týkají
|
||||
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 install` (or `make`) - locally install and setup virtualpy, install
|
||||
required packages. Ran again installs missing packages. Run after changing
|
||||
`requirements.txt`.
|
||||
|
||||
* `make clean` - remove local python packages.
|
||||
|
||||
* `make veryclean` - remove local packages and virtualpy enviroment and
|
||||
binaries.
|
||||
|
||||
* `make run` - runs "./manage.py runserver_plus"
|
||||
|
||||
* `make push_test` - pushes the last commited version to test location.
|
||||
Only git-commited changes are pushed! Rest is re-generated from scratch.
|
||||
At test server, the media data and database are kept the same.
|
||||
Everything else not in .gitignore is deleted/overwritten on the test server.
|
||||
|
||||
* `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`.
|
||||
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
|
||||
s webaři, na čem bys tak mohl/a pracovat.
|
||||
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
|
||||
podívat do dokumentace.
|
||||
1. Vyzkoušej, že ti to lokálně funguje tak, jak má.
|
||||
1. Zvládneš-li a máš-li čas, zkus to i zdokumentovat a/nebo napsat testy (TODO: chybí návod)
|
||||
1. Po dohodě s webaři to vyzkoušej na testwebu
|
||||
1. Pošli pull-request a případně zkus reagovat na komentáře
|
||||
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 :-)
|
||||
|
||||
### 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,8 +1,5 @@
|
|||
"""
|
||||
Soubor sloužící k pojmenování a jiným nastavením djangovské aplikace.
|
||||
"""
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class AesopConfig(AppConfig):
|
||||
name = 'aesop'
|
||||
verbose_name = 'Export do AESOPa'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.http import HttpResponse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
|
||||
|
||||
class OvvpFile:
|
||||
|
@ -20,7 +20,7 @@ class OvvpFile:
|
|||
yield '\t'.join(self.columns) + '\n'
|
||||
# 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):
|
||||
return ''.join(self.to_lines())
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
"""
|
||||
Soubor sloužící jako „router“, tj. zde se definují url adresy a na co ukazují:
|
||||
|
||||
- ``aesop-export/mam-rocnik-<int:prvni_rok>.csv`` (seminar_export_rocnik) :class:`~aesop.views.ExportRocnikView`
|
||||
- ``aesop-export/mam-sous-<str:datum_zacatku>.csv`` (seminar_export_sous) :class:`~aesop.views.ExportSousView`
|
||||
- ``aesop-export/index.csv`` (seminar_export_index) :class:`~aesop.views.ExportIndexView`
|
||||
"""
|
||||
from django.urls import path
|
||||
from aesop import views
|
||||
|
||||
|
@ -12,16 +5,16 @@ urlpatterns = [
|
|||
path(
|
||||
'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
|
||||
views.ExportRocnikView.as_view(),
|
||||
name='seminar_export_rocnik'
|
||||
name='aesop_export_rocnik'
|
||||
),
|
||||
path(
|
||||
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
|
||||
views.ExportSousView.as_view(),
|
||||
name='seminar_export_sous'
|
||||
name='aesop_export_sous'
|
||||
),
|
||||
path(
|
||||
'aesop-export/index.csv',
|
||||
views.ExportIndexView.as_view(),
|
||||
name='seminar_export_index'
|
||||
name='aesop_export_index'
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import datetime
|
||||
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
|
||||
from aesop.ovvpfile import OvvpFile
|
||||
|
||||
|
@ -9,7 +9,7 @@ def default_ovvpfile(event, rocnik):
|
|||
of = OvvpFile()
|
||||
of.headers['version'] = '1'
|
||||
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['id-scope'] = 'mam'
|
||||
of.headers['id-generation'] = '1'
|
||||
|
|
|
@ -1,28 +1,24 @@
|
|||
"""
|
||||
Soubor sloužící k deklaraci jednotlivých „views“ (nejčastěji funkce beroucí request
|
||||
a vracející :func:`django.shortcuts.render` respektive nějakou response, nebo
|
||||
třídy většinou rozšiřující nějakou třídu z :mod:`django.views.generic`)
|
||||
"""
|
||||
import django
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.http import HttpResponse
|
||||
from django.urls import reverse
|
||||
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 seminar.models import Rocnik, Soustredeni
|
||||
from soustredeni.models import Soustredeni
|
||||
from tvorba.models import Rocnik
|
||||
from vysledkovky import utils
|
||||
from seminar.utils import aktivniResitele
|
||||
from tvorba.utils import aktivniResitele
|
||||
|
||||
class ExportIndexView(generic.View):
|
||||
def get(self, request):
|
||||
ls = []
|
||||
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])
|
||||
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])
|
||||
|
||||
return HttpResponse('\n'.join(ls) + '\n', content_type='text/plain; charset=utf-8')
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
"""
|
||||
Soubor sloužící k pojmenování a jiným nastavením djangovské aplikace.
|
||||
"""
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ApiConfig(AppConfig):
|
||||
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
|
||||
import seminar.models as m
|
||||
import seminar.views as v
|
||||
from seminar.utils import sync_skoly
|
||||
from personalni.models import Skola
|
||||
from personalni.utils import sync_skoly
|
||||
|
||||
@tag('stejny-model-na-produkci')
|
||||
class OrgSkolyAutocompleteTestCase(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
@ -11,19 +11,20 @@ class OrgSkolyAutocompleteTestCase(TestCase):
|
|||
sync_skoly('https://mam.mff.cuni.cz/')
|
||||
# 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
|
||||
# TODO: Opravit zakomentované školy.
|
||||
cls.spravna_data = [
|
||||
('gymnázium kolín', 53),
|
||||
('kolín', 53),
|
||||
('gasoš', 96),
|
||||
#('gasoš', 96),
|
||||
('Rokycany', 96),
|
||||
('gasoš Rokycany', 96),
|
||||
('SPŠE Pardubice', 815),
|
||||
#('gasoš Rokycany', 96),
|
||||
#('SPŠE Pardubice', 815),
|
||||
('Jaroše', 164),
|
||||
("Gymnázium, Brno, tř. Kpt. Jaroše", 164),
|
||||
#("Gymnázium, Brno, tř. Kpt. Jaroše", 164),
|
||||
("Jírovcova", 157),
|
||||
('České Budějovice', 157),
|
||||
("Gymnázium, České Budějovice, Jírovcova 8", 157),
|
||||
("první soukromé", 2),
|
||||
#("první soukromé", 2),
|
||||
("Gymnázium Elgartova", 147),
|
||||
("Jihlava", 45),
|
||||
('Milevsko', 223),
|
||||
|
@ -47,7 +48,7 @@ class OrgSkolyAutocompleteTestCase(TestCase):
|
|||
"""Testuje, že pro každého orga je jeho škola ve výsledném QuerySetu"""
|
||||
for pfx, id in self.spravna_data:
|
||||
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í
|
||||
resp = self.client.get(reverse('autocomplete_skola')+'?q='+pfx).json()
|
||||
ids = [int(x['id']) for x in resp['results']]
|
||||
|
|
18
api/urls.py
18
api/urls.py
|
@ -1,18 +1,6 @@
|
|||
"""
|
||||
Soubor sloužící jako „router“, tj. zde se definují url adresy a na co ukazují:
|
||||
|
||||
- ``api/expor/skoly/`` (export_skoly) :func:`~api.views.exports.exportSkolView`
|
||||
- ``api/autocomplete/skola/`` (autocomplete_skola) :class:`~api.views.autocomplete.SkolaAutocomplete`
|
||||
- ``api/autocomplete/resitel/`` (autocomplete_resitel) :class:`~api.views.autocomplete.ResitelAutocomplete`
|
||||
- ``api/autocomplete/problem/odevzdatelny`` (autocomplete_problem_odevzdatelny) :class:`~api.views.autocomplete.OdevzdatelnyProblemAutocomplete`
|
||||
|
||||
Na autocomplete v3 čeká:
|
||||
|
||||
- ``autocomplete/organizatori/`` (seminar_autocomplete_organizator) :class:`~api.views.autocomplete.OrganizatorAutocomplete`
|
||||
"""
|
||||
from django.urls import path
|
||||
from . import views
|
||||
from seminar.utils import org_required
|
||||
from personalni.utils import org_required
|
||||
|
||||
urlpatterns = [
|
||||
# Export škol
|
||||
|
@ -22,10 +10,12 @@ urlpatterns = [
|
|||
# Autocomplete
|
||||
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_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/vsechny', views.ProblemAutocomplete.as_view(), name='autocomplete_problem'),
|
||||
|
||||
# Ceka na autocomplete v3
|
||||
# path('autocomplete/organizatori/',
|
||||
# org_member_required(views.OrganizatorAutocomplete.as_view()),
|
||||
# name='seminar_autocomplete_organizator')
|
||||
# name='autocomplete_organizator')
|
||||
]
|
||||
|
|
|
@ -1,7 +1,2 @@
|
|||
"""
|
||||
Soubory sloužící k deklaraci jednotlivých „views“ (nejčastěji funkce beroucí request
|
||||
a vracející :func:`django.shortcuts.render` respektive nějakou response, nebo
|
||||
třídy většinou rozšiřující nějakou třídu z :mod:`django.views.generic`)
|
||||
"""
|
||||
from .autocomplete import *
|
||||
from .exports import *
|
||||
|
|
|
@ -5,15 +5,17 @@ from dal import autocomplete
|
|||
from django.shortcuts import get_object_or_404
|
||||
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
|
||||
|
||||
# TODO filosofie - zkratky, jak v databázi, tak ve vyhledávání (SPŠE, GASOŠ, Kpt., soukr)
|
||||
class SkolaAutocomplete(autocomplete.Select2QuerySetView):
|
||||
""" View k :mod:`dal.autocomplete` pro vyhledávání škol hlavně při registraci. """
|
||||
def get_queryset(self):
|
||||
# Don't forget to filter out results depending on the visitor !
|
||||
qs = m.Skola.objects.all()
|
||||
# Don't forget to filter out results depending on the visitor !
|
||||
qs = Skola.objects.all()
|
||||
if self.q:
|
||||
words = self.q.split(' ') #TODO re split podle bileho znaku
|
||||
partq = Q()
|
||||
|
@ -31,36 +33,68 @@ class SkolaAutocomplete(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):
|
||||
qs = m.Resitel.objects.all()
|
||||
qs = Resitel.objects.all()
|
||||
if self.q:
|
||||
parts = self.q.split()
|
||||
query = Q()
|
||||
for part in parts:
|
||||
query &= (
|
||||
Q(osoba__jmeno__istartswith=self.q)|
|
||||
Q(osoba__prijmeni__istartswith=self.q)|
|
||||
Q(osoba__prezdivka__istartswith=self.q)
|
||||
Q(osoba__jmeno__istartswith=part)|
|
||||
Q(osoba__prijmeni__istartswith=part)|
|
||||
Q(osoba__prezdivka__istartswith=part)
|
||||
)
|
||||
qs = qs.filter(query)
|
||||
return qs
|
||||
|
||||
|
||||
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):
|
||||
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):
|
||||
nastaveni = get_object_or_404(m.Nastaveni)
|
||||
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
|
||||
# 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, stav=m.Problem.STAV_ZADANY)
|
||||
ulohaQ = Q(Uloha___cislo_zadani__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
||||
clanekQ = Q(Clanek___cislo__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
||||
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)
|
||||
temaQ = Q(Tema___rocnik = rocnik)
|
||||
ulohaQ = Q(Uloha___cislo_zadani__rocnik=rocnik)
|
||||
clanekQ = Q(Clanek___cislo__rocnik=rocnik)
|
||||
qs = Problem.objects.filter(temaQ | ulohaQ | clanekQ).order_by("-stav", "nazev")
|
||||
if self.q:
|
||||
qs = qs.filter(
|
||||
Q(nazev__icontains=self.q))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import seminar.models as m
|
||||
import personalni.models as m
|
||||
from django.core import serializers as ser
|
||||
from django.http import HttpResponse
|
||||
def exportSkolView(request):
|
||||
|
|
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,
|
||||
"title": "Aktuální<br/> ročník",
|
||||
"tree": 1,
|
||||
"url": "seminar_aktualni_zadani",
|
||||
"url": "tvorba_aktualni_zadani",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -121,7 +121,7 @@
|
|||
"sort_order": 5,
|
||||
"title": "Archiv",
|
||||
"tree": 1,
|
||||
"url": "seminar_archiv_rocniky",
|
||||
"url": "tvorba_archiv_rocniky",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -289,7 +289,7 @@
|
|||
"sort_order": 43,
|
||||
"title": "Výsledková listina",
|
||||
"tree": 1,
|
||||
"url": "seminar_aktualni_vysledky",
|
||||
"url": "tvorba_aktualni_vysledky",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -361,7 +361,7 @@
|
|||
"sort_order": 20,
|
||||
"title": "Proběhlo",
|
||||
"tree": 1,
|
||||
"url": "seminar_seznam_soustredeni",
|
||||
"url": "soustredeni_seznam",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -409,7 +409,7 @@
|
|||
"sort_order": 23,
|
||||
"title": "Osobní údaje",
|
||||
"tree": 1,
|
||||
"url": "seminar_resitel_edit",
|
||||
"url": "personalni_resitel_edit",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -437,9 +437,9 @@
|
|||
"insitetree": true,
|
||||
"parent": 21,
|
||||
"sort_order": 36,
|
||||
"title": "Poslat řešení",
|
||||
"title": "Nahrát řešení",
|
||||
"tree": 1,
|
||||
"url": "seminar_nahraj_reseni",
|
||||
"url": "odevzdavatko_nahraj_reseni",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -463,7 +463,7 @@
|
|||
"sort_order": 35,
|
||||
"title": "Témata",
|
||||
"tree": 1,
|
||||
"url": "seminar_archiv_temata",
|
||||
"url": "tvorba_archiv_temata",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -476,9 +476,9 @@
|
|||
"access_perm_type": 1,
|
||||
"access_permissions": [
|
||||
[
|
||||
"change_hodnoceni",
|
||||
"seminar",
|
||||
"hodnoceni"
|
||||
"org",
|
||||
"auth",
|
||||
"user"
|
||||
]
|
||||
],
|
||||
"access_restricted": true,
|
||||
|
@ -589,7 +589,7 @@
|
|||
"sort_order": 15,
|
||||
"title": "Aktuální číslo",
|
||||
"tree": 1,
|
||||
"url": "seminar_aktualni_zadani",
|
||||
"url": "tvorba_aktualni_zadani",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -613,7 +613,7 @@
|
|||
"sort_order": 24,
|
||||
"title": "Čísla",
|
||||
"tree": 1,
|
||||
"url": "seminar_archiv_rocniky",
|
||||
"url": "tvorba_archiv_rocniky",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -719,9 +719,9 @@
|
|||
"insitetree": true,
|
||||
"parent": 21,
|
||||
"sort_order": 36,
|
||||
"title": "Nahrát řešení",
|
||||
"title": "Vložit řešení",
|
||||
"tree": 1,
|
||||
"url": "seminar_vloz_reseni",
|
||||
"url": "odevzdavatko_vloz_reseni",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -804,7 +804,7 @@
|
|||
"sort_order": 37,
|
||||
"title": "Moje řešení",
|
||||
"tree": 1,
|
||||
"url": "seminar_resitel_odevzdana_reseni",
|
||||
"url": "odevzdavatko_resitel_odevzdana_reseni",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -828,7 +828,7 @@
|
|||
"sort_order": 33,
|
||||
"title": "Aktuální ročník",
|
||||
"tree": 1,
|
||||
"url": "seminar_aktualni_rocnik",
|
||||
"url": "tvorba_aktualni_rocnik",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -900,7 +900,7 @@
|
|||
"sort_order": 46,
|
||||
"title": "Ročník {{rocnik.rocnik}}",
|
||||
"tree": 1,
|
||||
"url": "seminar_rocnik rocnik.rocnik",
|
||||
"url": "tvorba_rocnik rocnik.rocnik",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -924,7 +924,7 @@
|
|||
"sort_order": 47,
|
||||
"title": "Číslo {{ cislo.rocnik.rocnik }}.{{ cislo.poradi }}",
|
||||
"tree": 1,
|
||||
"url": "seminar_cislo cislo.rocnik.rocnik cislo.poradi",
|
||||
"url": "tvorba_cislo cislo.rocnik.rocnik cislo.poradi",
|
||||
"urlaspattern": true
|
||||
},
|
||||
"model": "sitetree.treeitem",
|
||||
|
@ -1007,7 +1007,18 @@
|
|||
"access_guest": false,
|
||||
"access_loggedin": false,
|
||||
"access_perm_type": 1,
|
||||
"access_permissions": [],
|
||||
"access_permissions": [
|
||||
[
|
||||
"org",
|
||||
"auth",
|
||||
"user"
|
||||
],
|
||||
[
|
||||
"resitel",
|
||||
"auth",
|
||||
"user"
|
||||
]
|
||||
],
|
||||
"access_restricted": true,
|
||||
"alias": null,
|
||||
"description": "",
|
||||
|
@ -1025,5 +1036,83 @@
|
|||
},
|
||||
"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,652 +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"
|
||||
},
|
||||
{
|
||||
"codename": "add_deadline",
|
||||
"ct_app_label": "seminar",
|
||||
"ct_model": "deadline"
|
||||
},
|
||||
{
|
||||
"codename": "change_deadline",
|
||||
"ct_app_label": "seminar",
|
||||
"ct_model": "deadline"
|
||||
},
|
||||
{
|
||||
"codename": "view_deadline",
|
||||
"ct_app_label": "seminar",
|
||||
"ct_model": "deadline"
|
||||
}
|
||||
]
|
|
@ -13,7 +13,6 @@ make install_venv
|
|||
make install
|
||||
deploy_v2/pre_migration.py
|
||||
make deploy_test
|
||||
./manage.py load_org_permissions admin_org_prava.json
|
||||
./manage.py loaddata data/*
|
||||
systemctl --user start mamweb-test.service
|
||||
./manage.py generate_thumbnails
|
||||
|
|
|
@ -2,3 +2,4 @@ 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
|
||||
|
|
15
docs/conf.py
15
docs/conf.py
|
@ -36,6 +36,7 @@ extensions = [
|
|||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.autosectionlabel',
|
||||
'myst_parser',
|
||||
'sphinxcontrib_django',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
|
@ -85,3 +86,17 @@ 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)
|
||||
|
|
@ -9,12 +9,6 @@ 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``.
|
||||
|
||||
_git_hooks
|
||||
----------
|
||||
Hooky do gitu pro kontrolu Pythoního stylu. Především ``flake8``.
|
||||
|
||||
Zbylo tu z minulosti mamwebu.
|
||||
|
||||
data
|
||||
----
|
||||
Obsahuje data, která patří do databáze, ale jsou přímo součástí webu jako
|
||||
|
@ -28,7 +22,7 @@ Generuje se za pomocí::
|
|||
|
||||
nebo (v případě meníčka)::
|
||||
|
||||
./manage.py dumpdata sitetree --natrual-foreign > data/sitetree_new.json
|
||||
./manage.py dumpdata sitetree --natural-foreign > data/sitetree_new.json
|
||||
./fix_json.py data/sitetree_new.json data/sitetree.json
|
||||
|
||||
deploy_v2
|
||||
|
|
|
@ -6,14 +6,33 @@
|
|||
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
|
||||
dalsi_soubory
|
||||
skripty
|
||||
zkratky
|
||||
modules/modules
|
||||
dalsi_soubory
|
||||
zapisy/zapisy
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
admin -> flatpage odměn -> ikona přidat obrázek
|
||||
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``.
|
|
@ -1,19 +1,23 @@
|
|||
Sphinx na našem webu
|
||||
====================
|
||||
|
||||
Dokumentace se zkompiluje příkazem ``make html`` ve složce ``doc``.
|
||||
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 ``doc`` 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).
|
||||
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í::
|
||||
``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
|
||||
|
||||
|
|
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.
|
194
docs/vyvoj.rst
194
docs/vyvoj.rst
|
@ -1,20 +1,184 @@
|
|||
Lokální vývoj mamwebu
|
||||
=====================
|
||||
Stačí spustit::
|
||||
|
||||
## Nahradte svym gimli username
|
||||
git clone USER@gimli.ms.mff.cuni.cz:/akce/mam/git/mamweb.git mamweb
|
||||
cd mamweb
|
||||
## Instalace je trochu magická, spusť následující posloupnost příkazů:
|
||||
make install_venv
|
||||
. env/bin/activate
|
||||
make install_web
|
||||
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.
|
||||
|
||||
## Vygeneruje nejaka testovaci data (spis chuda)
|
||||
./manage.py testdata
|
||||
## Nahraje statické stránky, menu a obrázky v pozadí menu
|
||||
./manage.py loaddata data/*
|
||||
## Spusti testovaci server na http://127.0.0.1:8000/
|
||||
./manage.py runserver
|
||||
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, …)
|
||||
|
||||
Když si lokálně spustíte web, běží na http://127.0.0.1:8000/, admin najdete na http://127.0.0.1:8000/admin/ (admin/admin) Až skončíš s vývojem webu, spusť “deactivate”. Tím zmizí ‘(env)’ ze začátku promptu.
|
|
@ -116,7 +116,7 @@ Aktuálně: Jakýsi coding style zhruba existuje, není popsaný, šíří se li
|
|||
- 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 (`seminar.utils.roman_numerals`) i false negatives (`seminar.models.tvorba.Cislo.posli_cislo_mailem`)
|
||||
- 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?
|
||||
|
|
|
@ -2,4 +2,7 @@ Zápisy
|
|||
======
|
||||
|
||||
.. toctree::
|
||||
2021-12-06-testovani_dokumentace_codereview
|
||||
: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.
|
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 django.contrib import admin
|
||||
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 seminar.models import Soustredeni
|
||||
|
||||
class KomentarForm(forms.Form):
|
||||
komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
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
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.21 on 2019-06-10 21:58
|
||||
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.models import Q
|
||||
from django.utils.encoding import force_text
|
||||
from imagekit.models import ImageSpecField
|
||||
from imagekit.processors import ResizeToFit, Transpose
|
||||
|
||||
import os
|
||||
|
||||
from seminar.models import Soustredeni
|
||||
from soustredeni.models import Soustredeni
|
||||
|
||||
VZDY=0
|
||||
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 %}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base.html" %}
|
||||
{% extends "galerie/base.html" %}
|
||||
|
||||
{% block nadpis1a %}
|
||||
Galerie {{galerie.nazev}}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base.html" %}
|
||||
{% extends "galerie/base.html" %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
|
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,14 +1,5 @@
|
|||
"""
|
||||
Soubor sloužící jako „router“, tj. zde se definují url adresy a na co ukazují:
|
||||
|
||||
- ``<int:pk>/`` :func:`~galerie.views.nahled`
|
||||
- ``<int:pk>/<int:fotka>/`` :func:`~galerie.views.detail`
|
||||
- ``<int:galerie>/new/`` :func:`~galerie.views.new_galerie`
|
||||
- ``<int:galerie>/plus/<int:subgalerie>/`` :func:`~galerie.views.plus_galerie`
|
||||
- ``<int:galerie>/minus/<int:subgalerie>/`` :func:`~galerie.views.minus_galerie`
|
||||
"""
|
||||
from django.urls import path
|
||||
from seminar.utils import org_required
|
||||
from personalni.utils import org_required
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
# coding: utf-8
|
||||
|
||||
import random
|
||||
|
||||
from django.http import HttpResponse, Http404
|
||||
|
@ -8,7 +6,7 @@ from django.template import RequestContext
|
|||
from datetime import datetime
|
||||
|
||||
from galerie.models import Obrazek, Galerie
|
||||
from seminar.models import Soustredeni
|
||||
from soustredeni.models import Soustredeni
|
||||
from galerie.forms import KomentarForm, NewGalerieForm
|
||||
|
||||
def zobrazit(galerie, request):
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
"""
|
||||
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:
|
||||
|
||||
- :class:`~header_fotky.models.FotkaHeader`
|
||||
- :class:`~header_fotky.models.FotkaUrlVazba`
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.contrib.admin import ModelAdmin
|
||||
import header_fotky.models as m
|
||||
|
@ -22,4 +11,4 @@ class FotkaPozadiAdmin(ModelAdmin):
|
|||
readonly_fields = ['cas']
|
||||
|
||||
admin.site.register(m.FotkaHeader, FotkaPozadiAdmin)
|
||||
admin.site.register(m.FotkaUrlVazba)
|
||||
admin.site.register(m.FotkaUrlVazba)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
"""
|
||||
Soubor sloužící k pojmenování a jiným nastavením djangovské aplikace.
|
||||
"""
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class HeaderFotkyConfig(AppConfig):
|
||||
name = 'header_fotky'
|
||||
verbose_name = 'Fotky v záhlaví'
|
||||
|
|
|
@ -12,46 +12,46 @@ from header_fotky.models import FotkaUrlVazba
|
|||
|
||||
|
||||
def vzhled(request):
|
||||
"""
|
||||
Podle času přidá do contextu, zdali je nebo není noc. Dále podle dení
|
||||
doby a url přidá do contextu správnou fotku.
|
||||
"""
|
||||
Podle času přidá do contextu, zdali je nebo není noc. Dále podle dení
|
||||
doby a url přidá do contextu správnou fotku.
|
||||
|
||||
url adresu nejprve vyzkouší celou, pak postupně odřezává věci za
|
||||
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
|
||||
url adresu nejprve vyzkouší celou, pak postupně odřezává věci za
|
||||
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
|
||||
|
||||
fotky = FotkaUrlVazba.objects.exclude(denni_doba=nedoba)
|
||||
fotka = None
|
||||
fotky = FotkaUrlVazba.objects.exclude(denni_doba=nedoba)
|
||||
fotka = None
|
||||
|
||||
# TODO rychlejší patternmatch?
|
||||
while (fotka is None) and (url != ''):
|
||||
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()
|
||||
# TODO rychlejší patternmatch?
|
||||
while (fotka is None) and (url != ''):
|
||||
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]
|
||||
index = url.rfind('/')
|
||||
if index != -1:
|
||||
url = url[:index+1]
|
||||
url = url[:-1]
|
||||
index = url.rfind('/')
|
||||
if index != -1:
|
||||
url = url[:index+1]
|
||||
|
||||
if fotka is None:
|
||||
fotka = settings.STATIC_URL + "images/header/vikendovka.jpg"
|
||||
if fotka is None:
|
||||
fotka = settings.STATIC_URL + "images/header/vikendovka.jpg"
|
||||
|
||||
return {'noc': noc, 'fotka': fotka}
|
||||
return {'noc': noc, 'fotka': fotka}
|
||||
|
||||
|
|
|
@ -1,17 +1,3 @@
|
|||
"""
|
||||
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`
|
||||
"""
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
|
|
|
@ -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?
|
||||
|
||||
|
|
@ -1,21 +1,10 @@
|
|||
"""
|
||||
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:
|
||||
|
||||
- :class:`korektury.models.KorekturovanePDF`
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from reversion.admin import VersionAdmin
|
||||
from korektury.models import KorekturovanePDF
|
||||
from korektury.models import KorekturovanePDF, Oprava, KorekturaTag
|
||||
|
||||
from django.core.mail import send_mail
|
||||
from django.core.mail import EmailMessage
|
||||
from django.urls import reverse
|
||||
|
||||
# Register your models here.
|
||||
class KorekturovanePDFAdmin(VersionAdmin):
|
||||
"""
|
||||
nastaví čas vložení (:attr:`~koretkury.models.KorekturovanePDF.cas`) a počet
|
||||
|
@ -36,12 +25,13 @@ class KorekturovanePDFAdmin(VersionAdmin):
|
|||
fieldsets = [
|
||||
(None,
|
||||
{'fields':
|
||||
['pdf', 'cas', 'org', 'stran', 'nazev', 'komentar', 'poslat_mail']}),
|
||||
['pdf', 'cas', 'stran', 'nazev', 'orgove', 'komentar', 'poslat_mail']}),
|
||||
# (u'PDF', {'fields': ['pdf']}),
|
||||
]
|
||||
list_display = ['nazev', 'cas', 'stran', 'org']
|
||||
list_display = ['nazev', 'cas', 'stran']
|
||||
list_filter = []
|
||||
search_fields = []
|
||||
autocomplete_fields = ['orgove']
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
"""
|
||||
|
@ -64,6 +54,19 @@ Popis souboru:
|
|||
S pozdravem a korekturám zdar!
|
||||
Korekturovátko
|
||||
'''
|
||||
send_mail(predmet,text,odesilatel,[prijemce])
|
||||
EmailMessage(
|
||||
subject=predmet,
|
||||
body=text,
|
||||
from_email=odesilatel,
|
||||
to=[prijemce],
|
||||
).send()
|
||||
|
||||
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,24 +0,0 @@
|
|||
"""
|
||||
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
|
||||
"""
|
||||
from django import forms
|
||||
|
||||
class OpravaForm(forms.Form):
|
||||
""" formulář k přidání opravy (:class:`korektury.models.Oprava`) """
|
||||
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 django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.20 on 2019-04-30 21:40
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.21 on 2019-06-10 21:58
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
|
18
korektury/migrations/0019_auto_20221205_2014.py
Normal file
18
korektury/migrations/0019_auto_20221205_2014.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.28 on 2022-12-05 19:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('korektury', '0018_korekturovanepdf_poslat_mail'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='korekturovanepdf',
|
||||
name='nazev',
|
||||
field=models.CharField(help_text='Název (např. 22.1 verze 4) korekturovaného PDF', max_length=50, verbose_name='název PDF'),
|
||||
),
|
||||
]
|
18
korektury/migrations/0020_lepsi_popis_nazvu_PDF_v_adminu.py
Normal file
18
korektury/migrations/0020_lepsi_popis_nazvu_PDF_v_adminu.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.28 on 2023-06-19 19:38
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('korektury', '0019_auto_20221205_2014'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='korekturovanepdf',
|
||||
name='nazev',
|
||||
field=models.CharField(help_text='Název (např. `22.1 | analyza v4` nebo `propagace | letacek v0`) korekturovaného PDF', max_length=50, verbose_name='název PDF'),
|
||||
),
|
||||
]
|
13
korektury/migrations/0021_auto_20240312_2124.py
Normal file
13
korektury/migrations/0021_auto_20240312_2124.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Generated by Django 4.2.8 on 2024-03-12 20:24
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('korektury', '0020_lepsi_popis_nazvu_PDF_v_adminu'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
|
@ -0,0 +1,30 @@
|
|||
# Generated by Django 4.2.11 on 2024-03-19 21:35
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('personalni', '0003_initial'),
|
||||
('korektury', '0021_auto_20240312_2124'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='komentar',
|
||||
name='autor',
|
||||
field=models.ForeignKey(blank=True, help_text='Autor komentáře', null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='korekturovanepdf',
|
||||
name='org',
|
||||
field=models.ForeignKey(blank=True, default=None, help_text='Zodpovědný organizátor za obsah', null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='oprava',
|
||||
name='autor',
|
||||
field=models.ForeignKey(blank=True, help_text='Autor opravy', null=True, on_delete=django.db.models.deletion.SET_NULL, to='personalni.organizator'),
|
||||
),
|
||||
]
|
14
korektury/migrations/0023_personalni_post_migrate.py
Normal file
14
korektury/migrations/0023_personalni_post_migrate.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Generated by Django 4.2.11 on 2024-03-26 21:25
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('korektury', '0022_alter_komentar_autor_alter_korekturovanepdf_org_and_more'),
|
||||
('personalni', '0005_personalni_post_migrate'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
41
korektury/migrations/0024_vic_orgu_k_pdf.py
Normal file
41
korektury/migrations/0024_vic_orgu_k_pdf.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Generated by Django 4.2.13 on 2024-06-11 23:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
def pridej_orgy(apps, schema_editor):
|
||||
PDF = apps.get_model('korektury', 'KorekturovanePDF')
|
||||
for pdf in PDF.objects.all(): # Tohle by asi mělo jít udělat pomocí update, ale moc práce a rychlé hledání taky nepomohlo.
|
||||
if pdf.org is not None: pdf.orgove.add(pdf.org)
|
||||
pdf.save() # ig?
|
||||
|
||||
def vyber_orga(apps, schema_editor):
|
||||
PDF = apps.get_model('korektury', 'KorekturovanePDF')
|
||||
for pdf in PDF.objects.all():
|
||||
orgove = pdf.orgove.all()
|
||||
if len(orgove) > 1:
|
||||
raise migrations.exceptions.IrreversibleError(f'PDF {pdf.id} má víc než jednoho zodpovědného orga, nejde odmigrovat na verzi, která umí jen jednoho.')
|
||||
if len(orgove) == 0:
|
||||
pdf.org = None
|
||||
else:
|
||||
pdf.org = orgove[0]
|
||||
pdf.save()
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('personalni', '0011_osloveni_vsechny_choices'),
|
||||
('korektury', '0023_personalni_post_migrate'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='korekturovanepdf',
|
||||
name='orgove',
|
||||
field=models.ManyToManyField(blank=True, default=None, help_text='Zodpovědní organizátoři za obsah (chodí jim maily o nových korekturách)', to='personalni.organizator'),
|
||||
),
|
||||
migrations.RunPython(pridej_orgy, vyber_orga),
|
||||
migrations.RemoveField(
|
||||
model_name='korekturovanepdf',
|
||||
name='org',
|
||||
),
|
||||
]
|
|
@ -0,0 +1,45 @@
|
|||
# Generated by Django 4.2.16 on 2024-12-12 10:25
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
import datetime
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
def oprava2komentar(apps, schema_editor):
|
||||
Oprava = apps.get_model('korektury', 'Oprava')
|
||||
Komentar = apps.get_model('korektury', 'Komentar')
|
||||
|
||||
for o in Oprava.objects.all():
|
||||
Komentar.objects.create(oprava=o, text=o.text, autor=o.autor, cas=timezone.make_aware(datetime.datetime.fromtimestamp(0)))
|
||||
|
||||
def komentar2oprava(apps, schema_editor):
|
||||
Oprava = apps.get_model('korektury', 'Oprava')
|
||||
Komentar = apps.get_model('korektury', 'Komentar')
|
||||
|
||||
for o in Oprava.objects.all():
|
||||
k = Komentar.objects.filter(oprava=o).first()
|
||||
o.text = k.text
|
||||
o.autor = k.autor
|
||||
o.save()
|
||||
k.delete()
|
||||
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('korektury', '0024_vic_orgu_k_pdf'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(oprava2komentar, komentar2oprava),
|
||||
migrations.RemoveField(
|
||||
model_name='oprava',
|
||||
name='autor',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='oprava',
|
||||
name='text',
|
||||
),
|
||||
]
|
29
korektury/migrations/0026_oprava_informovani_orgove.py
Normal file
29
korektury/migrations/0026_oprava_informovani_orgove.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 4.2.16 on 2025-02-11 14:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
def pridani_orgu(apps, _schema_editor):
|
||||
Komentar = apps.get_model('korektury','Komentar')
|
||||
for komentar in Komentar.objects.all():
|
||||
org = komentar.autor
|
||||
if org is not None:
|
||||
# Tohle jde asi udělat lépe než .all(…). Ale nejhorší na tom je, že .add(…) funguje jinak tady v migracích.
|
||||
if org not in komentar.oprava.informovani_orgove.all():
|
||||
komentar.oprava.informovani_orgove.add(org)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('personalni', '0019_rename_upozorneni_resitel_upozornovat_na_opravy_reseni'),
|
||||
('korektury', '0025_remove_oprava_autor_remove_oprava_text'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='oprava',
|
||||
name='informovani_orgove',
|
||||
field=models.ManyToManyField(blank=True, default=None, help_text='Orgové informovaní při přidání komentáře ke korektuře', related_name='informovan_o_opravach', to='personalni.organizator', verbose_name='Informovaní organizátoři'),
|
||||
),
|
||||
migrations.RunPython(pridani_orgu, migrations.RunPython.noop),
|
||||
]
|
27
korektury/migrations/0027_korekturatag_oprava_tagy.py
Normal file
27
korektury/migrations/0027_korekturatag_oprava_tagy.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 4.2.16 on 2025-02-11 16:07
|
||||
|
||||
import colorfield.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('korektury', '0026_oprava_informovani_orgove'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='KorekturaTag',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('nazev', models.CharField(help_text='Název daného tagu, <20 znaků', max_length=20, verbose_name='název tagu')),
|
||||
('barva', colorfield.fields.ColorField(default='#FFFFFF', image_field=None, max_length=25, samples=None, verbose_name='barva daného tagu')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='oprava',
|
||||
name='tagy',
|
||||
field=models.ManyToManyField(blank=True, default=None, to='korektury.korekturatag'),
|
||||
),
|
||||
]
|
|
@ -1,27 +1,16 @@
|
|||
"""
|
||||
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`
|
||||
"""
|
||||
import os
|
||||
|
||||
from colorfield.fields import ColorField
|
||||
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_text
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.text import get_valid_filename
|
||||
|
||||
from seminar.models import Organizator
|
||||
from personalni.models import Organizator
|
||||
|
||||
import subprocess
|
||||
from reversion import revisions as reversion
|
||||
|
@ -41,7 +30,6 @@ def generate_filename(self, filename):
|
|||
clean)
|
||||
return os.path.join(settings.KOREKTURY_PDF_DIR, fname)
|
||||
|
||||
|
||||
#@reversion.register(ignore_duplicates=True)
|
||||
class KorekturovanePDF(models.Model):
|
||||
class Meta:
|
||||
|
@ -55,28 +43,25 @@ class KorekturovanePDF(models.Model):
|
|||
|
||||
cas = models.DateTimeField(u'čas vložení PDF',default=timezone.now,help_text = 'Čas vložení PDF')
|
||||
|
||||
nazev = models.CharField(u'název PDF',blank = True,max_length=50, help_text='Název (např. 22.1 verze 4) korekturovaného PDF')
|
||||
nazev = models.CharField(u'název PDF',blank = False,max_length=50, help_text='Název (např. `22.1 | analyza v4` nebo `propagace | letacek v0`) korekturovaného PDF')
|
||||
|
||||
komentar = models.TextField(u'komentář k PDF',blank = True, help_text='Komentář ke korekturovanému PDF (např. na co se zaměřit)')
|
||||
|
||||
pdf = models.FileField(u'PDF', upload_to = generate_filename)
|
||||
|
||||
org = models.ForeignKey(Organizator, blank=True,
|
||||
help_text='Zodpovědný organizátor za obsah',
|
||||
null=True, default=None, on_delete=models.SET_NULL)
|
||||
orgove = models.ManyToManyField(Organizator, blank=True,
|
||||
help_text='Zodpovědní organizátoři za obsah (chodí jim maily o nových korekturách)',
|
||||
default=None)
|
||||
|
||||
stran = models.IntegerField(u'počet stran', help_text='Počet stran PDF',
|
||||
default=0)
|
||||
STATUS_PRIDAVANI = 'pridavani'
|
||||
STATUS_ZANASENI = 'zanaseni'
|
||||
STATUS_ZASTARALE = 'zastarale'
|
||||
STATUS_CHOICES = (
|
||||
(STATUS_PRIDAVANI, u'Přidávání korektur'),
|
||||
(STATUS_ZANASENI, u'Korektury jsou zanášeny'),
|
||||
(STATUS_ZASTARALE, u'Stará verze, nekorigovat'),
|
||||
)
|
||||
status = models.CharField(u'stav PDF',max_length=16, choices=STATUS_CHOICES, blank=False,
|
||||
default = STATUS_PRIDAVANI)
|
||||
|
||||
class STATUS(models.TextChoices):
|
||||
PRIDAVANI = 'pridavani', 'Přidávání korektur'
|
||||
ZANASENI = 'zanaseni', 'Korektury jsou zanášeny'
|
||||
ZASTARALE = 'zastarale', 'Stará verze, nekorigovat'
|
||||
|
||||
status = models.CharField(u'stav PDF',max_length=16, choices=STATUS.choices, blank=False, default = STATUS.PRIDAVANI)
|
||||
|
||||
poslat_mail = models.BooleanField('Poslat mail o novém PDF', default=True,
|
||||
help_text='Určuje, zda se má o nově nahraném PDF poslat e-mail do mam-org. Při upravování existujícího souboru už nemá žádný vliv.',
|
||||
|
@ -144,6 +129,17 @@ class KorekturovanePDF(models.Model):
|
|||
return nazev_split[0] # + " " + nazev_split[2]
|
||||
except IndexError:
|
||||
return self.nazev
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('korektury', kwargs={'pdf': self.id})
|
||||
|
||||
|
||||
class KorekturaTag(models.Model):
|
||||
nazev = models.CharField("název tagu", blank = False, max_length=20, help_text="Název daného tagu, <20 znaků")
|
||||
barva = ColorField("barva daného tagu", default="#FFFFFF")
|
||||
|
||||
def __str__(self):
|
||||
return self.nazev
|
||||
|
||||
|
||||
@reversion.register(ignore_duplicates=True)
|
||||
|
@ -164,32 +160,22 @@ class Oprava(models.Model):
|
|||
x = models.IntegerField(u'x-ová souřadnice bugu')
|
||||
y = models.IntegerField(u'y-ová souřadnice bugu')
|
||||
|
||||
STATUS_K_OPRAVE = 'k_oprave'
|
||||
STATUS_OPRAVENO = 'opraveno'
|
||||
STATUS_NENI_CHYBA = 'neni_chyba'
|
||||
STATUS_K_ZANESENI = 'k_zaneseni'
|
||||
STATUS_CHOICES = (
|
||||
(STATUS_K_OPRAVE, u'K opravě'),
|
||||
(STATUS_OPRAVENO, u'Opraveno'),
|
||||
(STATUS_NENI_CHYBA, u'Není chyba'),
|
||||
(STATUS_K_ZANESENI, u'K zanesení do TeXu'),
|
||||
)
|
||||
status = models.CharField(u'stav opravy',max_length=16, choices=STATUS_CHOICES, blank=False,
|
||||
default = STATUS_K_OPRAVE)
|
||||
class STATUS(models.TextChoices):
|
||||
K_OPRAVE = 'k_oprave', 'K opravě'
|
||||
OPRAVENO = 'opraveno', 'Opraveno'
|
||||
NENI_CHYBA = 'neni_chyba', 'Není chyba'
|
||||
K_ZANESENI = 'k_zaneseni', 'K zanesení do TeXu'
|
||||
|
||||
autor = models.ForeignKey(Organizator, blank = True,
|
||||
help_text='Autor opravy',
|
||||
null = True, on_delete=models.SET_NULL)
|
||||
|
||||
text = models.TextField(u'text opravy',blank = True, help_text='Text opravy')
|
||||
status = models.CharField(u'stav opravy',max_length=16, choices=STATUS.choices, blank=False, default = STATUS.K_OPRAVE)
|
||||
|
||||
# def __init__(self,dictionary):
|
||||
# for k,v in dictionary.items():
|
||||
# setattr(self,k,v)
|
||||
|
||||
def __str__(self):
|
||||
return '{} od {}: {}'.format(self.status,self.autor,self.text)
|
||||
informovani_orgove = models.ManyToManyField(
|
||||
Organizator, blank=True, default=None,
|
||||
verbose_name='Informovaní organizátoři',
|
||||
help_text="Orgové informovaní při přidání komentáře ke korektuře",
|
||||
related_name='informovan_o_opravach',
|
||||
)
|
||||
|
||||
tagy = models.ManyToManyField(KorekturaTag, blank=True, default=None,)
|
||||
|
||||
|
||||
@reversion.register(ignore_duplicates=True)
|
||||
|
@ -215,5 +201,7 @@ class Komentar(models.Model):
|
|||
def __str__(self):
|
||||
return '{} od {}: {}'.format(self.cas,self.autor,self.text)
|
||||
|
||||
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super().save(*args, **kwargs)
|
||||
if self.autor is not None:
|
||||
self.oprava.informovani_orgove.add(self.autor)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue