Merge branch 'test' KRLEŠ!
							
								
								
									
										16
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,11 +1,5 @@ | ||||||
| # virtual env | # virtual env | ||||||
| /bin/ | /env/ | ||||||
| /include/ |  | ||||||
| /lib/ |  | ||||||
| /local/ |  | ||||||
| /share/ |  | ||||||
| /virtualenv/ |  | ||||||
| /pip-selfcheck.json |  | ||||||
| 
 | 
 | ||||||
| # transient files | # transient files | ||||||
| /db-test.sqlite3* | /db-test.sqlite3* | ||||||
|  | @ -16,7 +10,7 @@ | ||||||
| 
 | 
 | ||||||
| # aux files | # aux files | ||||||
| *.pyc | *.pyc | ||||||
| *.swp | *.sw[mnop] | ||||||
| 
 | 
 | ||||||
| # secrets | # secrets | ||||||
| /django.secret | /django.secret | ||||||
|  | @ -33,3 +27,9 @@ TODO | ||||||
| 
 | 
 | ||||||
| # .htpasswd pro AESOPa | # .htpasswd pro AESOPa | ||||||
| /.htpasswd-aesop | /.htpasswd-aesop | ||||||
|  | 
 | ||||||
|  | # reversion kvůli historii objektů v reversion | ||||||
|  | **/reversion | ||||||
|  | 
 | ||||||
|  | # pro lidi, co programují v nástrojích od JetBrains | ||||||
|  | .idea | ||||||
|  |  | ||||||
							
								
								
									
										187
									
								
								MIGRATIONS
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,187 @@ | ||||||
|  | Jak zvládnout migrace na nový model: | ||||||
|  | 
 | ||||||
|  | - V mojí verzi databáze mají úlohy-Problémy typ "b'uloha'" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Log migrace na nový model: | ||||||
|  | 
 | ||||||
|  | Operations to perform: | ||||||
|  |   Apply all migrations: admin, auth, contenttypes, django_comments, flatpages, fluent_comments, galerie, korektury, prednasky, reversion, seminar, sessions, sites, sitetree, taggit, threadedcomments | ||||||
|  | Running migrations: | ||||||
|  |   Applying admin.0003_logentry_add_action_flag_choices... OK | ||||||
|  |   Applying auth.0009_alter_user_last_name_max_length... OK | ||||||
|  |   Applying auth.0010_alter_group_name_max_length... OK | ||||||
|  |   Applying auth.0011_update_proxy_permissions... OK | ||||||
|  |   Applying galerie.0008_auto_20190430_2340... OK | ||||||
|  |   Applying galerie.0009_auto_20190610_2358... OK | ||||||
|  |   Applying galerie.0010_auto_20200819_0947... OK | ||||||
|  |   Applying korektury.0016_auto_20190430_2340... OK | ||||||
|  |   Applying korektury.0017_auto_20190610_2358... OK | ||||||
|  |   Applying prednasky.0011_auto_20190430_2340... OK | ||||||
|  |   Applying prednasky.0012_auto_20190610_2358... OK | ||||||
|  |   Applying seminar.0049_auto_20190430_2354... OK | ||||||
|  |   Applying seminar.0050_auto_20190510_2228... OK | ||||||
|  |   Applying seminar.0051_resitel_to_osoba... OK | ||||||
|  |   Applying seminar.0052_user_to_organizator... OK | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2004-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1998-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2017-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2017-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2014-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2011-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2013-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2004-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2013-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2012-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2007-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2011-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2009-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2009-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2008-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2005-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2015-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2001-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2010-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2008-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2006-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2002-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2005-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1999-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2003-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2000-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2002-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2001-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1996-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2000-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (1999-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (1996-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1994-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2012-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2016-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2018-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2014-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2019-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2006-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (1995-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_do received a naive datetime (2007-12-31 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2015-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2016-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2018-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2019-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  | /aux/akce/mam/www/mamweb-test/env/lib/python3.7/site-packages/django/db/models/fields/__init__.py:1427: RuntimeWarning: DateTimeField Organizator.organizuje_od received a naive datetime (2020-01-01 00:00:00) while time zone support is active. | ||||||
|  |   RuntimeWarning) | ||||||
|  |   Applying seminar.0053_organizator_organizuje_od_do... OK | ||||||
|  |   Applying seminar.0055_smazat_nemigrovane_zastarale_veci... OK | ||||||
|  |   Applying seminar.0056_vrcholy_pro_rocniky_a_cisla... OK | ||||||
|  |   Applying seminar.0057_reseni_to_reseni_hodnoceni...!!!!!!!!!!!!!!! | ||||||
|  | 31397 Reseni object (31397) | ||||||
|  | !!!!!!!!!!!!!!! | ||||||
|  | !!!!!!!!!!!!!!! | ||||||
|  | 31396 Reseni object (31396) | ||||||
|  | !!!!!!!!!!!!!!! | ||||||
|  | !!!!!!!!!!!!!!! | ||||||
|  | 31395 Reseni object (31395) | ||||||
|  | !!!!!!!!!!!!!!! | ||||||
|  | !!!!!!!!!!!!!!! | ||||||
|  | 31394 Reseni object (31394) | ||||||
|  | !!!!!!!!!!!!!!! | ||||||
|  | !!!!!!!!!!!!!!! | ||||||
|  | 31393 Reseni object (31393) | ||||||
|  | !!!!!!!!!!!!!!! | ||||||
|  |  OK | ||||||
|  |   Applying seminar.0058_problem_to_uloha_tema_clanek... OK | ||||||
|  |   Applying seminar.fix_0058... OK | ||||||
|  |   Applying seminar.0059_vytvorit_pohadkanode... OK | ||||||
|  |   Applying seminar.0060_spoj_stromy... OK | ||||||
|  |   Applying seminar.0061_kill_frankenstein... OK | ||||||
|  |   Applying seminar.0062_redukce_modelu_pohadky... OK | ||||||
|  |   Applying seminar.0063_procisteni_migraci... OK | ||||||
|  |   Applying seminar.0064_auto_20190610_2358... OK | ||||||
|  |   Applying seminar.0065_treenode_polymorphic_ctype... OK | ||||||
|  |   Applying seminar.0066_problem_polymorphic_ctype... OK | ||||||
|  |   Applying seminar.0067_auto_20190814_0805... OK | ||||||
|  |   Applying seminar.0068_treenode_nazev... OK | ||||||
|  |   Applying seminar.0069_auto_20191120_2115... OK | ||||||
|  |   Applying seminar.0070_auto_20191120_2357... OK | ||||||
|  |   Applying seminar.0071_remove_nastaveni_aktualni_rocnik... OK | ||||||
|  |   Applying seminar.0072_auto_20191204_2257... OK | ||||||
|  |   Applying seminar.0073_copy_osoba_email_to_user_email... OK | ||||||
|  |   Applying seminar.0074_auto_20200228_1401... OK | ||||||
|  |   Applying seminar.0075_auto_20200228_2010... OK | ||||||
|  |   Applying seminar.0076_auto_20200228_2013... OK | ||||||
|  |   Applying seminar.0077_auto_20200318_2146... OK | ||||||
|  |   Applying seminar.0078_otistenereseninode... OK | ||||||
|  |   Applying seminar.0079_clanek_resitelsky... OK | ||||||
|  |   Applying seminar.0080_zruseni_claneknode_a_konferanode... OK | ||||||
|  |   Applying seminar.0081_auto_20200408_2221... OK | ||||||
|  |   Applying seminar.0082_auto_20200506_1951... OK | ||||||
|  |   Applying seminar.0083_auto_20200506_1952... OK | ||||||
|  | WARNING 2020-08-20 00:49:07,941 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2215) | ||||||
|  | WARNING 2020-08-20 00:49:07,953 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2221) | ||||||
|  | WARNING 2020-08-20 00:49:07,959 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2212) | ||||||
|  | WARNING 2020-08-20 00:49:07,965 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1955) | ||||||
|  | WARNING 2020-08-20 00:49:07,968 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2027) | ||||||
|  | WARNING 2020-08-20 00:49:07,971 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1981) | ||||||
|  | WARNING 2020-08-20 00:49:07,974 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1970) | ||||||
|  | WARNING 2020-08-20 00:49:07,978 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2001) | ||||||
|  | WARNING 2020-08-20 00:49:07,981 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2004) | ||||||
|  | WARNING 2020-08-20 00:49:07,984 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1941) | ||||||
|  | WARNING 2020-08-20 00:49:07,990 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2024) | ||||||
|  | WARNING 2020-08-20 00:49:07,993 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2031) | ||||||
|  | WARNING 2020-08-20 00:49:07,997 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2211) | ||||||
|  | WARNING 2020-08-20 00:49:08,005 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2073) | ||||||
|  | WARNING 2020-08-20 00:49:08,017 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2018) | ||||||
|  | WARNING 2020-08-20 00:49:08,022 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2222) | ||||||
|  | WARNING 2020-08-20 00:49:08,028 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (1953) | ||||||
|  | WARNING 2020-08-20 00:49:08,034 0084_clanek_cislo: Více než jedno řešení pro článek Clanek object (2026) | ||||||
|  |   Applying seminar.0084_clanek_cislo... OK | ||||||
|  |   Applying seminar.0085_nepovinna_prezdivka... OK | ||||||
|  |   Applying seminar.0086_auto_20200819_0959... OK | ||||||
|  |   Applying sitetree.0001_initial... OK | ||||||
|  |   Applying taggit.0003_taggeditem_add_unique_index... OK | ||||||
|  | 
 | ||||||
							
								
								
									
										120
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						|  | @ -1,68 +1,71 @@ | ||||||
| .PHONY: clean_env init_env clean_virtualenv install_packages clean install run all schema_seminar.pdf schema_all.pdf sync_test_media sync_test_db sync_test sync_local_media sync_local_db sync_local | PYTHON ?= python3 | ||||||
| PYTHON=python2.7 | VENV ?= ${PYTHON} -m venv | ||||||
| VE_VER=16.0.0 | # Všechny flagy, které se s venvem/virtualenvem/... mají volat patří sem. Volá se "${VENV} cesta"
 | ||||||
| LOCAL_PYTHON=bin/python | VENV_PATH ?= env | ||||||
|  | # Musí být definovaná, i kdyby to měla být "."
 | ||||||
| 
 | 
 | ||||||
| all: install | .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 | ||||||
| 
 | 
 | ||||||
| clean: clean_env | # 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. | ||||||
| 
 | 
 | ||||||
| veryclean: clean clean_virtualenv | 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 | ||||||
| 
 | 
 | ||||||
| install: virtualenv bin/python install_packages | clean: clean_venv clean_schema | ||||||
| 
 | 
 | ||||||
|  | install: install_web | ||||||
| 
 | 
 | ||||||
| # phony, but depends on file
 | install_web: venv_check | ||||||
| make_env: ${LOCAL_PYTHON} | 	@# venv může být příšerně starý, takže nejdříve upgradujeme venvové věci | ||||||
|  | 	pip install --upgrade pip | ||||||
|  | 	pip install --upgrade setuptools | ||||||
|  | 	# Instalace závislostí webu | ||||||
|  | 	pip install -r requirements.txt --upgrade | ||||||
|  | 	# Po vygenerování testdat spusť  ./manage.py loaddata data/*, ať máš menu a další modely | ||||||
|  | 	# Pro synchronizaci flatpages spusť make sync_prod_flatpages | ||||||
| 
 | 
 | ||||||
| # phony, but fast repeated execution
 | install_venv: | ||||||
| install_packages: make_env | 	${VENV} ${VENV_PATH} | ||||||
| 	bin/pip install -r requirements.txt --upgrade |  | ||||||
| 
 | 
 | ||||||
| # phony
 | clean_venv: | ||||||
| clean_env: | 	# Možná není 100% foolproof... | ||||||
| 	rm -rf bin/ include/ lib/ local/ share/ | 	@test ! ${VENV_PATH} = . || ! echo "Smaž si prosím venv sám, nebudu mazat celý web" | ||||||
|  | 	rm -rfv ${VENV_PATH} | ||||||
| 	rm -f pip-selfcheck.json | 	rm -f pip-selfcheck.json | ||||||
|  | clean_schema: | ||||||
| 	rm -f schema_seminar.pdf schema_all.pdf | 	rm -f schema_seminar.pdf schema_all.pdf | ||||||
| 
 | 
 | ||||||
| # binary name representing set-up env
 | run: venv_check | ||||||
| ${LOCAL_PYTHON}: virtualenv |  | ||||||
| 	${PYTHON} virtualenv/virtualenv.py . |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # directory name
 |  | ||||||
| virtualenv: |  | ||||||
| 	# I could not find a link without hash anymore. This will probably break in |  | ||||||
| 	# the future. |  | ||||||
| 	curl -O https://files.pythonhosted.org/packages/33/bc/fa0b5347139cd9564f0d44ebd2b147ac97c36b2403943dbee8a25fd74012/virtualenv-16.0.0.tar.gz |  | ||||||
| 	tar xvfz virtualenv-${VE_VER}.tar.gz |  | ||||||
| 	mv -T virtualenv-${VE_VER} virtualenv |  | ||||||
| 	rm virtualenv-${VE_VER}.tar.gz |  | ||||||
| 
 |  | ||||||
| # phony
 |  | ||||||
| clean_virtualenv: |  | ||||||
| 	rm -rf virtualenv/ |  | ||||||
| 	rm -rf virtualenv-*.tar.gz |  | ||||||
| 
 |  | ||||||
| run: |  | ||||||
| 	./manage.py runserver | 	./manage.py runserver | ||||||
| 
 | 
 | ||||||
| test: | test: venv_check | ||||||
| 	./manage.py test -v2 seminar mamweb | 	./manage.py test -v2 seminar mamweb | ||||||
| 
 | 
 | ||||||
| # DB schemata
 | # DB schemata
 | ||||||
| 
 | 
 | ||||||
| schema: schema_seminar.pdf schema_all.pdf | schema: schema_seminar.pdf schema_all.pdf | ||||||
| 
 | 
 | ||||||
| schema_seminar.pdf: | schema_seminar.pdf: venv_check | ||||||
| 	./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf | 	./manage.py graph_models seminar | dot -Tpdf > schema_seminar.pdf | ||||||
| 
 | 
 | ||||||
| schema_all.pdf: | schema_all.pdf: venv_check | ||||||
| 	./manage.py graph_models -a -g | dot -Tpdf > schema_all.pdf | 	./manage.py graph_models -a -g | dot -Tpdf > schema_all.pdf | ||||||
| 
 | 
 | ||||||
| # Deploy to current *mamweb-test* directory
 | # Deploy to current *mamweb-test* directory
 | ||||||
| deploy_test: | deploy_test: venv_check | ||||||
| 	@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi | 	@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 | 	@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 ..." | 	@echo "Installing version from origin/test ..." | ||||||
|  | @ -78,7 +81,7 @@ deploy_test: | ||||||
| 	@echo Done. | 	@echo Done. | ||||||
| 
 | 
 | ||||||
| # Deploy to current *mamweb-prod* directory
 | # Deploy to current *mamweb-prod* directory
 | ||||||
| deploy_prod: | deploy_prod: venv_check | ||||||
| 	@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi | 	@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 | 	@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 ..." | 	@echo "Backing up production DB ..." | ||||||
|  | @ -96,6 +99,15 @@ deploy_prod: | ||||||
| 	@echo Done. | 	@echo Done. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | sync_prod_flatpages: venv_check  | ||||||
|  | 	@echo Downloading current version of flatpages from mamweb-prod. | ||||||
|  | 	ssh mam-web@gimli.ms.mff.cuni.cz \
 | ||||||
|  | 	"cd /akce/mam/www/mamweb-prod; ./manage.py dumpdata flatpages --indent=2 > flat.json" | ||||||
|  | 	rsync -ave ssh mam-web@gimli.ms.mff.cuni.cz:/akce/mam/www/mamweb-prod/flat.json ./flat.json | ||||||
|  | 	@echo "Applying downloaded flatpages." | ||||||
|  | 	./manage.py loaddata flat.json | ||||||
|  | 	@echo "Done." | ||||||
|  | 
 | ||||||
| # Sync test media directory with production
 | # Sync test media directory with production
 | ||||||
| sync_test_media: | sync_test_media: | ||||||
| 	@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi | 	@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi | ||||||
|  | @ -107,12 +119,24 @@ sync_test_db: | ||||||
| 	@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi | 	@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 mam_test > dump-test-`date +"%Y%m%d_%H%M"`.sql | ||||||
| 	pg_dump -Fc mam_prod > dump-prod.sql | 	pg_dump -Fc mam_prod > dump-prod.sql | ||||||
| 	pg_restore -c -d mam_test dump-prod.sql | 	pg_restore -c --if-exists -d mam_test dump-prod.sql | ||||||
|  | 	rm dump-prod.sql | ||||||
|  | 	@echo Done. | ||||||
|  | 	 | ||||||
|  | # Aggresive variant: destroy original mam_test db with 'DROP OWNED BY "mam-web";'
 | ||||||
|  | sync_test_db_aggressive: | ||||||
|  | 	@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi | ||||||
|  | 	pg_dump mam_test > dump-test-`date +"%Y%m%d_%H%M"`.sql | ||||||
|  | 	pg_dump -Fc mam_prod > dump-prod.sql | ||||||
|  | 	@# I am not sure which shell is used, so I am calling bash to make sure | ||||||
|  | 	bash -c "psql mam_test <<< 'DROP OWNED BY \"mam-web\";'" | ||||||
|  | 	pg_restore -c --if-exists -d mam_test dump-prod.sql | ||||||
| 	rm dump-prod.sql | 	rm dump-prod.sql | ||||||
| 	@echo Done. | 	@echo Done. | ||||||
| 
 | 
 | ||||||
| # Sync test with production
 | # Sync test with production
 | ||||||
| sync_test: sync_test_media sync_test_db | # 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
 | # Sync media directory with atrey. Useful for local development with production database
 | ||||||
|  | @ -128,4 +152,10 @@ sync_local_db: | ||||||
| 	pg_restore -c -d mam-prod  last.pgdump | 	pg_restore -c -d mam-prod  last.pgdump | ||||||
| 
 | 
 | ||||||
| # Sync database and media. See above lines
 | # Sync database and media. See above lines
 | ||||||
| sync_local: sync_media sync_db | 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' | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								README.md
									
									
									
									
									
								
							
							
						
						|  | @ -13,12 +13,12 @@ Use git :-) | ||||||
| 
 | 
 | ||||||
| Quickstart | Quickstart | ||||||
| ---------- | ---------- | ||||||
|  | Run the following commands: | ||||||
|  | 	make install_venv | ||||||
|  | 	. env/bin/activate | ||||||
|  | 	make install_web | ||||||
| 
 | 
 | ||||||
| Install the following packages in Debian/Ubuntu: `libpq-dev python-dev python-setuptools python2.7 libjpeg-dev libpng12-dev`. Then run: | After finishing development, run "deactivate". | ||||||
| 
 |  | ||||||
|   make |  | ||||||
|   ./manage.py testdata |  | ||||||
|   make run |  | ||||||
| 
 | 
 | ||||||
| Make commands | Make commands | ||||||
| ------------- | ------------- | ||||||
|  | @ -41,6 +41,8 @@ Make commands | ||||||
| 
 | 
 | ||||||
| * `make schema` - generates graph of seminar and all schemas as PDF. Supercool! | * `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 commands | ||||||
| -------------------- | -------------------- | ||||||
| 
 | 
 | ||||||
|  | @ -56,6 +58,8 @@ Make commands | ||||||
| 
 | 
 | ||||||
| * `./manage.py test` - run the tests. | * `./manage.py test` - run the tests. | ||||||
| 
 | 
 | ||||||
|  | * `./manage.py shell` - run commands, list elemements of database, check syntax | ||||||
|  |   by importing files, etc. | ||||||
| 
 | 
 | ||||||
| Configurations | Configurations | ||||||
| -------------- | -------------- | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								Schema_new.dia
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										637
									
								
								admin_org_prava.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,637 @@ | ||||||
|  | [ | ||||||
|  | 	{ | ||||||
|  | 		"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" | ||||||
|  | 	} | ||||||
|  | ] | ||||||
							
								
								
									
										10
									
								
								checklinks.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						|  | @ -0,0 +1,10 @@ | ||||||
|  | #!/bin/sh | ||||||
|  | 
 | ||||||
|  | # Props to https://www.commandlinefu.com/commands/view/8234/check-broken-links-using-wget-as-a-spider | ||||||
|  | set -eu | ||||||
|  | 
 | ||||||
|  | logfile="$(pwd)/wget.log.$(date +%FT%T)" | ||||||
|  | tmp=$(mktemp --directory) | ||||||
|  | cd "$tmp" | ||||||
|  | 
 | ||||||
|  | wget --spider -o "$logfile" -r -p -X '/soustredeni/*/fotogalerie/' "$@" | ||||||
							
								
								
									
										17
									
								
								convert_spaces_to_tabs.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						|  | @ -0,0 +1,17 @@ | ||||||
|  | #!/bin/sh | ||||||
|  | 
 | ||||||
|  | if test "$#" -lt 1 | ||||||
|  | then | ||||||
|  | 	echo "Usage: $0 file ..." | ||||||
|  | 	exit 2 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | for file in "$@" | ||||||
|  | do | ||||||
|  | 	# Do the sed magic: keep replacing 4 spaces at the begining of line | ||||||
|  | 	sed -i -re ' | ||||||
|  | 		: loop | ||||||
|  | 		s/^(	*)    /\1	/ | ||||||
|  | 		t loop | ||||||
|  | 		' "$file" | ||||||
|  | done | ||||||
							
								
								
									
										182
									
								
								data/flat.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										207
									
								
								data/fotka_header.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,207 @@ | ||||||
|  | [ | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "baliky.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/baliky.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "beh.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/beh.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "kryptografie.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/kryptografie.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "mam_cernobile.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/mam_cernobile.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "noc.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/noc.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "ohen.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/ohen.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "snih.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/snih.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "spolecna.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/spolecna.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "stiny.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/stiny.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "vikendovka.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/vikendovka.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaheader", | ||||||
|  |   "pk": "vylet.jpg", | ||||||
|  |   "fields": { | ||||||
|  |     "cas": "2020-09-20T09:18:34.562Z", | ||||||
|  |     "fotka": "header/vylet.jpg" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 1, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/archiv/", | ||||||
|  |     "fotka": "stiny.jpg", | ||||||
|  |     "denni_doba": "oboji" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 2, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/clanky/", | ||||||
|  |     "fotka": "kryptografie.jpg", | ||||||
|  |     "denni_doba": "den" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 3, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/clanky/", | ||||||
|  |     "fotka": "ohen.jpg", | ||||||
|  |     "denni_doba": "noc" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 4, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/aktualni/", | ||||||
|  |     "fotka": "baliky.jpg", | ||||||
|  |     "denni_doba": "den" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 5, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/aktualni/", | ||||||
|  |     "fotka": "stiny.jpg", | ||||||
|  |     "denni_doba": "noc" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 6, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/o-nas/", | ||||||
|  |     "fotka": "vikendovka.jpg", | ||||||
|  |     "denni_doba": "den" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 7, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/o-nas/", | ||||||
|  |     "fotka": "noc.jpg", | ||||||
|  |     "denni_doba": "noc" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 8, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/soustredeni/", | ||||||
|  |     "fotka": "beh.jpg", | ||||||
|  |     "denni_doba": "den" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 9, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/soustredeni/", | ||||||
|  |     "fotka": "vylet.jpg", | ||||||
|  |     "denni_doba": "noc" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 10, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/prihlasit/", | ||||||
|  |     "fotka": "baliky.jpg", | ||||||
|  |     "denni_doba": "den" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 11, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/prihlasit/", | ||||||
|  |     "fotka": "stiny.jpg", | ||||||
|  |     "denni_doba": "noc" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 12, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/profil/", | ||||||
|  |     "fotka": "baliky.jpg", | ||||||
|  |     "denni_doba": "den" | ||||||
|  |   } | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "model": "header_fotky.fotkaurlvazba", | ||||||
|  |   "pk": 13, | ||||||
|  |   "fields": { | ||||||
|  |     "url": "/profil/", | ||||||
|  |     "fotka": "stiny.jpg", | ||||||
|  |     "denni_doba": "noc" | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | ] | ||||||
							
								
								
									
										860
									
								
								data/sitetree.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,860 @@ | ||||||
|  | [ | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"alias": "main_menu", | ||||||
|  | 			"title": "Hlavní menu" | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.tree", | ||||||
|  | 		"pk": 1 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": null, | ||||||
|  | 			"sort_order": 1, | ||||||
|  | 			"title": "Co je M&M", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/o-nas/uvod/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 1 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": null, | ||||||
|  | 			"sort_order": 2, | ||||||
|  | 			"title": "Jak řešit", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/jak-resit/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 2 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": null, | ||||||
|  | 			"sort_order": 3, | ||||||
|  | 			"title": "Aktuální<br/> ročník", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_aktualni_zadani", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 3 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": null, | ||||||
|  | 			"sort_order": 4, | ||||||
|  | 			"title": "Soustředění", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/soustredeni/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 4 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": null, | ||||||
|  | 			"sort_order": 5, | ||||||
|  | 			"title": "Archiv", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_archiv_rocniky", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 5 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"access_guest": true, | ||||||
|  | 			"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": null, | ||||||
|  | 			"sort_order": 6, | ||||||
|  | 			"title": "Přihlásit", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "login", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 6 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 1, | ||||||
|  | 			"sort_order": 7, | ||||||
|  | 			"title": "Úvod", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/o-nas/uvod/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 7 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 1, | ||||||
|  | 			"sort_order": 8, | ||||||
|  | 			"title": "Organizátoři", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "organizatori", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 8 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 1, | ||||||
|  | 			"sort_order": 10, | ||||||
|  | 			"title": "Kontakt", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/o-nas/kontakt/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 10 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 2, | ||||||
|  | 			"sort_order": 11, | ||||||
|  | 			"title": "Úvod", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/jak-resit/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 11 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 2, | ||||||
|  | 			"sort_order": 45, | ||||||
|  | 			"title": "Jak psát článek", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/jak-resit/jak-psat-clanek/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 12 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 3, | ||||||
|  | 			"sort_order": 43, | ||||||
|  | 			"title": "Výsledková listina", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_aktualni_vysledky", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 16 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 4, | ||||||
|  | 			"sort_order": 18, | ||||||
|  | 			"title": "Úvod", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/soustredeni/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 18 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 4, | ||||||
|  | 			"sort_order": 19, | ||||||
|  | 			"title": "Připravujeme", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/soustredeni/pripravujeme/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 19 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 4, | ||||||
|  | 			"sort_order": 20, | ||||||
|  | 			"title": "Proběhlo", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_seznam_soustredeni", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 20 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"access_guest": false, | ||||||
|  | 			"access_loggedin": true, | ||||||
|  | 			"access_perm_type": 1, | ||||||
|  | 			"access_permissions": [], | ||||||
|  | 			"access_restricted": false, | ||||||
|  | 			"alias": null, | ||||||
|  | 			"description": "", | ||||||
|  | 			"hidden": false, | ||||||
|  | 			"hint": "", | ||||||
|  | 			"inbreadcrumbs": true, | ||||||
|  | 			"inmenu": true, | ||||||
|  | 			"insitetree": true, | ||||||
|  | 			"parent": null, | ||||||
|  | 			"sort_order": 21, | ||||||
|  | 			"title": "Profil", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "profil", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 21 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 21, | ||||||
|  | 			"sort_order": 23, | ||||||
|  | 			"title": "Osobní údaje", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_resitel_edit", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 22 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"access_guest": false, | ||||||
|  | 			"access_loggedin": false, | ||||||
|  | 			"access_perm_type": 1, | ||||||
|  | 			"access_permissions": [ | ||||||
|  | 				2 | ||||||
|  | 			], | ||||||
|  | 			"access_restricted": true, | ||||||
|  | 			"alias": null, | ||||||
|  | 			"description": "", | ||||||
|  | 			"hidden": false, | ||||||
|  | 			"hint": "", | ||||||
|  | 			"inbreadcrumbs": true, | ||||||
|  | 			"inmenu": true, | ||||||
|  | 			"insitetree": true, | ||||||
|  | 			"parent": 21, | ||||||
|  | 			"sort_order": 36, | ||||||
|  | 			"title": "Poslat řešení", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_nahraj_reseni", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 23 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 5, | ||||||
|  | 			"sort_order": 35, | ||||||
|  | 			"title": "Témata", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_archiv_temata", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 24 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"access_guest": false, | ||||||
|  | 			"access_loggedin": false, | ||||||
|  | 			"access_perm_type": 1, | ||||||
|  | 			"access_permissions": [ | ||||||
|  | 				1 | ||||||
|  | 			], | ||||||
|  | 			"access_restricted": true, | ||||||
|  | 			"alias": null, | ||||||
|  | 			"description": "", | ||||||
|  | 			"hidden": false, | ||||||
|  | 			"hint": "", | ||||||
|  | 			"inbreadcrumbs": true, | ||||||
|  | 			"inmenu": true, | ||||||
|  | 			"insitetree": true, | ||||||
|  | 			"parent": null, | ||||||
|  | 			"sort_order": 28, | ||||||
|  | 			"title": "HIDDEN", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/korektury/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 28 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 30, | ||||||
|  | 			"title": "Aktuální", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "korektury_list", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 30 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 31, | ||||||
|  | 			"title": "Zastaralé", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "korektury_stare_list", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 31 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 32, | ||||||
|  | 			"title": "Nápověda", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/korektury/help/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 32 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 3, | ||||||
|  | 			"sort_order": 15, | ||||||
|  | 			"title": "Aktuální číslo", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_aktualni_zadani", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 33 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 5, | ||||||
|  | 			"sort_order": 24, | ||||||
|  | 			"title": "Čísla", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_archiv_rocniky", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 35 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 21, | ||||||
|  | 			"sort_order": 22, | ||||||
|  | 			"title": "Úvod", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "profil", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 36 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"access_guest": false, | ||||||
|  | 			"access_loggedin": false, | ||||||
|  | 			"access_perm_type": 1, | ||||||
|  | 			"access_permissions": [ | ||||||
|  | 				1 | ||||||
|  | 			], | ||||||
|  | 			"access_restricted": true, | ||||||
|  | 			"alias": null, | ||||||
|  | 			"description": "", | ||||||
|  | 			"hidden": false, | ||||||
|  | 			"hint": "To, co ŘEŠITELÉ poslali", | ||||||
|  | 			"inbreadcrumbs": true, | ||||||
|  | 			"inmenu": true, | ||||||
|  | 			"insitetree": true, | ||||||
|  | 			"parent": 21, | ||||||
|  | 			"sort_order": 38, | ||||||
|  | 			"title": "Došlá řešení", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "odevzdavatko_tabulka", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 37 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"access_guest": false, | ||||||
|  | 			"access_loggedin": true, | ||||||
|  | 			"access_perm_type": 1, | ||||||
|  | 			"access_permissions": [], | ||||||
|  | 			"access_restricted": false, | ||||||
|  | 			"alias": null, | ||||||
|  | 			"description": "", | ||||||
|  | 			"hidden": false, | ||||||
|  | 			"hint": "", | ||||||
|  | 			"inbreadcrumbs": true, | ||||||
|  | 			"inmenu": true, | ||||||
|  | 			"insitetree": true, | ||||||
|  | 			"parent": 21, | ||||||
|  | 			"sort_order": 42, | ||||||
|  | 			"title": "Odhlásit se", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "logout", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 38 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"access_guest": false, | ||||||
|  | 			"access_loggedin": false, | ||||||
|  | 			"access_perm_type": 1, | ||||||
|  | 			"access_permissions": [ | ||||||
|  | 				1 | ||||||
|  | 			], | ||||||
|  | 			"access_restricted": true, | ||||||
|  | 			"alias": null, | ||||||
|  | 			"description": "", | ||||||
|  | 			"hidden": false, | ||||||
|  | 			"hint": "", | ||||||
|  | 			"inbreadcrumbs": true, | ||||||
|  | 			"inmenu": true, | ||||||
|  | 			"insitetree": true, | ||||||
|  | 			"parent": 21, | ||||||
|  | 			"sort_order": 36, | ||||||
|  | 			"title": "Nahrát řešení", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_vloz_reseni", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 39 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 5, | ||||||
|  | 			"sort_order": 40, | ||||||
|  | 			"title": "Řešitelské články", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/archiv/clanky", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 40 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 1, | ||||||
|  | 			"sort_order": 41, | ||||||
|  | 			"title": "Odměny", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/o-nas/odmeny/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 41 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"fields": { | ||||||
|  | 			"access_guest": false, | ||||||
|  | 			"access_loggedin": false, | ||||||
|  | 			"access_perm_type": 1, | ||||||
|  | 			"access_permissions": [ | ||||||
|  | 				2 | ||||||
|  | 			], | ||||||
|  | 			"access_restricted": true, | ||||||
|  | 			"alias": null, | ||||||
|  | 			"description": "", | ||||||
|  | 			"hidden": false, | ||||||
|  | 			"hint": "To, co jsem JÁ odevzdal", | ||||||
|  | 			"inbreadcrumbs": true, | ||||||
|  | 			"inmenu": true, | ||||||
|  | 			"insitetree": true, | ||||||
|  | 			"parent": 21, | ||||||
|  | 			"sort_order": 37, | ||||||
|  | 			"title": "Odevzdaná řešení", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_resitel_odevzdana_reseni", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 42 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 3, | ||||||
|  | 			"sort_order": 33, | ||||||
|  | 			"title": "Aktuální ročník", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "seminar_aktualni_rocnik", | ||||||
|  | 			"urlaspattern": true | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 43 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 1, | ||||||
|  | 			"sort_order": 44, | ||||||
|  | 			"title": "Další aktivity", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/o-nas/dalsi-akce/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 44 | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"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": 2, | ||||||
|  | 			"sort_order": 12, | ||||||
|  | 			"title": "Podrobněji", | ||||||
|  | 			"tree": 1, | ||||||
|  | 			"url": "/jak-resit/podrobneji/", | ||||||
|  | 			"urlaspattern": false | ||||||
|  | 		}, | ||||||
|  | 		"model": "sitetree.treeitem", | ||||||
|  | 		"pk": 45 | ||||||
|  | 	} | ||||||
|  | ] | ||||||
							
								
								
									
										513
									
								
								db_compare.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						|  | @ -0,0 +1,513 @@ | ||||||
|  | #!/usr/bin/env python3 | ||||||
|  | 
 | ||||||
|  | import psycopg2 | ||||||
|  | import psycopg2.extras | ||||||
|  | 
 | ||||||
|  | OLD_DB = "mam_old" | ||||||
|  | NEW_DB = "mamweb" | ||||||
|  | 
 | ||||||
|  | oldconn = psycopg2.connect(f"dbname={OLD_DB}") | ||||||
|  | newconn = psycopg2.connect(f"dbname={NEW_DB}") | ||||||
|  | 
 | ||||||
|  | oldcur = oldconn.cursor(cursor_factory=psycopg2.extras.DictCursor) | ||||||
|  | newcur = newconn.cursor(cursor_factory=psycopg2.extras.DictCursor) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Uses global variables oldcur, newcur! | ||||||
|  | def execute_simple(old_query, new_query=None): | ||||||
|  | 	if new_query is None: | ||||||
|  | 		new_query = old_query | ||||||
|  | 
 | ||||||
|  | 	oldcur.execute(old_query) | ||||||
|  | 	newcur.execute(new_query) | ||||||
|  | 
 | ||||||
|  | 	if oldcur.rowcount != newcur.rowcount: | ||||||
|  | 		raise ValueError(f"Queries '{old_query}' and '{new_query}' returned different number of rows ({oldcur.rowcount} and {newcur.rowcount})") | ||||||
|  | 
 | ||||||
|  | 	return(oldcur.fetchall(), newcur.fetchall()) | ||||||
|  | 
 | ||||||
|  | def check_same(old_row, new_row, old_fields, new_fields=None): | ||||||
|  | 	if type(old_fields) != list: | ||||||
|  | 		old_fields = [old_fields] | ||||||
|  | 
 | ||||||
|  | 	if new_fields is None: | ||||||
|  | 		new_fields = old_fields | ||||||
|  | 	 | ||||||
|  | 	fields = zip(old_fields, new_fields) | ||||||
|  | 
 | ||||||
|  | 	for old_field, new_field in fields: | ||||||
|  | 		if old_row[old_field] == new_row[new_field]: | ||||||
|  | 			continue | ||||||
|  | 		raise ValueError(f"Fields '{old_field}'({old_row[old_field]}) and '{new_field}'({new_row[new_field]}) differs for rows \n'{old_row}' and \n'{new_row}'") | ||||||
|  | 	return True | ||||||
|  | 
 | ||||||
|  | def get_user_id_for_org_id(org_id): | ||||||
|  | 	query = """SELECT auth_user.id FROM auth_user  | ||||||
|  | 		INNER JOIN seminar_osoby ON seminar_osoby.user_id = auth_user.id | ||||||
|  | 		INNER JOIN seminar_organizator ON seminar_organizator.osoba_id = seminar_osoby.id | ||||||
|  | 		WHERE seminar_organizator.id = %s """ | ||||||
|  | 	 | ||||||
|  | 	newcur.execute(query,(org_id,)) | ||||||
|  | 	return newcur.fetchone()['id'] | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def check_skola(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_skoly ORDER BY id" | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,['id','aesop_id','izo','nazev','kratky_nazev','ulice','mesto','psc','stat','je_zs','je_ss','poznamka']) | ||||||
|  | 
 | ||||||
|  | def check_resitel(): | ||||||
|  | 	old_query = 'SELECT * FROM seminar_resitele ORDER BY id' | ||||||
|  | 	new_query = '''SELECT seminar_resitele.id, skola_id, rok_maturity, zasilat, seminar_resitele.poznamka, | ||||||
|  | 	o.jmeno AS jmeno, o.prijmeni AS prijmeni, o.user_id AS user_id, o.pohlavi_muz AS pohlavi_muz, o.email AS email, o.telefon AS telefon, o.datum_narozeni AS datum_narozeni, | ||||||
|  | 	o.datum_souhlasu_udaje AS datum_souhlasu_udaje, o.datum_souhlasu_zasilani AS datum_souhlasu_zasilani, o.datum_registrace AS datum_prihlaseni, o.ulice AS ulice, o.mesto AS mesto, o.psc AS psc, o.stat AS stat | ||||||
|  | 	FROM seminar_resitele JOIN seminar_osoby AS o ON seminar_resitele.osoba_id = o.id ORDER BY seminar_resitele.id''' | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query,new_query) | ||||||
|  | 
 | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 	 | ||||||
|  | 	fields_osoba = [ | ||||||
|  | 		'jmeno', | ||||||
|  | 		'prijmeni', | ||||||
|  | 		'user_id', | ||||||
|  | 		'pohlavi_muz', | ||||||
|  | 		#'email', #vyreseno separatne | ||||||
|  | 		'telefon', | ||||||
|  | 		'datum_narozeni', | ||||||
|  | 		'datum_souhlasu_udaje', | ||||||
|  | 		'datum_souhlasu_zasilani', | ||||||
|  | 		'datum_prihlaseni', | ||||||
|  | 		'ulice', | ||||||
|  | 		'mesto', | ||||||
|  | 		'psc', | ||||||
|  | 		'stat', | ||||||
|  | 	] | ||||||
|  | 	fields_keep = [ | ||||||
|  | 		'id', | ||||||
|  | 		'skola_id', | ||||||
|  | 		'rok_maturity', | ||||||
|  | 		'zasilat', | ||||||
|  | 		'poznamka', | ||||||
|  | 	] | ||||||
|  | 	fields = fields_keep+fields_osoba | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,fields) | ||||||
|  | 		if o['email'] != n['email'] and o['email'] != '': | ||||||
|  | 			print(f"WARNING: Emails differ: old: {o['email']}, new: {n['email']}") | ||||||
|  | 
 | ||||||
|  | def check_reseni(): | ||||||
|  | 	# Migrace 0058 zamerne meni (zmensuje) pocet reseni, aby kazdy clanek mel | ||||||
|  | 	# jen jedno reseni (s vice resiteli, coz postaru neslo) | ||||||
|  | 	# Kvuli tomu je potreba kontrolovat dve veci: | ||||||
|  | 	# 1) Ze kazdy resitel dostal za kazdy problem spravne bodu | ||||||
|  | 	# 2) Ze detaily reseni zustaly zachovany | ||||||
|  | 
 | ||||||
|  | 	# Cast 1) | ||||||
|  | 	old_query = 'SELECT * FROM seminar_reseni ORDER BY problem_id, resitel_id, body, timestamp' | ||||||
|  | 	new_query = '''SELECT seminar_reseni.id, forma, seminar_reseni.poznamka, cas_doruceni, hodnoceni.problem_id AS problem_id, hodnoceni.body AS body, hodnoceni.cislo_body_id AS cislo_body_id, res.id AS resitel_id | ||||||
|  | 		FROM seminar_reseni | ||||||
|  | 		JOIN seminar_hodnoceni AS hodnoceni ON seminar_reseni.id = hodnoceni.reseni_id | ||||||
|  | 		JOIN seminar_reseni_resitele AS rr ON seminar_reseni.id = rr.reseni_id | ||||||
|  | 		JOIN seminar_resitele AS res ON res.id = rr.resitele_id | ||||||
|  | 		ORDER BY problem_id, resitel_id, body, cas_doruceni''' | ||||||
|  | 
 | ||||||
|  | 	# Po spojeni nekterych problemu se lisi casy doruceni a poznamky, proto je nebudeme kontrolovat (jde v podstate o triviality, tak je to snad jedno) | ||||||
|  | 	same_fields = ['forma', 'problem_id', 'body', 'cislo_body_id', 'resitel_id'] | ||||||
|  | 	renamed_fields = [ | ||||||
|  | 		#('timestamp', 'cas_doruceni'), | ||||||
|  | 		] | ||||||
|  | 	old_fields = same_fields + [f[0] for f in renamed_fields] | ||||||
|  | 	new_fields = same_fields + [f[1] for f in renamed_fields] | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query, new_query) | ||||||
|  | 
 | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,old_fields, new_fields) | ||||||
|  | 
 | ||||||
|  | 	# Cast 2) | ||||||
|  | 	# Query se lisi tim, ze uz nejoinujeme resitele. | ||||||
|  | 	old_query = 'SELECT * FROM seminar_reseni ORDER BY id' | ||||||
|  | 	new_query = '''SELECT seminar_reseni.id, forma, poznamka, cas_doruceni AS timestamp, h.problem_id AS problem_id, h.body AS body, h.cislo_body_id AS cislo_body_id | ||||||
|  | 		FROM seminar_reseni | ||||||
|  | 		JOIN seminar_hodnoceni AS h ON h.reseni_id = seminar_reseni.id | ||||||
|  | 		ORDER BY id''' | ||||||
|  | 
 | ||||||
|  | 	# execute_simple kontroluje stejnost poctu radku, to nechceme. | ||||||
|  | 	oldcur.execute(old_query) | ||||||
|  | 	newcur.execute(new_query) | ||||||
|  | 	old_res, new_res = oldcur.fetchall(), newcur.fetchall() | ||||||
|  | 	# Zkontrolujeme, ze pro kazde nove reseni ma stare reseni spravna data. | ||||||
|  | 	new_ids = [n['id'] for n in new_res] | ||||||
|  | 	spravna_old = list(filter(lambda o: o['id'] in new_ids, old_res)) | ||||||
|  | 	res = zip(spravna_old,new_res) | ||||||
|  | 	for o,n in res: | ||||||
|  | 		# Tady by se poznamky i timestampy mely zachovat | ||||||
|  | 		# Z nejakeho duvodu se ale poznamky lisi ve whitespace, tak je zkontrolujeme separatne | ||||||
|  | 		check_same(o,n,['id', 'forma', 'timestamp', 'problem_id', 'body', 'cislo_body_id']) | ||||||
|  | 		old_pozn = o['poznamka'].strip() | ||||||
|  | 		new_pozn = n['poznamka'].strip() | ||||||
|  | 		if old_pozn != new_pozn: | ||||||
|  | 			raise ValueError('Poznamky se lisi pro radky {dict(o)} a {dict(n)}') | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def check_organizator(): | ||||||
|  | 	old_query = 'SELECT * FROM seminar_organizator ORDER BY id' | ||||||
|  | 	new_query = '''SELECT seminar_organizator.id AS id, studuje, strucny_popis_organizatora, users.id AS uid, osoba.prezdivka AS o_prezdivka, osoba.foto AS o_foto, organizuje_od, organizuje_do | ||||||
|  | 		FROM seminar_organizator | ||||||
|  | 		JOIN seminar_osoby AS osoba ON osoba_id = osoba.id  | ||||||
|  | 		JOIN auth_user AS users ON osoba.user_id = users.id  | ||||||
|  | 		ORDER BY seminar_organizator.id''' | ||||||
|  | 
 | ||||||
|  | 	same_fields = ['studuje', 'strucny_popis_organizatora'] | ||||||
|  | 	renamed_fields = [ | ||||||
|  | 		('user_id', 'uid'), | ||||||
|  | 		#('prezdivka', 'o_prezdivka'), | ||||||
|  | 		('foto', 'o_foto'), | ||||||
|  | 		] | ||||||
|  | 	old_fields = same_fields + [f[0] for f in renamed_fields] | ||||||
|  | 	new_fields = same_fields + [f[1] for f in renamed_fields] | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query,new_query) | ||||||
|  | 	res = zip(old_res, new_res) | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,old_fields, new_fields) | ||||||
|  | 		# organizuje od, do: | ||||||
|  | 		# Migrace prirazuje aktualni casovou zonu, takze chceme tady rucne vynutit CET. | ||||||
|  | 		from datetime import timedelta, timezone | ||||||
|  | 		cet = timezone(timedelta(hours=1)) | ||||||
|  | 		if o['organizuje_od_roku'] is None and n['organizuje_od'] is None: | ||||||
|  | 				pass | ||||||
|  | 		elif o['organizuje_od_roku'] != n['organizuje_od'].astimezone(cet).year: | ||||||
|  | 			raise ValueError(f'Not matching organizuje_od for org id={o["id"]}: old {o["organizuje_od_roku"]}, new {n["organizuje_od"]}') | ||||||
|  | 		if o['organizuje_do_roku'] is None and n['organizuje_do'] is None: | ||||||
|  | 				pass | ||||||
|  | 		elif o['organizuje_do_roku'] != n['organizuje_do'].astimezone(cet).year: | ||||||
|  | 			raise ValueError(f'Not matching organizuje_do for org id={o["id"]}: old {o["organizuje_do_roku"]}, new {n["organizuje_do"]}') | ||||||
|  | 		if o['prezdivka'] == n['o_prezdivka']: | ||||||
|  | 			continue | ||||||
|  | 		if o['prezdivka'] is None and n['o_prezdivka'] == '': | ||||||
|  | 			continue | ||||||
|  | 		raise ValueError(f'Not matching prezdivka for org id={o["id"]}: old {o["prezdivka"]}, new {n["o_prezdivka"]}') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def check_rocnik(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_rocniky ORDER BY id" | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,['id','prvni_rok', 'rocnik', 'exportovat']) | ||||||
|  | 
 | ||||||
|  | def check_cislo(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_cisla ORDER BY id" | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n, ['id','rocnik_id','cislo', 'datum_vydani','datum_deadline','verejne','poznamka','pdf'], | ||||||
|  | 				['id','rocnik_id','poradi','datum_vydani','datum_deadline','verejne','poznamka','pdf']) | ||||||
|  | 
 | ||||||
|  | def check_priloha_reseni(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_priloha_reseni" | ||||||
|  | 	 | ||||||
|  | 	old_res, new_res = execute_simple(old_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n, ['id','reseni_id', 'timestamp', 'soubor', 'poznamka'], | ||||||
|  | 				['id','reseni_id', 'vytvoreno', 'soubor', 'poznamka']) | ||||||
|  | 
 | ||||||
|  | def check_soustredeni(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_soustredeni ORDER BY id" | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,['id','rocnik_id','datum_zacatku','datum_konce','verejne','misto','text','typ','exportovat']) | ||||||
|  | 	#Kontrola ucasnici, organizatori v samostatnych funkcich | ||||||
|  | 
 | ||||||
|  | def check_soustredeni_ucastnici(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_soustredeni_ucastnici ORDER BY id" | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,['id','resitel_id','soustredeni_id','poznamka']) | ||||||
|  | 
 | ||||||
|  | def check_soustredeni_organizatori(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_soustredeni_organizatori ORDER BY id" | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,['id','organizator_id','soustredeni_id','poznamka']) | ||||||
|  | 
 | ||||||
|  | def check_nastaveni(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_nastaveni ORDER BY id" | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,['id','aktualni_cislo_id']) | ||||||
|  | 
 | ||||||
|  | def check_novinky(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_novinky ORDER BY id" | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,['id','datum','text','obrazek','zverejneno']) | ||||||
|  | 		if get_user_id_for_org_id(n['autor_id']) != o['autor_id']: | ||||||
|  | 			raise ValueError("Nesedi autori u novinek") | ||||||
|  | 			 | ||||||
|  | def check_pohadka(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_pohadky ORDER BY id" | ||||||
|  | 	new_query = """SELECT sp.id AS id, sp.autor_id AS autor_id, sp.vytvoreno AS vytvoreno, snp.treenode_ptr_id AS treenode_ptr_id, st.na_web AS text, | ||||||
|  | 				zn_pred.uloha_id AS uloha_pred, zn_po.uloha_id AS uloha_po | ||||||
|  | 			FROM seminar_pohadky AS sp  | ||||||
|  | 			-- Text pohádky | ||||||
|  | 			INNER JOIN seminar_nodes_pohadka AS snp ON sp.id = snp.pohadka_id  | ||||||
|  | 			INNER JOIN seminar_nodes_treenode AS snt ON snt.id = snp.treenode_ptr_id | ||||||
|  | 			INNER JOIN seminar_nodes_obsah AS sno ON sno.treenode_ptr_id = snt.first_child_id  | ||||||
|  | 			INNER JOIN seminar_texty AS st ON sno.text_id = st.id | ||||||
|  | 			-- Predchozí úloha | ||||||
|  | 			LEFT OUTER JOIN seminar_nodes_treenode AS ztn_pred ON ztn_pred.succ_id = snt.id | ||||||
|  | 			LEFT OUTER JOIN seminar_nodes_uloha_zadani AS zn_pred ON zn_pred.treenode_ptr_id = ztn_pred.id | ||||||
|  | 			-- Následující úloha | ||||||
|  | 			LEFT OUTER JOIN seminar_nodes_uloha_zadani AS zn_po ON zn_po.treenode_ptr_id = snt.succ_id | ||||||
|  | 
 | ||||||
|  | 			ORDER BY sp.id""" | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query,new_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n,['id','timestamp','text'],['id','vytvoreno','text']) | ||||||
|  | 		if o['autor_id'] is not None: | ||||||
|  | 			if get_user_id_for_org_id(n['autor_id']) != o['autor_id']: | ||||||
|  | 				raise ValueError("Nesedi autori u pohadky") | ||||||
|  | 		# Správné úlohy | ||||||
|  | 		# NOTE: o['pred'] rika, zda je pohadka pred ulohou, nikoliv zda je relevantni uloha pred pohadkou! | ||||||
|  | 		spravny_klic = 'uloha_po' if o['pred'] else 'uloha_pred' | ||||||
|  | 		if o['uloha_id'] != n[spravny_klic]: | ||||||
|  | 			raise ValueError(f"Pohádka přidružená ke špatné úloze! old: {o['uloha_id']}, new: {n[spravny_klic]}, pozice: {spravny_klic}") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Problémy jsou rozdělené podle typů: | ||||||
|  | def check_problem_common(): | ||||||
|  | 	old_query = "SELECT id, nazev, stav, kod, autor_id, text_org, timestamp, typ FROM seminar_problemy ORDER BY id" | ||||||
|  | 	new_query = """SELECT sp.id AS id, sp.nazev AS nazev, sp.stav AS stav, sp.kod AS kod, au.id AS autor_id, sp.poznamka AS poznamka, sp.vytvoreno AS vytvoreno | ||||||
|  | 		FROM seminar_problemy AS sp | ||||||
|  | 		LEFT OUTER JOIN seminar_organizator AS so ON sp.autor_id = so.id | ||||||
|  | 		LEFT OUTER JOIN seminar_osoby AS sos ON so.osoba_id = sos.id | ||||||
|  | 		LEFT OUTER JOIN auth_user AS au ON sos.user_id = au.id | ||||||
|  | 		ORDER BY sp.id""" | ||||||
|  | 
 | ||||||
|  | 	same_fields = ['id', 'nazev', 'stav', 'autor_id', 'kod'] | ||||||
|  | 	renamed_fields = [ | ||||||
|  | 		('text_org', 'poznamka'), | ||||||
|  | 		('timestamp', 'vytvoreno'), | ||||||
|  | 		] | ||||||
|  | 	old_fields = same_fields + [f[0] for f in renamed_fields] | ||||||
|  | 	new_fields = same_fields + [f[1] for f in renamed_fields] | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query,new_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n, old_fields, new_fields) | ||||||
|  | 
 | ||||||
|  | 	# Opravovatelé | ||||||
|  | 	# Po staru byli opravovatele organizatori, takze je potreba je dohledat. | ||||||
|  | 	old_query = """SELECT seminar_problemy.id, org.id AS opravovatel_id FROM seminar_problemy | ||||||
|  | 		JOIN seminar_organizator AS org ON seminar_problemy.opravovatel_id = org.user_id;""" | ||||||
|  | 	new_query = "SELECT problem_id, organizator_id FROM seminar_problemy_opravovatele" | ||||||
|  | 
 | ||||||
|  | 	# Simple cursors | ||||||
|  | 	#oldcur = oldconn.cursor() | ||||||
|  | 	oldcur.execute(old_query) | ||||||
|  | 	old_results = oldcur.fetchall() | ||||||
|  | 	#newcur = newconn.cursor() | ||||||
|  | 	newcur.execute(new_query) | ||||||
|  | 	new_results = newcur.fetchall() | ||||||
|  | 
 | ||||||
|  | 	for oldr in old_results: | ||||||
|  | 		if oldr not in new_results: | ||||||
|  | 			raise ValueError(f'Opravovatel pair {oldr} not found in new db.') | ||||||
|  | 
 | ||||||
|  | 	# Zaměření se vyřeší okometricky (#1186) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def check_uloha(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_problemy WHERE typ = 'uloha' ORDER BY id" | ||||||
|  | 	new_query = """SELECT cislo_zadani_id, cislo_reseni_id, problem_ptr_id, max_body, COALESCE(uzt.na_web, '') AS text_zadani, COALESCE(uvt.na_web, '') AS text_reseni, cislo_deadline_id | ||||||
|  | 	FROM seminar_ulohy | ||||||
|  | 	-- Problém: | ||||||
|  | 	JOIN seminar_problemy AS problem ON problem_ptr_id = problem.id | ||||||
|  | 	-- Text zadání: | ||||||
|  | 	-- ZadaniNode a VzorakNode maji existovat vzdy, ale obsah nemusi (pokud ho nemaji) | ||||||
|  | 	INNER JOIN seminar_nodes_uloha_zadani AS uzn ON problem.id = uzn.uloha_id | ||||||
|  | 	INNER JOIN seminar_nodes_treenode AS uztn ON uztn.id = uzn.treenode_ptr_id | ||||||
|  | 	LEFT OUTER JOIN seminar_nodes_obsah AS uzo ON uzo.treenode_ptr_id = uztn.first_child_id | ||||||
|  | 	LEFT OUTER JOIN seminar_texty AS uzt ON uzo.text_id = uzt.id | ||||||
|  | 	-- Text vzoráku: | ||||||
|  | 	INNER JOIN seminar_nodes_uloha_vzorak AS uvn ON problem.id = uvn.uloha_id | ||||||
|  | 	INNER JOIN seminar_nodes_treenode AS uvtn ON uvtn.id = uvn.treenode_ptr_id | ||||||
|  | 	LEFT OUTER JOIN seminar_nodes_obsah AS uvo ON uvo.treenode_ptr_id = uvtn.first_child_id | ||||||
|  | 	LEFT OUTER JOIN seminar_texty AS uvt ON uvo.text_id = uvt.id | ||||||
|  | 
 | ||||||
|  | 	ORDER BY problem_ptr_id""" | ||||||
|  | 
 | ||||||
|  | 	same_fields = ['cislo_zadani_id', 'cislo_reseni_id', 'text_zadani', 'text_reseni'] | ||||||
|  | 	renamed_fields = [ | ||||||
|  | 		('id', 'problem_ptr_id'), | ||||||
|  | 		('body', 'max_body'), | ||||||
|  | 		] | ||||||
|  | 	old_fields = same_fields + [f[0] for f in renamed_fields] | ||||||
|  | 	new_fields = same_fields + [f[1] for f in renamed_fields] | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query, new_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n, old_fields, new_fields) | ||||||
|  | 		# Datum deadline vypadá prázdně, tak to budeme předpokládat. | ||||||
|  | 		if n['cislo_deadline_id'] is not None: | ||||||
|  | 			raise ValueError("Úloha má deadline.") | ||||||
|  | 
 | ||||||
|  | def check_tema(): | ||||||
|  | 	old_query = """SELECT text_zadani, text_reseni, typ, c.rocnik_id AS rocnik_id | ||||||
|  | 	FROM seminar_problemy | ||||||
|  | 	LEFT OUTER JOIN seminar_cisla AS c ON c.id = cislo_zadani_id | ||||||
|  | 	WHERE typ IN ('tema', 'serial') | ||||||
|  | 	ORDER BY  seminar_problemy.id""" | ||||||
|  | 	new_query = """SELECT tema_typ, COALESCE(zad_text.na_web, '') AS text_zadani, COALESCE(res_text.na_web, '') AS text_reseni, rn.rocnik_id AS rocnik_id | ||||||
|  | 	FROM seminar_temata | ||||||
|  | 	-- Problém: | ||||||
|  | 	JOIN seminar_problemy AS problem ON problem_ptr_id = problem.id | ||||||
|  | 	-- Text: | ||||||
|  | 	-- TvCNode má dva potomky, oba TextNode. První drží původní text zadání, druhý řešení. | ||||||
|  | 	INNER JOIN seminar_nodes_temavcisle AS tvcn ON tvcn.tema_id = id | ||||||
|  | 	INNER JOIN seminar_nodes_treenode AS ttn ON tvcn.treenode_ptr_id = ttn.id | ||||||
|  | 	LEFT OUTER JOIN seminar_nodes_treenode AS zad_tn ON ttn.first_child_id = zad_tn.id -- jen 33 z nich ma zadani | ||||||
|  | 	LEFT OUTER JOIN seminar_nodes_treenode AS res_tn ON zad_tn.succ_id = res_tn.id -- jen 4 z nich ma reseni | ||||||
|  | 	LEFT OUTER JOIN seminar_nodes_obsah AS zad_on ON zad_on.treenode_ptr_id = zad_tn.id | ||||||
|  | 	LEFT OUTER JOIN seminar_nodes_obsah AS res_on ON res_on.treenode_ptr_id = res_tn.id | ||||||
|  | 	LEFT OUTER JOIN seminar_texty AS zad_text ON zad_on.text_id = zad_text.id | ||||||
|  | 	LEFT OUTER JOIN seminar_texty AS res_text ON res_on.text_id = res_text.id -- vsechny 4 | ||||||
|  | 	-- Ročník tématu: | ||||||
|  | 	-- Podle rootu TvCN | ||||||
|  | 	LEFT OUTER JOIN seminar_nodes_rocnik AS rn ON ttn.root_id = rn.treenode_ptr_id | ||||||
|  | 
 | ||||||
|  | 	ORDER BY problem_ptr_id""" | ||||||
|  | 	same_fields = ['text_zadani', 'text_reseni', 'rocnik_id'] | ||||||
|  | 	renamed_fields = [ | ||||||
|  | 		('typ', 'tema_typ'), | ||||||
|  | 		] | ||||||
|  | 	old_fields = same_fields + [f[0] for f in renamed_fields] | ||||||
|  | 	new_fields = same_fields + [f[1] for f in renamed_fields] | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query, new_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		check_same(o,n, old_fields, new_fields) | ||||||
|  | 
 | ||||||
|  | def check_konfera(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_problemy WHERE typ = 'konfera'" | ||||||
|  | 	new_query = "SELECT * FROM seminar_konfera" | ||||||
|  | 
 | ||||||
|  | 	oldcur.execute(old_query) | ||||||
|  | 	newcur.execute(new_query) | ||||||
|  | 
 | ||||||
|  | 	if oldcur.rowcount != 0 or newcur.rowcount != 0: | ||||||
|  | 		raise ValueError('There exists a Konfera!') | ||||||
|  | 
 | ||||||
|  | def check_org_clanek(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_problemy WHERE typ = 'org-clanek'" | ||||||
|  | 
 | ||||||
|  | 	oldcur.execute(old_query) | ||||||
|  | 
 | ||||||
|  | 	if oldcur.rowcount != 0: | ||||||
|  | 		raise ValueError('There exists a Org-clanek!') | ||||||
|  | 
 | ||||||
|  | def check_res_clanek(): | ||||||
|  | 	# Dva(!) články mají text (zadání), který se má zachovat. | ||||||
|  | 	old_query = "SELECT * FROM seminar_problemy WHERE typ = 'res-clanek' ORDER BY id" | ||||||
|  | 	new_query = """SELECT cislo_id, text.na_web AS text_zadani | ||||||
|  | 	FROM seminar_clanky | ||||||
|  | 	JOIN seminar_problemy AS problem ON problem_ptr_id = problem.id | ||||||
|  | 	INNER JOIN seminar_hodnoceni AS hodn ON problem.id = hodn.problem_id | ||||||
|  | 	INNER JOIN seminar_reseni AS rese ON rese.id = hodn.reseni_id | ||||||
|  | 	INNER JOIN seminar_nodes_otistene_reseni AS rn ON rese.text_cely_id = rn.treenode_ptr_id -- Tenhle radek neni potreba, ale ujistuje se mj. o spravnem typu TreeNode. | ||||||
|  | 	INNER JOIN seminar_nodes_treenode AS tn ON rn.treenode_ptr_id = tn.id | ||||||
|  | 	-- Nektere clanky vubec nemely text, tak jim migr 0058 nevyrobila dalsi treenody | ||||||
|  | 	LEFT OUTER JOIN seminar_nodes_obsah AS son ON son.treenode_ptr_id = tn.first_child_id | ||||||
|  | 	LEFT OUTER JOIN seminar_texty AS text ON text.id = son.text_id | ||||||
|  | 
 | ||||||
|  | 	ORDER BY problem_ptr_id""" | ||||||
|  | 	same_fields = ['text_zadani'] | ||||||
|  | 	renamed_fields = [ | ||||||
|  | 		('cislo_zadani_id', 'cislo_id'), | ||||||
|  | 		] | ||||||
|  | 	old_fields = same_fields + [f[0] for f in renamed_fields] | ||||||
|  | 	new_fields = same_fields + [f[1] for f in renamed_fields] | ||||||
|  | 
 | ||||||
|  | 	old_res, new_res = execute_simple(old_query, new_query) | ||||||
|  | 	res = zip(old_res,new_res) | ||||||
|  | 
 | ||||||
|  | 	for o,n in res: | ||||||
|  | 		# text_zadani po novu mohl byt None | ||||||
|  | 		if n['text_zadani'] is None: | ||||||
|  | 			n['text_zadani'] = '' | ||||||
|  | 		check_same(o,n, old_fields, new_fields) | ||||||
|  | 		assert(o['text_reseni'] == '') | ||||||
|  | 
 | ||||||
|  | def check_untyped_problem(): | ||||||
|  | 	old_query = "SELECT * FROM seminar_problemy WHERE typ NOT IN ('uloha', 'tema', 'serial', 'konfera', 'org-clanek', 'res-clanek')" | ||||||
|  | 
 | ||||||
|  | 	oldcur.execute(old_query) | ||||||
|  | 
 | ||||||
|  | 	if oldcur.rowcount != 0: | ||||||
|  | 		raise ValueError('There exists a Problem without type!') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | check_skola() | ||||||
|  | check_resitel() | ||||||
|  | check_reseni() | ||||||
|  | check_organizator() | ||||||
|  | check_rocnik() | ||||||
|  | check_cislo() | ||||||
|  | check_priloha_reseni() | ||||||
|  | check_soustredeni() | ||||||
|  | check_soustredeni_ucastnici() | ||||||
|  | check_soustredeni_organizatori() | ||||||
|  | check_nastaveni() | ||||||
|  | check_novinky() | ||||||
|  | check_pohadka() | ||||||
|  | 
 | ||||||
|  | check_problem_common() | ||||||
|  | check_uloha() | ||||||
|  | check_tema() | ||||||
|  | check_konfera() | ||||||
|  | check_org_clanek() | ||||||
|  | check_res_clanek() | ||||||
|  | check_untyped_problem() | ||||||
							
								
								
									
										3
									
								
								deploy_v2/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,3 @@ | ||||||
|  | Tahle slozka obsahuje vsechny detaily a popisy, jak nasadit "druhou verzi" M&M webu. | ||||||
|  | 
 | ||||||
|  | TODO: chybi tu popis na zprovozneni flatpages, na loaddata &c. | ||||||
							
								
								
									
										22
									
								
								deploy_v2/full_redeploy.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,22 @@ | ||||||
|  | #!/bin/bash | ||||||
|  | 
 | ||||||
|  | set -u | ||||||
|  | 
 | ||||||
|  | deactivate || true | ||||||
|  | 
 | ||||||
|  | cd /akce/mam/www/mamweb-test/ | ||||||
|  | make sync_test | ||||||
|  | systemctl --user stop mamweb-test.service | ||||||
|  | rm -rvf env | ||||||
|  | make install_venv | ||||||
|  | . env/bin/activate | ||||||
|  | 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 | ||||||
|  | 
 | ||||||
|  | echo 'Et voilá!' | ||||||
|  | echo 'Nezapomeň opravit práva pro sitetree!' | ||||||
							
								
								
									
										3
									
								
								deploy_v2/post_deploy.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,3 @@ | ||||||
|  | Jsou špatně práva k sitetree (protože se používají primární klíče, které jsou jiné :-() | ||||||
|  | Špatné položky se dají najít pomocí následujícího příkazu: | ||||||
|  | 	grep -E 'access_permissions": \[$' data/sitetree.json -A17 | grep -E 'acc|tit' -A2 | ||||||
							
								
								
									
										42
									
								
								deploy_v2/pre_migration.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						|  | @ -0,0 +1,42 @@ | ||||||
|  | #!/usr/bin/env python3 | ||||||
|  | 
 | ||||||
|  | import os | ||||||
|  | import sys | ||||||
|  | 
 | ||||||
|  | import django | ||||||
|  | 
 | ||||||
|  | #### Inicializace Djanga | ||||||
|  | sys.path.append(os.path.dirname(os.path.realpath(__file__))+'/..') | ||||||
|  | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mamweb.settings') | ||||||
|  | django.setup() | ||||||
|  | 
 | ||||||
|  | ## Pozor, nejde pouzit ORM, protoze kod je na jine verzi nez databaze a nejde namigrovat. | ||||||
|  | from django.db import connection | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def smaz_zle_clanky(): | ||||||
|  | 	# Tyhle clanky vubec nejsou clanky, bude potreba je udelat cele jinak a spravne. | ||||||
|  | 	#m.Problem.objects.filter(id__in=[1981, 1970, 2222]).delete() | ||||||
|  | 	## with connection.cursor() as cursor: | ||||||
|  | 	## 	# Nejdriv musime smazat reseni: | ||||||
|  | 	## 	cursor.execute('DELETE FROM seminar_reseni WHERE problem_id IN (1981, 1970, 2222);') | ||||||
|  | 	## 	# Nakonec i ty clanky samotne | ||||||
|  | 	## 	cursor.execute('DELETE FROM seminar_problemy WHERE id IN (1981, 1970, 2222);') | ||||||
|  | 
 | ||||||
|  |         # Update: stejně je v DB bordel, tak z nich prostě jen udělám témata a všechno zhruba přežije… | ||||||
|  | 	with connection.cursor() as cursor: | ||||||
|  | 		cursor.execute("UPDATE seminar_problemy SET typ = 'tema' WHERE id IN (1981, 1970, 2222);") | ||||||
|  | 
 | ||||||
|  | def smaz_divne_uzivatele(): | ||||||
|  | 	# U techto uzivatelu neexistuje Organizator s nimi spojeny | ||||||
|  | 	# Takze pak delaji akorat neporadek | ||||||
|  | 	with connection.cursor() as cursor: | ||||||
|  | 		# Jeste je potreba zrusit vazby | ||||||
|  | 		cursor.execute('UPDATE django_comments SET user_id = NULL WHERE user_id = 34;') | ||||||
|  | 		cursor.execute('UPDATE seminar_problemy SET autor_id = NULL WHERE autor_id = 34;') | ||||||
|  | 		cursor.execute('DELETE FROM django_admin_log WHERE user_id = 34;') | ||||||
|  | 		cursor.execute('DELETE FROM auth_user_groups WHERE user_id = 34;') | ||||||
|  | 		cursor.execute('DELETE FROM auth_user WHERE id IN (34, 40, 30, 50, 54, 58, 43);') | ||||||
|  | 
 | ||||||
|  | smaz_zle_clanky() | ||||||
|  | smaz_divne_uzivatele() | ||||||
							
								
								
									
										12
									
								
								fix_json.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						|  | @ -0,0 +1,12 @@ | ||||||
|  | #!/usr/bin/python3 | ||||||
|  | 
 | ||||||
|  | import json | ||||||
|  | import argparse | ||||||
|  | 
 | ||||||
|  | parser = argparse.ArgumentParser() | ||||||
|  | parser.add_argument("input", type=argparse.FileType('r', encoding='utf-8')) | ||||||
|  | parser.add_argument('output', type=argparse.FileType('w', encoding='utf-8')) | ||||||
|  | args = parser.parse_args() | ||||||
|  | 
 | ||||||
|  | data = json.load(args.input) | ||||||
|  | json.dump(data, args.output, ensure_ascii=False, sort_keys=True, indent='\t') | ||||||
|  | @ -5,50 +5,50 @@ from django.contrib import admin | ||||||
| from django.http import HttpResponseRedirect | from django.http import HttpResponseRedirect | ||||||
| from django import forms | from django import forms | ||||||
| from django.db import models | from django.db import models | ||||||
| from autocomplete_light import shortcuts as autocomplete_light |  | ||||||
| 
 | 
 | ||||||
| # akction | # akction | ||||||
| 
 | 
 | ||||||
| def zverejnit_fotogalerii(modeladmin, request, queryset): | def zverejnit_fotogalerii(modeladmin, request, queryset): | ||||||
|     '''zverejni vybranou fotogalerii i jeji vsechny podgalerie''' | 	'''zverejni vybranou fotogalerii i jeji vsechny podgalerie''' | ||||||
|     for galerie in queryset: | 	for galerie in queryset: | ||||||
|         galerie.zobrazit = 0 | 		galerie.zobrazit = 0 | ||||||
|         galerie.save() | 		galerie.save() | ||||||
|         zverejnit_fotogalerii(modeladmin, request, | 		zverejnit_fotogalerii(modeladmin, request, | ||||||
|                 Galerie.objects.filter(galerie_up = galerie)) | 				Galerie.objects.filter(galerie_up = galerie)) | ||||||
|     zverejnit_fotogalerii.short_description = 'Zveřejnit fotogalerie' | 	zverejnit_fotogalerii.short_description = 'Zveřejnit fotogalerie' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset): | def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset): | ||||||
|     '''zneverjni vybranou fotogalerii i jeji vsechny podgalerie''' | 	'''zneverjni vybranou fotogalerii i jeji vsechny podgalerie''' | ||||||
|     for galerie in queryset: | 	for galerie in queryset: | ||||||
|         galerie.zobrazit = 1 | 		galerie.zobrazit = 1 | ||||||
|         galerie.save() | 		galerie.save() | ||||||
|         prepnout_fotogalerii_do_org_rezimu(modeladmin, request, | 		prepnout_fotogalerii_do_org_rezimu(modeladmin, request, | ||||||
|                 Galerie.objects.filter(galerie_up = galerie)) | 				Galerie.objects.filter(galerie_up = galerie)) | ||||||
|     prepnout_fotogalerii_do_org_rezimu.short_description = \ | 	prepnout_fotogalerii_do_org_rezimu.short_description = \ | ||||||
|             'Přepnout do režimu úprav (zneveřejní galerii)' | 			'Přepnout do režimu úprav (zneveřejní galerii)' | ||||||
| 
 | 
 | ||||||
| class GalerieInline(admin.TabularInline): | class GalerieInline(admin.TabularInline): | ||||||
|     model = Obrazek | 	model = Obrazek | ||||||
|     fields = ['obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi'] | 	fields = ['obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi'] | ||||||
|     readonly_fields = ['nazev', 'obrazek_maly_tag'] | 	readonly_fields = ['nazev', 'obrazek_maly_tag'] | ||||||
|     formfield_overrides = { | 	formfield_overrides = { | ||||||
|         models.TextField: {'widget': forms.TextInput}, | 		models.TextField: {'widget': forms.TextInput}, | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
| class ObrazekAdmin(admin.ModelAdmin): | class ObrazekAdmin(admin.ModelAdmin): | ||||||
|     list_display = ('obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi') | 	list_display = ('obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi') | ||||||
|  | 	search_fields = ['nazev','popis'] | ||||||
| 
 | 
 | ||||||
| class GalerieAdmin(admin.ModelAdmin): | class GalerieAdmin(admin.ModelAdmin): | ||||||
|     form = autocomplete_light.modelform_factory(Galerie, autocomplete_fields=['titulni_obrazek'], fields=['titulni_obrazek']) | 	model = Galerie | ||||||
|     model = Galerie | 	fields = ('zobrazit', 'nazev', 'titulni_obrazek', 'popis', 'galerie_up', 'soustredeni', 'poradi') | ||||||
|     fields = ('zobrazit', 'nazev', 'titulni_obrazek', 'popis', 'galerie_up', 'soustredeni', 'poradi') | 	autocomplete_fields = ['titulni_obrazek'] | ||||||
|     list_display = ('nazev', 'soustredeni', 'galerie_up', 'poradi', 'zobrazit', 'datum_zmeny') | 	list_display = ('nazev', 'soustredeni', 'galerie_up', 'poradi', 'zobrazit', 'datum_zmeny') | ||||||
|     inlines = [GalerieInline] | 	inlines = [GalerieInline] | ||||||
|     actions = [zverejnit_fotogalerii, prepnout_fotogalerii_do_org_rezimu] | 	actions = [zverejnit_fotogalerii, prepnout_fotogalerii_do_org_rezimu] | ||||||
|     save_on_top = True | 	save_on_top = True | ||||||
|     ordering = ['galerie_up__nazev', 'poradi'] | 	ordering = ['galerie_up__nazev', 'poradi'] | ||||||
| 
 | 
 | ||||||
| admin.site.register(Obrazek, ObrazekAdmin) | admin.site.register(Obrazek, ObrazekAdmin) | ||||||
| admin.site.register(Galerie, GalerieAdmin) | admin.site.register(Galerie, GalerieAdmin) | ||||||
|  |  | ||||||
|  | @ -1,11 +1,9 @@ | ||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| 
 | 
 | ||||||
| from __future__ import unicode_literals |  | ||||||
| 
 |  | ||||||
| from autocomplete_light import shortcuts as autocomplete_light | from autocomplete_light import shortcuts as autocomplete_light | ||||||
| 
 | 
 | ||||||
| from models import Obrazek, Galerie | from .models import Obrazek, Galerie | ||||||
| from views import cesta_od_korene | from .views import cesta_od_korene | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class ObrazekAutocomplete(autocomplete_light.AutocompleteModelBase): | class ObrazekAutocomplete(autocomplete_light.AutocompleteModelBase): | ||||||
|  | @ -4,8 +4,8 @@ from django import forms | ||||||
| from seminar.models import Soustredeni | from seminar.models import Soustredeni | ||||||
| 
 | 
 | ||||||
| class KomentarForm(forms.Form): | class KomentarForm(forms.Form): | ||||||
|     komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False) | 	komentar = forms.CharField(label = "Komentář:", max_length = 300, required=False) | ||||||
| 
 | 
 | ||||||
| class NewGalerieForm(forms.Form): | class NewGalerieForm(forms.Form): | ||||||
|     nazev = forms.CharField(label = "Název galerie", max_length = 100) | 	nazev = forms.CharField(label = "Název galerie", max_length = 100) | ||||||
|     #popis = forms.CharField(label = "Popis", required = False, max_length = 2000, widget = forms.Textarea) | 	#popis = forms.CharField(label = "Popis", required = False, max_length = 2000, widget = forms.Textarea) | ||||||
|  |  | ||||||
|  | @ -21,8 +21,8 @@ class Migration(migrations.Migration): | ||||||
|                 ('datum_zmeny', models.DateTimeField(auto_now=True, verbose_name=b'Datum posledn\xc3\xad zm\xc4\x9bny')), |                 ('datum_zmeny', models.DateTimeField(auto_now=True, verbose_name=b'Datum posledn\xc3\xad zm\xc4\x9bny')), | ||||||
|                 ('popis', models.TextField(null=True, verbose_name=b'Popis', blank=True)), |                 ('popis', models.TextField(null=True, verbose_name=b'Popis', blank=True)), | ||||||
|                 ('zobrazit', models.IntegerField(default=1, verbose_name=b'Zobrazit?', choices=[(0, b'V\xc5\xbedy'), (1, b'Organiz\xc3\xa1tor\xc5\xafm'), (2, b'Nikdy')])), |                 ('zobrazit', models.IntegerField(default=1, verbose_name=b'Zobrazit?', choices=[(0, b'V\xc5\xbedy'), (1, b'Organiz\xc3\xa1tor\xc5\xafm'), (2, b'Nikdy')])), | ||||||
|                 ('galerie_up', models.ForeignKey(blank=True, to='galerie.Galerie', null=True)), |                 ('galerie_up', models.ForeignKey(blank=True, to='galerie.Galerie', null=True, on_delete=models.CASCADE)), | ||||||
|                 ('soustredeni', models.ForeignKey(blank=True, to='seminar.Soustredeni', null=True)), |                 ('soustredeni', models.ForeignKey(blank=True, to='seminar.Soustredeni', null=True, on_delete=models.CASCADE)), | ||||||
|             ], |             ], | ||||||
|             options={ |             options={ | ||||||
|                 'verbose_name': 'Galerie', |                 'verbose_name': 'Galerie', | ||||||
|  | @ -42,7 +42,7 @@ class Migration(migrations.Migration): | ||||||
|                 ('datum_vlozeni', models.DateTimeField(auto_now_add=True, verbose_name=b'Datum vlo\xc5\xbeen\xc3\xad')), |                 ('datum_vlozeni', models.DateTimeField(auto_now_add=True, verbose_name=b'Datum vlo\xc5\xbeen\xc3\xad')), | ||||||
|                 ('datum', models.DateTimeField(verbose_name=b'Datum po\xc5\x99\xc3\xadzen\xc3\xad fotografie')), |                 ('datum', models.DateTimeField(verbose_name=b'Datum po\xc5\x99\xc3\xadzen\xc3\xad fotografie')), | ||||||
|                 ('poradi', models.IntegerField(null=True, verbose_name=b'Po\xc5\x99ad\xc3\xad', blank=True)), |                 ('poradi', models.IntegerField(null=True, verbose_name=b'Po\xc5\x99ad\xc3\xad', blank=True)), | ||||||
|                 ('galerie', models.ForeignKey(to='galerie.Galerie')), |                 ('galerie', models.ForeignKey(to='galerie.Galerie', on_delete=models.CASCADE)), | ||||||
|             ], |             ], | ||||||
|             options={ |             options={ | ||||||
|                 'verbose_name': 'Obr\xe1zek', |                 'verbose_name': 'Obr\xe1zek', | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ class Migration(migrations.Migration): | ||||||
|         migrations.AlterField( |         migrations.AlterField( | ||||||
|             model_name='obrazek', |             model_name='obrazek', | ||||||
|             name='galerie', |             name='galerie', | ||||||
|             field=models.ForeignKey(blank=True, to='galerie.Galerie', null=True), |             field=models.ForeignKey(blank=True, to='galerie.Galerie', null=True, on_delete=models.CASCADE), | ||||||
|             preserve_default=True, |             preserve_default=True, | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
							
								
								
									
										71
									
								
								galerie/migrations/0008_auto_20190430_2340.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,71 @@ | ||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | # Generated by Django 1.11.20 on 2019-04-30 21:40 | ||||||
|  | from __future__ import unicode_literals | ||||||
|  | 
 | ||||||
|  | from django.db import migrations, models | ||||||
|  | import galerie.models | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  | 
 | ||||||
|  |     dependencies = [ | ||||||
|  |         ('galerie', '0007_obrazek_odstranen_datum'), | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     operations = [ | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='galerie', | ||||||
|  |             name='datum_vytvoreni', | ||||||
|  |             field=models.DateTimeField(auto_now_add=True, verbose_name='Datum vytvoření'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='galerie', | ||||||
|  |             name='datum_zmeny', | ||||||
|  |             field=models.DateTimeField(auto_now=True, verbose_name='Datum poslední změny'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='galerie', | ||||||
|  |             name='nazev', | ||||||
|  |             field=models.CharField(max_length=100, verbose_name='Název'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='galerie', | ||||||
|  |             name='popis', | ||||||
|  |             field=models.TextField(blank=True, null=True, verbose_name='Popis'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='galerie', | ||||||
|  |             name='poradi', | ||||||
|  |             field=models.IntegerField(blank=True, null=True, verbose_name='Pořadí'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='galerie', | ||||||
|  |             name='zobrazit', | ||||||
|  |             field=models.IntegerField(choices=[(0, 'Vždy'), (1, 'Organizátorům'), (2, 'Nikdy')], default=1, verbose_name='Zobrazit?'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='obrazek', | ||||||
|  |             name='datum_vlozeni', | ||||||
|  |             field=models.DateTimeField(auto_now_add=True, verbose_name='Datum vložení'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='obrazek', | ||||||
|  |             name='nazev', | ||||||
|  |             field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Název'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='obrazek', | ||||||
|  |             name='obrazek_velky', | ||||||
|  |             field=models.ImageField(help_text='Lze vložit libovolně velký obrázek. Ideální je, aby alespoň jeden rozměr měl alespoň 500px.', upload_to=galerie.models.obrazek_filename), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='obrazek', | ||||||
|  |             name='popis', | ||||||
|  |             field=models.TextField(blank=True, null=True, verbose_name='Popis'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='obrazek', | ||||||
|  |             name='poradi', | ||||||
|  |             field=models.IntegerField(blank=True, null=True, verbose_name='Pořadí'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
							
								
								
									
										31
									
								
								galerie/migrations/0009_auto_20190610_2358.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,31 @@ | ||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | # Generated by Django 1.11.21 on 2019-06-10 21:58 | ||||||
|  | from __future__ import unicode_literals | ||||||
|  | 
 | ||||||
|  | from django.db import migrations, models | ||||||
|  | import django.db.models.deletion | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  | 
 | ||||||
|  |     dependencies = [ | ||||||
|  |         ('galerie', '0008_auto_20190430_2340'), | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     operations = [ | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='galerie', | ||||||
|  |             name='galerie_up', | ||||||
|  |             field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='galerie.Galerie'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='galerie', | ||||||
|  |             name='soustredeni', | ||||||
|  |             field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='seminar.Soustredeni'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='obrazek', | ||||||
|  |             name='galerie', | ||||||
|  |             field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='galerie.Galerie'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
|  | @ -1,6 +1,4 @@ | ||||||
| # -*- coding: utf-8 -*- | # Generated by Django 2.2.15 on 2020-08-19 07:47 | ||||||
| # Generated by Django 1.11.26 on 2019-12-09 22:26 |  | ||||||
| from __future__ import unicode_literals |  | ||||||
| 
 | 
 | ||||||
| from django.db import migrations, models | from django.db import migrations, models | ||||||
| 
 | 
 | ||||||
|  | @ -8,13 +6,13 @@ from django.db import migrations, models | ||||||
| class Migration(migrations.Migration): | class Migration(migrations.Migration): | ||||||
| 
 | 
 | ||||||
|     dependencies = [ |     dependencies = [ | ||||||
|         ('galerie', '0007_obrazek_odstranen_datum'), |         ('galerie', '0009_auto_20190610_2358'), | ||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|     operations = [ |     operations = [ | ||||||
|         migrations.AlterField( |         migrations.AlterField( | ||||||
|             model_name='galerie', |             model_name='galerie', | ||||||
|             name='poradi', |             name='poradi', | ||||||
|             field=models.IntegerField(blank=True, default=0, verbose_name=b'Po\xc5\x99ad\xc3\xad'), |             field=models.IntegerField(blank=True, default=0, verbose_name='Pořadí'), | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| from django.db import models | from django.db import models | ||||||
| #from django.db.models import Q | #from django.db.models import Q | ||||||
| from django.utils.encoding import force_unicode | from django.utils.encoding import force_text | ||||||
| from imagekit.models import ImageSpecField | from imagekit.models import ImageSpecField | ||||||
| from imagekit.processors import ResizeToFit, Transpose | from imagekit.processors import ResizeToFit, Transpose | ||||||
| 
 | 
 | ||||||
|  | @ -14,109 +14,112 @@ VZDY=0 | ||||||
| ORG=1 | ORG=1 | ||||||
| NIKDY=2 | NIKDY=2 | ||||||
| VIDITELNOST = ( | VIDITELNOST = ( | ||||||
|     (VZDY, 'Vždy'), | 	(VZDY, 'Vždy'), | ||||||
|     (ORG, 'Organizátorům'), | 	(ORG, 'Organizátorům'), | ||||||
|     (NIKDY, 'Nikdy'), | 	(NIKDY, 'Nikdy'), | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| # tyhle funkce jsou tady jen kvůli starým migracím, které se na ně odkazují | # tyhle funkce jsou tady jen kvůli starým migracím, které se na ně odkazují | ||||||
| # až se ty migrace někdy squashnou, tak by mělo být možné funkce smazat | # až se ty migrace někdy squashnou, tak by mělo být možné funkce smazat | ||||||
| def obrazek_filename_maly(): | def obrazek_filename_maly(): | ||||||
|     pass | 	pass | ||||||
| def obrazek_filename_stredni(): | def obrazek_filename_stredni(): | ||||||
|     pass | 	pass | ||||||
| def obrazek_filename_velky(): | def obrazek_filename_velky(): | ||||||
|     pass | 	pass | ||||||
| 
 | 
 | ||||||
| def obrazek_filename(self, filename): | def obrazek_filename(self, filename): | ||||||
|     gal = self.galerie | 	gal = self.galerie | ||||||
|     cislo_gal = force_unicode(gal.pk) | 	cislo_gal = gal.pk | ||||||
| 
 | 
 | ||||||
|     # najdi kořenovou galerii | 	# najdi kořenovou galerii | ||||||
|     while (gal.galerie_up): | 	while (gal.galerie_up): | ||||||
|         gal = gal.galerie_up | 		gal = gal.galerie_up | ||||||
| 
 | 
 | ||||||
|     # soustředění je v cestě jen pokud galerie pod nějaké patří | 	# soustředění je v cestě jen pokud galerie pod nějaké patří | ||||||
|     cesta = ( | 	cesta = ( | ||||||
|         ['Galerie'] + | 		['Galerie'] + | ||||||
|         (["soustredeni_" + force_unicode(gal.soustredeni.pk)] if gal.soustredeni else []) + | 		(["soustredeni_{}".format(gal.soustredeni.pk)] if gal.soustredeni else []) + | ||||||
|         ["galerie_" + cislo_gal, force_unicode(self.nazev)] | 		["galerie_{}".format(cislo_gal), self.nazev] | ||||||
|     ) | 	) | ||||||
| 
 | 
 | ||||||
|     return os.path.join(*cesta) | 	return os.path.join(*cesta) | ||||||
| 
 | 
 | ||||||
| class Obrazek(models.Model): | class Obrazek(models.Model): | ||||||
|     obrazek_velky = models.ImageField(upload_to=obrazek_filename, | 	obrazek_velky = models.ImageField(upload_to=obrazek_filename, | ||||||
|       help_text = "Lze vložit libovolně velký obrázek. Ideální je, aby alespoň jeden rozměr měl alespoň 500px.") | 		help_text = "Lze vložit libovolně velký obrázek. Ideální je, aby alespoň jeden rozměr měl alespoň 500px.") | ||||||
|     obrazek_stredni = ImageSpecField(source='obrazek_velky', | 	obrazek_stredni = ImageSpecField(source='obrazek_velky', | ||||||
|                                   processors=[Transpose(Transpose.AUTO), ResizeToFit(900, 675, upscale=False)], | 				processors=[Transpose(Transpose.AUTO), ResizeToFit(900, 675, upscale=False)], | ||||||
|                                   options={'quality': 95}) | 				options={'quality': 95}) | ||||||
|     obrazek_maly = ImageSpecField(source='obrazek_velky', | 	obrazek_maly = ImageSpecField(source='obrazek_velky', | ||||||
|                                   processors=[Transpose(Transpose.AUTO), ResizeToFit(167, 167, upscale=False)], | 				processors=[Transpose(Transpose.AUTO), ResizeToFit(167, 167, upscale=False)], | ||||||
|                                   options={'quality': 95}) | 				options={'quality': 95}) | ||||||
|     nazev = models.CharField('Název', max_length=50, blank=True, null=True) | 	nazev = models.CharField('Název', max_length=50, blank=True, null=True) | ||||||
|     popis = models.TextField('Popis', blank=True, null=True) | 	popis = models.TextField('Popis', blank=True, null=True) | ||||||
|     datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add=True) | 	datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add=True) | ||||||
|     galerie = models.ForeignKey('Galerie', blank=True, null=True) | 	galerie = models.ForeignKey('Galerie', blank=True, null=True, on_delete=models.SET_NULL) | ||||||
|     poradi = models.IntegerField('Pořadí', blank=True, null=True) | 	poradi = models.IntegerField('Pořadí', blank=True, null=True) | ||||||
| 
 | 
 | ||||||
|     def __unicode__(self): | 	def __str__(self): | ||||||
|           return unicode(self.obrazek_velky.name) | 			return self.obrazek_velky.name | ||||||
| 
 | 
 | ||||||
|     class Meta: | 	class Meta: | ||||||
|       verbose_name = 'Obrázek' | 		verbose_name = 'Obrázek' | ||||||
|       verbose_name_plural = 'Obrázky' | 		verbose_name_plural = 'Obrázky' | ||||||
|       ordering = ['nazev'] | 		ordering = ['nazev'] | ||||||
| 
 | 
 | ||||||
|     def obrazek_maly_tag(self): | 	def obrazek_maly_tag(self): | ||||||
|       return u'<img src="{}">'.format(self.obrazek_maly.url) | 		if not self.obrazek_maly: | ||||||
|     obrazek_maly_tag.short_description = "Náhled" | 			return '' | ||||||
|     obrazek_maly_tag.allow_tags = True | 		return u'<img src="{}">'.format(self.obrazek_maly.url) | ||||||
| 
 | 	obrazek_maly_tag.short_description = "Náhled" | ||||||
|     def save(self, *args, **kwargs): | 	obrazek_maly_tag.allow_tags = True | ||||||
|         # obrázek potřebuje název, protože se z něj generuje cesta pro jeho uložení |  | ||||||
|         # (a pak se podle něj taky řadí) |  | ||||||
|         if self.nazev is None: |  | ||||||
|             self.nazev = os.path.basename(self.obrazek_velky.name) |  | ||||||
|         super(Obrazek, self).save(*args, **kwargs) |  | ||||||
| 
 | 
 | ||||||
|  | 	def save(self, *args, **kwargs): | ||||||
|  | 		# obrázek potřebuje název, protože se z něj generuje cesta pro jeho uložení | ||||||
|  | 		# (a pak se podle něj taky řadí) | ||||||
|  | 		if self.nazev is None: | ||||||
|  | 			self.nazev = os.path.basename(self.obrazek_velky.name) | ||||||
|  | 		super(Obrazek, self).save(*args, **kwargs) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Galerie(models.Model): | class Galerie(models.Model): | ||||||
|   nazev = models.CharField('Název', max_length=100) | 	nazev = models.CharField('Název', max_length=100) | ||||||
|   datum_vytvoreni = models.DateTimeField('Datum vytvoření', auto_now_add = True) | 	datum_vytvoreni = models.DateTimeField('Datum vytvoření', auto_now_add = True) | ||||||
|   datum_zmeny = models.DateTimeField('Datum poslední změny', auto_now = True) | 	datum_zmeny = models.DateTimeField('Datum poslední změny', auto_now = True) | ||||||
|   popis = models.TextField('Popis', blank = True, null = True) | 	popis = models.TextField('Popis', blank = True, null = True) | ||||||
|   titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL) | 	titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL) | ||||||
|   zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST) | 	zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST) | ||||||
|   galerie_up = models.ForeignKey('Galerie', blank = True, null = True) | 	galerie_up = models.ForeignKey('Galerie', blank = True, null = True, | ||||||
|   soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True) | 		on_delete=models.SET_NULL) | ||||||
|   poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0) | 	soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True, | ||||||
|  | 		on_delete=models.PROTECT) | ||||||
|  | 	poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0) | ||||||
| 
 | 
 | ||||||
|   def __unicode__(self): | 	def __str__(self): | ||||||
|     return self.nazev | 		return self.nazev | ||||||
|   class Meta: | 	class Meta: | ||||||
|     verbose_name = 'Galerie' | 		verbose_name = 'Galerie' | ||||||
|     verbose_name_plural = 'Galerie' | 		verbose_name_plural = 'Galerie' | ||||||
| 
 | 
 | ||||||
|   #def link_na_preview(self): | 	#def link_na_preview(self): | ||||||
|     #"""Odkaz na galerii, používá se v admin rozhranní. """ | 		#"""Odkaz na galerii, používá se v admin rozhranní. """ | ||||||
|     #return '<a href="/fotogalerie/galerie/%s/">Preview</a>' % self.id | 		#return '<a href="/fotogalerie/galerie/%s/">Preview</a>' % self.id | ||||||
|   #link_na_preview.allow_tags = True | 	#link_na_preview.allow_tags = True | ||||||
|   #link_na_preview.short_description = 'Zobrazit galerii' | 	#link_na_preview.short_description = 'Zobrazit galerii' | ||||||
| # | # | ||||||
|   #def je_publikovano(self): | 	#def je_publikovano(self): | ||||||
|     #"""Vraci True, pokud je tato galerie publikovana. """  | 		#"""Vraci True, pokud je tato galerie publikovana. """  | ||||||
|     #if self.zobrazit == VZDY: | 		#if self.zobrazit == VZDY: | ||||||
|       #return True | 			#return True | ||||||
|     #if self.zobrazit == PODLE_CLANKU: | 		#if self.zobrazit == PODLE_CLANKU: | ||||||
|       #for clanek in self.clanek_set.all(): | 			#for clanek in self.clanek_set.all(): | ||||||
|         #if clanek.je_publikovano(): | 				#if clanek.je_publikovano(): | ||||||
|           #return True | 					#return True | ||||||
|     #return False | 		#return False | ||||||
| # | # | ||||||
|   #@staticmethod | 	#@staticmethod | ||||||
|   #def publikovane_galerie(): | 	#def publikovane_galerie(): | ||||||
|     #"""Vraci galerie, ktere uz maji byt publikovane.""" | 		#"""Vraci galerie, ktere uz maji byt publikovane.""" | ||||||
|     #clanky = Blog.models.Clanek.publikovane_clanky() | 		#clanky = Blog.models.Clanek.publikovane_clanky() | ||||||
|     #return Galerie.objects.filter(Q(zobrazit=VZDY) | (Q(clanek__in=clanky) & Q(zobrazit=PODLE_CLANKU))).distinct() | 		#return Galerie.objects.filter(Q(zobrazit=VZDY) | (Q(clanek__in=clanky) & Q(zobrazit=PODLE_CLANKU))).distinct() | ||||||
|  |  | ||||||
| Before Width: | Height: | Size: 15 KiB | 
							
								
								
									
										65
									
								
								galerie/static/galerie/prvky/dalsi.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,65 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <svg | ||||||
|  |    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||||
|  |    xmlns:cc="http://creativecommons.org/ns#" | ||||||
|  |    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    width="25.135418mm" | ||||||
|  |    height="42.333332mm" | ||||||
|  |    viewBox="0 0 25.135418 42.333331" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg851" | ||||||
|  |    sodipodi:docname="dalsi.svg" | ||||||
|  |    inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#666666" | ||||||
|  |      borderopacity="1" | ||||||
|  |      objecttolerance="10" | ||||||
|  |      gridtolerance="10" | ||||||
|  |      guidetolerance="10" | ||||||
|  |      inkscape:pageopacity="0" | ||||||
|  |      inkscape:pageshadow="2" | ||||||
|  |      inkscape:window-width="1850" | ||||||
|  |      inkscape:window-height="1136" | ||||||
|  |      id="namedview7" | ||||||
|  |      showgrid="true" | ||||||
|  |      inkscape:zoom="23.600001" | ||||||
|  |      inkscape:cx="18.587131" | ||||||
|  |      inkscape:cy="74.924864" | ||||||
|  |      inkscape:window-x="70" | ||||||
|  |      inkscape:window-y="27" | ||||||
|  |      inkscape:window-maximized="1" | ||||||
|  |      inkscape:current-layer="svg851"> | ||||||
|  |     <inkscape:grid | ||||||
|  |        type="xygrid" | ||||||
|  |        id="grid833" /> | ||||||
|  |   </sodipodi:namedview> | ||||||
|  |   <defs | ||||||
|  |      id="defs845" /> | ||||||
|  |   <metadata | ||||||
|  |      id="metadata848"> | ||||||
|  |     <rdf:RDF> | ||||||
|  |       <cc:Work | ||||||
|  |          rdf:about=""> | ||||||
|  |         <dc:format>image/svg+xml</dc:format> | ||||||
|  |         <dc:type | ||||||
|  |            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||||
|  |         <dc:title></dc:title> | ||||||
|  |       </cc:Work> | ||||||
|  |     </rdf:RDF> | ||||||
|  |   </metadata> | ||||||
|  |   <g | ||||||
|  |      id="layer1" | ||||||
|  |      transform="matrix(-1.0282842,0,0,1,111.4545,-88.415317)"> | ||||||
|  |     <path | ||||||
|  |        d="m 98.096584,101.64448 1.286528,1.32292 -5.660724,5.82083 h 13.379892 v 1.5875 H 93.722388 l 5.660724,5.82083 -1.286528,1.32292 -7.719171,-7.9375 z" | ||||||
|  |        style="fill:#e84e10;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.23177969" | ||||||
|  |        id="path44-3" | ||||||
|  |        inkscape:connector-curvature="0" | ||||||
|  |        sodipodi:nodetypes="cccccccccc" /> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2 KiB | 
| Before Width: | Height: | Size: 18 KiB | 
| Before Width: | Height: | Size: 15 KiB | 
							
								
								
									
										65
									
								
								galerie/static/galerie/prvky/predchozi.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,65 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <svg | ||||||
|  |    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||||
|  |    xmlns:cc="http://creativecommons.org/ns#" | ||||||
|  |    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    width="25.135418mm" | ||||||
|  |    height="42.333332mm" | ||||||
|  |    viewBox="0 0 25.135418 42.333331" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg851" | ||||||
|  |    sodipodi:docname="predchozi.svg" | ||||||
|  |    inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#666666" | ||||||
|  |      borderopacity="1" | ||||||
|  |      objecttolerance="10" | ||||||
|  |      gridtolerance="10" | ||||||
|  |      guidetolerance="10" | ||||||
|  |      inkscape:pageopacity="0" | ||||||
|  |      inkscape:pageshadow="2" | ||||||
|  |      inkscape:window-width="1850" | ||||||
|  |      inkscape:window-height="1136" | ||||||
|  |      id="namedview7" | ||||||
|  |      showgrid="true" | ||||||
|  |      inkscape:zoom="4.1719301" | ||||||
|  |      inkscape:cx="124.03002" | ||||||
|  |      inkscape:cy="97.874031" | ||||||
|  |      inkscape:window-x="70" | ||||||
|  |      inkscape:window-y="27" | ||||||
|  |      inkscape:window-maximized="1" | ||||||
|  |      inkscape:current-layer="svg851"> | ||||||
|  |     <inkscape:grid | ||||||
|  |        type="xygrid" | ||||||
|  |        id="grid833" /> | ||||||
|  |   </sodipodi:namedview> | ||||||
|  |   <defs | ||||||
|  |      id="defs845" /> | ||||||
|  |   <metadata | ||||||
|  |      id="metadata848"> | ||||||
|  |     <rdf:RDF> | ||||||
|  |       <cc:Work | ||||||
|  |          rdf:about=""> | ||||||
|  |         <dc:format>image/svg+xml</dc:format> | ||||||
|  |         <dc:type | ||||||
|  |            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||||
|  |         <dc:title></dc:title> | ||||||
|  |       </cc:Work> | ||||||
|  |     </rdf:RDF> | ||||||
|  |   </metadata> | ||||||
|  |   <g | ||||||
|  |      id="layer1" | ||||||
|  |      transform="matrix(1.0282842,0,0,1,-86.319083,-88.415315)"> | ||||||
|  |     <path | ||||||
|  |        d="m 98.096584,101.64448 1.286528,1.32292 -5.660724,5.82083 h 13.379892 v 1.5875 H 93.722388 l 5.660724,5.82083 -1.286528,1.32292 -7.719171,-7.9375 z" | ||||||
|  |        style="fill:#e84e10;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.23177969" | ||||||
|  |        id="path44-3" | ||||||
|  |        inkscape:connector-curvature="0" | ||||||
|  |        sodipodi:nodetypes="cccccccccc" /> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 2 KiB | 
|  | @ -1,6 +0,0 @@ | ||||||
| {% extends "base.html" %} |  | ||||||
| 
 |  | ||||||
| {# TODO predelat pres context processor #} |  | ||||||
| {% block header %}soustredeni{% endblock %} |  | ||||||
| {% block menu_soustredeni %}selected{% endblock %} |  | ||||||
| {% block submenu %}{% include 'seminar/soustredeni/submenu.html' %}{% endblock %} |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| {% extends "galerie/Base.html" %} | {% extends "base.html" %} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| {% block nadpis1a %} | {% block nadpis1a %} | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| {% extends "galerie/Base.html" %} | {% extends "base.html" %} | ||||||
| 
 | 
 | ||||||
| {% block nadpis1a %} | {% block nadpis1a %} | ||||||
| Galerie {{galerie.nazev}} | Galerie {{galerie.nazev}} | ||||||
|  | @ -61,7 +61,7 @@ Galerie {{galerie.nazev}} | ||||||
|             {{ galerie|truncatechars:max_delka_nazvu }} |             {{ galerie|truncatechars:max_delka_nazvu }} | ||||||
|             </div> |             </div> | ||||||
|         </a> |         </a> | ||||||
|         {% if user.is_staff and galerie.zobrazit > 0 %} |         {% if user.je_org and galerie.zobrazit > 0 %} | ||||||
|           <div class="mam-org-only-galerie"> |           <div class="mam-org-only-galerie"> | ||||||
|             ({{galerie.poradi}}) |             ({{galerie.poradi}}) | ||||||
|             <span class="plus"><a href="plus/{{galerie.pk}}/">+</a></span> |             <span class="plus"><a href="plus/{{galerie.pk}}/">+</a></span> | ||||||
|  | @ -73,7 +73,7 @@ Galerie {{galerie.nazev}} | ||||||
|       {% endwith %} |       {% endwith %} | ||||||
|     {% endif %} |     {% endif %} | ||||||
|   {% endif %} |   {% endif %} | ||||||
|   {% if user.is_staff and galerie.zobrazit > 0 %} |   {% if user.je_org and galerie.zobrazit > 0 %} | ||||||
|   <div class="mam-org-only"> |   <div class="mam-org-only"> | ||||||
|       <a href="./new">Vytvořit novou podgalerii </a> |       <a href="./new">Vytvořit novou podgalerii </a> | ||||||
|   </div> |   </div> | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| {% extends "galerie/Base.html" %} | {% extends "base.html" %} | ||||||
| 
 | 
 | ||||||
| {% block title %}{% block nadpis1a %} | {% block title %}{% block nadpis1a %} | ||||||
| Vytvářím novou galerii | Vytvářím novou galerii | ||||||
|  |  | ||||||
|  | @ -1,13 +1,14 @@ | ||||||
| # coding: utf-8 | # coding: utf-8 | ||||||
| 
 | 
 | ||||||
| from django.conf.urls import include, url | from django.urls import path | ||||||
|  | from seminar.utils import org_required | ||||||
| from . import views | from . import views | ||||||
| 
 | 
 | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|     url(r'^(?P<pk>\d+)/$', views.nahled), | 	path('<int:pk>/', views.nahled), | ||||||
|     url(r'^(?P<pk>\d+)/(?P<fotka>\d+)/$', views.detail), | 	path('<int:pk>/<int:fotka>/', views.detail), | ||||||
|     url(r'^(?P<galerie>\d+)/new/$', views.new_galerie), | 	path('<int:galerie>/new/', org_required(views.new_galerie)), | ||||||
|     url(r'^(?P<galerie>\d+)/plus/(?P<subgalerie>\d+)/$', views.plus_galerie), | 	path('<int:galerie>/plus/<int:subgalerie>/', org_required(views.plus_galerie)), | ||||||
|     url(r'^(?P<galerie>\d+)/minus/(?P<subgalerie>\d+)/$', views.minus_galerie), | 	path('<int:galerie>/minus/<int:subgalerie>/', org_required(views.minus_galerie)), | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										371
									
								
								galerie/views.py
									
									
									
									
									
								
							
							
						
						|  | @ -12,226 +12,225 @@ from seminar.models import Soustredeni | ||||||
| from galerie.forms import KomentarForm, NewGalerieForm | from galerie.forms import KomentarForm, NewGalerieForm | ||||||
| 
 | 
 | ||||||
| def zobrazit(galerie, request): | def zobrazit(galerie, request): | ||||||
|     preview = False | 	preview = False | ||||||
|     if galerie.zobrazit >= 1: | 	if galerie.zobrazit >= 1: | ||||||
|         if request.user.is_staff: | 		if request.user.je_org: | ||||||
|             preview = True; | 			preview = True; | ||||||
|         else: | 		else: | ||||||
|             raise Http404 | 			raise Http404 | ||||||
|     return preview | 	return preview | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def cesta_od_korene(g): | def cesta_od_korene(g): | ||||||
|     """Vrátí seznam galerií od kořene ke g""" | 	"""Vrátí seznam galerií od kořene ke g""" | ||||||
|     cesta = [] | 	cesta = [] | ||||||
|     while g != None: | 	while g != None: | ||||||
|         cesta.append(g) | 		cesta.append(g) | ||||||
|         g = g.galerie_up | 		g = g.galerie_up | ||||||
|     return reversed(cesta) | 	return reversed(cesta) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def nahled(request, pk, soustredeni): | def nahled(request, pk, soustredeni): | ||||||
|     """Zobrazeni nahledu vsech fotek ve skupine.""" | 	"""Zobrazeni nahledu vsech fotek ve skupine.""" | ||||||
|     galerie = get_object_or_404(Galerie, pk=pk) | 	galerie = get_object_or_404(Galerie, pk=pk) | ||||||
| 
 | 
 | ||||||
|     podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi') | 	podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi') | ||||||
|     if not request.user.is_staff: | 	if not request.user.je_org: | ||||||
|         podgalerie = podgalerie.filter(zobrazit__lt=1) | 		podgalerie = podgalerie.filter(zobrazit__lt=1) | ||||||
| 
 | 
 | ||||||
|     obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev') | 	obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev') | ||||||
|     preview = zobrazit(galerie, request) | 	preview = zobrazit(galerie, request) | ||||||
| 
 | 
 | ||||||
|     sourozenci = [] | 	sourozenci = [] | ||||||
|     if galerie.galerie_up: | 	if galerie.galerie_up: | ||||||
|         sourozenci = galerie.galerie_up.galerie_set.all().order_by('poradi') | 		sourozenci = galerie.galerie_up.galerie_set.all().order_by('poradi') | ||||||
|         if not request.user.is_staff: | 		if not request.user.je_org: | ||||||
|             sourozenci = sourozenci.filter(zobrazit__lt=1) | 			sourozenci = sourozenci.filter(zobrazit__lt=1) | ||||||
| 
 | 
 | ||||||
|     predchozi = None | 	predchozi = None | ||||||
|     nasledujici = None | 	nasledujici = None | ||||||
|     minuly = None | 	minuly = None | ||||||
|     for g in sourozenci: | 	for g in sourozenci: | ||||||
|         if g.pk == galerie.pk: | 		if g.pk == galerie.pk: | ||||||
|             predchozi = minuly | 			predchozi = minuly | ||||||
|         if minuly != None and minuly.pk == galerie.pk: | 		if minuly != None and minuly.pk == galerie.pk: | ||||||
|             nasledujici = g | 			nasledujici = g | ||||||
|             break | 			break | ||||||
|         minuly = g | 		minuly = g | ||||||
| 
 | 
 | ||||||
|     cesta = cesta_od_korene(galerie) | 	cesta = cesta_od_korene(galerie) | ||||||
| 
 | 
 | ||||||
|     return render(request, 'galerie/GalerieNahled.html', | 	return render(request, 'galerie/GalerieNahled.html', | ||||||
|         {'galerie' : galerie, | 		{'galerie' : galerie, | ||||||
|          'podgalerie' : podgalerie, | 		 'podgalerie' : podgalerie, | ||||||
|          'obrazky' : obrazky, | 		 'obrazky' : obrazky, | ||||||
|          'preview' : preview, | 		 'preview' : preview, | ||||||
|          'cesta': cesta, | 		 'cesta': cesta, | ||||||
|          'sourozenci': sourozenci, | 		 'sourozenci': sourozenci, | ||||||
|          'predchozi': predchozi, | 		 'predchozi': predchozi, | ||||||
|          'nasledujici': nasledujici, | 		 'nasledujici': nasledujici, | ||||||
|         }) | 		}) | ||||||
| 
 | 
 | ||||||
| def detail(request, pk, fotka, soustredeni): | def detail(request, pk, fotka, soustredeni): | ||||||
|   """Zobrazeni nahledu fotky s id 'fotka'.""" | 	"""Zobrazeni nahledu fotky s id 'fotka'.""" | ||||||
|   MAX_VYSKA = 900 | 	MAX_VYSKA = 900 | ||||||
|   MAX_SIRKA = 900 | 	MAX_SIRKA = 900 | ||||||
|   MAX_VYSKA_MALA = 100 | 	MAX_VYSKA_MALA = 100 | ||||||
|   MAX_SIRKA_MALA = 200 | 	MAX_SIRKA_MALA = 200 | ||||||
|   NAHLEDU = 1 | 	NAHLEDU = 1 | ||||||
| 
 | 
 | ||||||
|   galerie = get_object_or_404(Galerie, pk=pk) | 	galerie = get_object_or_404(Galerie, pk=pk) | ||||||
|   preview = zobrazit(galerie, request) | 	preview = zobrazit(galerie, request) | ||||||
|   obrazek = get_object_or_404(Obrazek, pk=fotka) | 	obrazek = get_object_or_404(Obrazek, pk=fotka) | ||||||
|   obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev') | 	obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev') | ||||||
| 
 | 
 | ||||||
|   # vytvoreni a obslouzeni formulare | 	# vytvoreni a obslouzeni formulare | ||||||
|   if request.method == 'POST': | 	if request.method == 'POST': | ||||||
|       form = KomentarForm(request.POST) | 		form = KomentarForm(request.POST) | ||||||
|       if form.is_valid(): | 		if form.is_valid(): | ||||||
|           obrazek.popis = form.cleaned_data['komentar'] | 			obrazek.popis = form.cleaned_data['komentar'] | ||||||
|           obrazek.save() | 			obrazek.save() | ||||||
|   else: | 	else: | ||||||
|       form = KomentarForm({'komentar': obrazek.popis}) | 		form = KomentarForm({'komentar': obrazek.popis}) | ||||||
| 
 | 
 | ||||||
|   # Poradi aktualniho obrazku v galerii/stitku. | 	# Poradi aktualniho obrazku v galerii/stitku. | ||||||
|   for i in range(len(obrazky)): | 	for i in range(len(obrazky)): | ||||||
|     if obrazky[i] == obrazek: | 		if obrazky[i] == obrazek: | ||||||
|       poradi = i | 			poradi = i | ||||||
|       break | 			break | ||||||
|   else: | 	else: | ||||||
|     # Obrazek neni v galerii/stitku. | 		# Obrazek neni v galerii/stitku. | ||||||
|     raise Http404 | 		raise Http404 | ||||||
| 
 | 
 | ||||||
| 	 | 	 | ||||||
|   # Nacteni okolnich obrazku a galerii | 	# Nacteni okolnich obrazku a galerii | ||||||
|   # TODO vyjmout zjisteni predchozich a nasledujicich galerii | 	# TODO vyjmout zjisteni predchozich a nasledujicich galerii | ||||||
|   # a udelat z toho funkci, ktera se pouzije u nahledu | 	# a udelat z toho funkci, ktera se pouzije u nahledu | ||||||
|   predchozi_galerie = None | 	predchozi_galerie = None | ||||||
|   nasledujici_galerie = None | 	nasledujici_galerie = None | ||||||
|   obrazky_dalsi = obrazky[poradi+1:poradi+NAHLEDU+1] | 	obrazky_dalsi = obrazky[poradi+1:poradi+NAHLEDU+1] | ||||||
|   if (poradi+1) > NAHLEDU: | 	if (poradi+1) > NAHLEDU: | ||||||
|     obrazky_predchozi = obrazky[poradi-NAHLEDU:poradi] | 		obrazky_predchozi = obrazky[poradi-NAHLEDU:poradi] | ||||||
|   else: | 	else: | ||||||
|     obrazky_predchozi = obrazky[0:poradi] | 		obrazky_predchozi = obrazky[0:poradi] | ||||||
|     if galerie.poradi > 1: | 		if galerie.poradi > 1: | ||||||
|         predchozi_galerie = Galerie.objects.\ | 			predchozi_galerie = Galerie.objects.\ | ||||||
|             filter(galerie_up=galerie.galerie_up).\ | 				filter(galerie_up=galerie.galerie_up).\ | ||||||
|             filter(poradi=(galerie.poradi-1)) | 				filter(poradi=(galerie.poradi-1)) | ||||||
|     if predchozi_galerie: | 		if predchozi_galerie: | ||||||
|         predchozi_galerie = predchozi_galerie[0] | 			predchozi_galerie = predchozi_galerie[0] | ||||||
|     else: | 		else: | ||||||
|         predchozi_galerie = None | 			predchozi_galerie = None | ||||||
|   if (poradi+1) == len(obrazky):    # Tohle je poslední obrázek | 	if (poradi+1) == len(obrazky):		# Tohle je poslední obrázek | ||||||
|     if (galerie.poradi is not None | 		if (galerie.poradi is not None | ||||||
|       and galerie.galerie_up is not None): | 			and galerie.galerie_up is not None): | ||||||
|         nasledujici_galerie = Galerie.objects.\ | 				nasledujici_galerie = Galerie.objects.\ | ||||||
|             filter(galerie_up=galerie.galerie_up).\ | 					filter(galerie_up=galerie.galerie_up).\ | ||||||
|             filter(poradi=(galerie.poradi+1)) | 					filter(poradi=(galerie.poradi+1)) | ||||||
|     else: | 		else: | ||||||
|         nasledujici_galerie = None | 			nasledujici_galerie = None | ||||||
|     if nasledujici_galerie: | 		if nasledujici_galerie: | ||||||
|         nasledujici_galerie = nasledujici_galerie[0] | 			nasledujici_galerie = nasledujici_galerie[0] | ||||||
|     else: | 		else: | ||||||
|         nasledujici_galerie = None | 			nasledujici_galerie = None | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	 | 	 | ||||||
|   # Preskalovani obrazku do vybraneho prostoru. | 	# Preskalovani obrazku do vybraneho prostoru. | ||||||
|   vyska = obrazek.obrazek_stredni.height | 	vyska = obrazek.obrazek_stredni.height | ||||||
|   sirka = obrazek.obrazek_stredni.width | 	sirka = obrazek.obrazek_stredni.width | ||||||
|   if vyska > MAX_VYSKA: | 	if vyska > MAX_VYSKA: | ||||||
|     sirka = sirka * MAX_VYSKA / vyska   | 		sirka = sirka * MAX_VYSKA / vyska	 | ||||||
|     vyska = MAX_VYSKA | 		vyska = MAX_VYSKA | ||||||
|   if sirka > MAX_SIRKA: | 	if sirka > MAX_SIRKA: | ||||||
|     vyska = vyska * MAX_SIRKA / sirka | 		vyska = vyska * MAX_SIRKA / sirka | ||||||
|     sirka = MAX_SIRKA | 		sirka = MAX_SIRKA | ||||||
| 
 |  | ||||||
|   return render(request, 'galerie/Galerie.html', |  | ||||||
|       {'galerie' : galerie, |  | ||||||
|        'predchozi_galerie' : predchozi_galerie, |  | ||||||
|        'nasledujici_galerie' : nasledujici_galerie, |  | ||||||
|        'obrazek' : obrazek, |  | ||||||
|        'vyska' : vyska, |  | ||||||
|        'sirka' : sirka, |  | ||||||
|        'obrazky_predchozi' : obrazky_predchozi, |  | ||||||
|        'obrazky_dalsi' : obrazky_dalsi, |  | ||||||
|        'preview' : preview, |  | ||||||
|        'form' : form, |  | ||||||
|        'cesta': cesta_od_korene(galerie), |  | ||||||
|       }) |  | ||||||
| 
 | 
 | ||||||
|  | 	return render(request, 'galerie/Galerie.html', | ||||||
|  | 		{'galerie' : galerie, | ||||||
|  | 		 'predchozi_galerie' : predchozi_galerie, | ||||||
|  | 		 'nasledujici_galerie' : nasledujici_galerie, | ||||||
|  | 		 'obrazek' : obrazek, | ||||||
|  | 		 'vyska' : vyska, | ||||||
|  | 		 'sirka' : sirka, | ||||||
|  | 		 'obrazky_predchozi' : obrazky_predchozi, | ||||||
|  | 		 'obrazky_dalsi' : obrazky_dalsi, | ||||||
|  | 		 'preview' : preview, | ||||||
|  | 		 'form' : form, | ||||||
|  | 		 'cesta': cesta_od_korene(galerie), | ||||||
|  | 		}) | ||||||
| 
 | 
 | ||||||
| def new_galerie(request, galerie, soustredeni): | def new_galerie(request, galerie, soustredeni): | ||||||
| 
 | 
 | ||||||
|     # zjistime k jakemu soustredeni se vaze nove vytvarena galerie | 	# zjistime k jakemu soustredeni se vaze nove vytvarena galerie | ||||||
|     soustredeni = get_object_or_404(Soustredeni, pk = soustredeni) | 	soustredeni = get_object_or_404(Soustredeni, pk = soustredeni) | ||||||
|     # pokud je parametr galerie 0, pak jde o hlavni galerii | 	# pokud je parametr galerie 0, pak jde o hlavni galerii | ||||||
|     # kdyz je nejaky jiny, pak je pk galerie pod kterou tu dalsi vytvarim | 	# kdyz je nejaky jiny, pak je pk galerie pod kterou tu dalsi vytvarim | ||||||
|     if int(galerie) == 0: | 	if int(galerie) == 0: | ||||||
|         galerie_up = False | 		galerie_up = False | ||||||
|         galerie_text = "Hlavní fotogalerie soustředění" | 		galerie_text = "Hlavní fotogalerie soustředění" | ||||||
|     else: | 	else: | ||||||
|         galerie_up = get_object_or_404(Galerie, pk = int(galerie)) | 		galerie_up = get_object_or_404(Galerie, pk = int(galerie)) | ||||||
|         galerie_text = "podgalerii ke galerii " + str(galerie_up) | 		galerie_text = "podgalerii ke galerii " + str(galerie_up) | ||||||
| 
 | 
 | ||||||
|     # obsluha formulare umoznujiciho multiple nahravani fotek | 	# obsluha formulare umoznujiciho multiple nahravani fotek | ||||||
|     if request.method == 'POST': | 	if request.method == 'POST': | ||||||
|         form = NewGalerieForm(request.POST, request.FILES) | 		form = NewGalerieForm(request.POST, request.FILES) | ||||||
|         if form.is_valid(): | 		if form.is_valid(): | ||||||
|             # vytvoreni nove galerie | 			# vytvoreni nove galerie | ||||||
|             gal = Galerie() | 			gal = Galerie() | ||||||
|             gal.nazev = form.cleaned_data['nazev'] | 			gal.nazev = form.cleaned_data['nazev'] | ||||||
|             #gal.popis = form.cleaned_data['popis'] # popis nepouzivame | 			#gal.popis = form.cleaned_data['popis'] # popis nepouzivame | ||||||
|             gal.zobrazit = 1 # galerie je v procesu vytvareni | 			gal.zobrazit = 1 # galerie je v procesu vytvareni | ||||||
|             ''' pokud je to podgalerie pridej nadrazenou galerii | 			''' pokud je to podgalerie pridej nadrazenou galerii | ||||||
|             a nadrazene soustredeni nechej volne, | 			a nadrazene soustredeni nechej volne, | ||||||
|             pokud je to hlavni galerie, tak nadrazena galerie neexistuje, | 			pokud je to hlavni galerie, tak nadrazena galerie neexistuje, | ||||||
|             ale v takovem pripade musi byt nadrazene soustredeni a ne jinak ''' | 			ale v takovem pripade musi byt nadrazene soustredeni a ne jinak ''' | ||||||
|             if galerie_up: | 			if galerie_up: | ||||||
|                 gal.galerie_up = galerie_up | 				gal.galerie_up = galerie_up | ||||||
|             else: | 			else: | ||||||
|                 gal.soustredeni = soustredeni | 				gal.soustredeni = soustredeni | ||||||
|             if gal.galerie_up: | 			if gal.galerie_up: | ||||||
|                 gal.poradi = int(len(gal.galerie_up.galerie_set.all())) + 1  | 				gal.poradi = int(len(gal.galerie_up.galerie_set.all())) + 1  | ||||||
|             gal.save() | 			gal.save() | ||||||
| 
 | 
 | ||||||
|             # zpracovani obrazku v galerii | 			# zpracovani obrazku v galerii | ||||||
|             for obr in request.FILES.getlist('obr'): | 			for obr in request.FILES.getlist('obr'): | ||||||
|                 o = Obrazek() | 				o = Obrazek() | ||||||
|                 o.obrazek_velky = obr | 				o.obrazek_velky = obr | ||||||
|                 o.nazev = str(obr) | 				o.nazev = str(obr) | ||||||
|                 o.galerie = gal | 				o.galerie = gal | ||||||
|                 o.save() | 				o.save() | ||||||
| 
 | 
 | ||||||
|             # presmerovani na prave vzniklou galerii | 			# presmerovani na prave vzniklou galerii | ||||||
|             return HttpResponseRedirect('../../' + str(gal.pk)) | 			return HttpResponseRedirect('../../' + str(gal.pk)) | ||||||
| 
 | 
 | ||||||
|     else: | 	else: | ||||||
|         form = NewGalerieForm() | 		form = NewGalerieForm() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     return render(request, 'galerie/GalerieNew.html', | 	return render(request, 'galerie/GalerieNew.html', | ||||||
|             { | 			{ | ||||||
|                 'form' : form, | 				'form' : form, | ||||||
|                 'soustredeni' : soustredeni, | 				'soustredeni' : soustredeni, | ||||||
|                 'galerie_text' : galerie_text, | 				'galerie_text' : galerie_text, | ||||||
|                 }) | 				}) | ||||||
| 
 | 
 | ||||||
| def plus_galerie(request, galerie, soustredeni, subgalerie): | def plus_galerie(request, galerie, soustredeni, subgalerie): | ||||||
|     galerie = get_object_or_404(Galerie, pk=subgalerie) | 	galerie = get_object_or_404(Galerie, pk=subgalerie) | ||||||
|     if galerie.poradi: | 	if galerie.poradi: | ||||||
|         galerie.poradi += 1 | 		galerie.poradi += 1 | ||||||
|     else: | 	else: | ||||||
|         galerie.poradi = int(len(galerie.galerie_up.galerie_set.all())) | 		galerie.poradi = int(len(galerie.galerie_up.galerie_set.all())) | ||||||
|     galerie.save() | 	galerie.save() | ||||||
|     return HttpResponseRedirect('../../') | 	return HttpResponseRedirect('../../') | ||||||
| 
 | 
 | ||||||
| def minus_galerie(request, galerie, soustredeni, subgalerie): | def minus_galerie(request, galerie, soustredeni, subgalerie): | ||||||
|     galerie = get_object_or_404(Galerie, pk=subgalerie) | 	galerie = get_object_or_404(Galerie, pk=subgalerie) | ||||||
|     if galerie.poradi: | 	if galerie.poradi: | ||||||
|         galerie.poradi -= 1 | 		galerie.poradi -= 1 | ||||||
|     else: | 	else: | ||||||
|         galerie.poradi = 1 | 		galerie.poradi = 1 | ||||||
|     galerie.save() | 	galerie.save() | ||||||
|     return HttpResponseRedirect('../../') | 	return HttpResponseRedirect('../../') | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										0
									
								
								header_fotky/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										10
									
								
								header_fotky/admin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,10 @@ | ||||||
|  | from django.contrib import admin | ||||||
|  | from django.contrib.admin import ModelAdmin | ||||||
|  | import header_fotky.models as m | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FotkaPozadiAdmin(ModelAdmin): | ||||||
|  |     readonly_fields = ['cas'] | ||||||
|  | 
 | ||||||
|  | admin.site.register(m.FotkaHeader, FotkaPozadiAdmin) | ||||||
|  | admin.site.register(m.FotkaUrlVazba) | ||||||
							
								
								
									
										5
									
								
								header_fotky/apps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,5 @@ | ||||||
|  | from django.apps import AppConfig | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class HeaderFotkyConfig(AppConfig): | ||||||
|  |     name = 'header_fotky' | ||||||
							
								
								
									
										45
									
								
								header_fotky/context_processors.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,45 @@ | ||||||
|  | 
 | ||||||
|  | from datetime import datetime, date | ||||||
|  | import random | ||||||
|  | 
 | ||||||
|  | from django.conf import settings | ||||||
|  | 
 | ||||||
|  | from header_fotky.models import FotkaUrlVazba | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def vzhled(request): | ||||||
|  |     ''' Podle casu prida do templatu, zdali je nebo neni noc ''' | ||||||
|  |     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 | ||||||
|  | 
 | ||||||
|  |     # 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] | ||||||
|  | 
 | ||||||
|  |     if fotka is None: | ||||||
|  |         fotka = settings.STATIC_URL + "images/header/vikendovka.jpg" | ||||||
|  | 
 | ||||||
|  |     return {'noc': noc, 'fotka': fotka} | ||||||
|  | 
 | ||||||
							
								
								
									
										63
									
								
								header_fotky/migrations/0001_initial.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,63 @@ | ||||||
|  | # Generated by Django 2.2.15 on 2020-09-20 09:14 | ||||||
|  | 
 | ||||||
|  | from django.db import migrations, models | ||||||
|  | import django.db.models.deletion | ||||||
|  | import django.utils.timezone | ||||||
|  | 
 | ||||||
|  | from shutil import copytree | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def zkopiruj_fotky(apps, schema_editor): | ||||||
|  |     try: | ||||||
|  |         copytree("mamweb/static/images/header/", "media/header/") # FIXME: bylo tu dirs_exists_ok=True, nekompatibilní s Py 3.7 | ||||||
|  |     except FileExistsError: | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |     initial = True | ||||||
|  | 
 | ||||||
|  |     dependencies = [ | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     operations = [ | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name='FotkaHeader', | ||||||
|  |             fields=[ | ||||||
|  |                 ('cas', models.DateTimeField(default=django.utils.timezone.now, help_text='Čas vložení fotky', | ||||||
|  |                                              verbose_name='čas vložení fotky')), | ||||||
|  |                 ('nazev', | ||||||
|  |                  models.CharField(help_text='Název např. archiv_noc', max_length=50, primary_key=True, serialize=False, | ||||||
|  |                                   unique=True, verbose_name='název fotky')), | ||||||
|  |                 ('fotka', models.ImageField(upload_to='header')), | ||||||
|  |             ], | ||||||
|  |             options={ | ||||||
|  |                 'verbose_name': 'fotka do pozadí menu', | ||||||
|  |                 'verbose_name_plural': 'fotky do pozadí menu', | ||||||
|  |                 'db_table': 'fotky_header', | ||||||
|  |                 'ordering': ['-cas'], | ||||||
|  |             }, | ||||||
|  |         ), | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name='FotkaUrlVazba', | ||||||
|  |             fields=[ | ||||||
|  |                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||||
|  |                 ('url', | ||||||
|  |                  models.CharField(blank=True, help_text='url prefix stránek např: /archiv/ nebo /', max_length=100, | ||||||
|  |                                   verbose_name='URL')), | ||||||
|  |                 ('denni_doba', models.CharField(choices=[('den', 'Zobrazit jen ve dne'), ('noc', 'Zobrazit jen v noci'), | ||||||
|  |                                                          ('oboji', 'Zobrazovat pořád')], default='oboji', max_length=16, | ||||||
|  |                                                 verbose_name='denní doba')), | ||||||
|  |                 ('fotka', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='header_fotky.FotkaHeader', | ||||||
|  |                                             verbose_name='fotka')), | ||||||
|  |             ], | ||||||
|  |             options={ | ||||||
|  |                 'verbose_name': 'vazba url a fotky do pozadí menu', | ||||||
|  |                 'verbose_name_plural': 'vazby url a fotek do pozadí menu', | ||||||
|  |                 'db_table': 'fotky_url_vazby', | ||||||
|  |                 'ordering': ['url'], | ||||||
|  |             }, | ||||||
|  | 
 | ||||||
|  |         ), | ||||||
|  |         migrations.RunPython(zkopiruj_fotky, migrations.RunPython.noop), | ||||||
|  |     ] | ||||||
							
								
								
									
										0
									
								
								header_fotky/migrations/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										65
									
								
								header_fotky/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,65 @@ | ||||||
|  | from django.core.exceptions import ValidationError | ||||||
|  | from django.db import models | ||||||
|  | from django.utils import timezone | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FotkaHeader(models.Model): | ||||||
|  | 	class Meta: | ||||||
|  | 		ordering = ['-cas'] | ||||||
|  | 		db_table = 'fotky_header' | ||||||
|  | 		verbose_name = u'fotka do pozadí menu' | ||||||
|  | 		verbose_name_plural = u'fotky do pozadí menu' | ||||||
|  | 
 | ||||||
|  | 	cas = models.DateTimeField(u'čas vložení fotky', default=timezone.now, help_text='Čas vložení fotky') | ||||||
|  | 
 | ||||||
|  | 	nazev = models.CharField( | ||||||
|  | 		u'název fotky', null=False, blank=False, unique=True, primary_key=True, | ||||||
|  | 		max_length=50, help_text='Název např. archiv_noc' | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	fotka = models.ImageField(upload_to='header', null=False, blank=False) | ||||||
|  | 
 | ||||||
|  | 	def __str__(self): | ||||||
|  | 		return self.nazev | ||||||
|  | 
 | ||||||
|  | 	def clean(self): | ||||||
|  | 		if not self.fotka: | ||||||
|  | 			raise ValidationError("Chybí obrázek") | ||||||
|  | 		""" Kontroluje, zda sedí poměr stran """ | ||||||
|  | 		if abs(self.fotka.width - (self.fotka.height * 970 / 350)) > 2: | ||||||
|  | 			raise ValidationError("Obrázek by měl mít rozměry 970w na 350h, nebo alespoň podobný poměr stran.") | ||||||
|  | 		super().clean() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FotkaUrlVazba(models.Model): | ||||||
|  | 	class Meta: | ||||||
|  | 		ordering = ['url'] | ||||||
|  | 		db_table = 'fotky_url_vazby' | ||||||
|  | 		verbose_name = u'vazba url a fotky do pozadí menu' | ||||||
|  | 		verbose_name_plural = u'vazby url a fotek do pozadí menu' | ||||||
|  | 
 | ||||||
|  | 	url = models.CharField( | ||||||
|  | 		u'URL', blank=True, null=False, max_length=100, | ||||||
|  | 		help_text='url prefix stránek např: /archiv/ nebo /' | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	fotka = models.ForeignKey( | ||||||
|  | 		FotkaHeader, blank=False, null=False, verbose_name='fotka', | ||||||
|  | 		on_delete=models.CASCADE | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	DOBA_DEN = 'den' | ||||||
|  | 	DOBA_NOC = 'noc' | ||||||
|  | 	DOBA_OBOJI = 'oboji' | ||||||
|  | 	DOBA_CHOICES = [ | ||||||
|  | 		(DOBA_DEN, 'Zobrazit jen ve dne'), | ||||||
|  | 		(DOBA_NOC, 'Zobrazit jen v noci'), | ||||||
|  | 		(DOBA_OBOJI, 'Zobrazovat pořád')] | ||||||
|  | 
 | ||||||
|  | 	denni_doba = models.CharField('denní doba', max_length=16, choices=DOBA_CHOICES, blank=False, default=DOBA_OBOJI) | ||||||
|  | 
 | ||||||
|  | 	def __str__(self): | ||||||
|  | 		return self.url | ||||||
|  | 
 | ||||||
|  | 	def url_fotky(self): | ||||||
|  | 		return self.fotka.fotka.url | ||||||
							
								
								
									
										7
									
								
								ilustrace_odmeny/jak_nahrat_do_flatpage
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,7 @@ | ||||||
|  | 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 | ||||||
|  | přespočí to zpět, velikost nechat, jen ok | ||||||
|  | přepnout na html zdroj, k obrázku (dovnitř img tagu) nahradit style za: | ||||||
|  | 	style="display:block; margin-left: auto; margin-right: auto; width: 70%;" | ||||||
|  | 	pro dort méně než 70%, asi 60% či 55%, okometricky | ||||||
							
								
								
									
										16
									
								
								init_local.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						|  | @ -0,0 +1,16 @@ | ||||||
|  | #!/bin/sh | ||||||
|  | 
 | ||||||
|  | set -e # Spadni pokud něco spadne | ||||||
|  | 
 | ||||||
|  | # Check venvu | ||||||
|  | # NOTE: zkontroluje i správnou složku -- existencí Makefilu | ||||||
|  | make venv_check | ||||||
|  | 
 | ||||||
|  | # Vygenerujeme testdata | ||||||
|  | ./manage.py testdata | ||||||
|  | 
 | ||||||
|  | # Nahrajeme statický obsah modelů | ||||||
|  | ./manage.py loaddata flat.json sitetree_new.json | ||||||
|  | 
 | ||||||
|  | # Posbíráme statické soubory | ||||||
|  | ./manage.py collectstatic | ||||||
|  | @ -6,21 +6,21 @@ from korektury.models import KorekturovanePDF | ||||||
| # Register your models here. | # Register your models here. | ||||||
| class KorekturovanePDFAdmin(VersionAdmin): | class KorekturovanePDFAdmin(VersionAdmin): | ||||||
| 
 | 
 | ||||||
|     readonly_fields = ['cas', 'stran'] | 	readonly_fields = ['cas', 'stran'] | ||||||
| 
 | 
 | ||||||
|     def get_readonly_fields(self, request, obj=None): | 	def get_readonly_fields(self, request, obj=None): | ||||||
|         if obj: | 		if obj: | ||||||
|             return self.readonly_fields + ['pdf'] | 			return self.readonly_fields + ['pdf'] | ||||||
|         return self.readonly_fields | 		return self.readonly_fields | ||||||
| 
 | 
 | ||||||
|     fieldsets = [ | 	fieldsets = [ | ||||||
|             (None, | 			(None, | ||||||
|                 {'fields': | 				{'fields': | ||||||
|                     ['pdf', 'cas', 'org', 'stran', 'nazev', 'komentar']}), | 					['pdf', 'cas', 'org', 'stran', 'nazev', 'komentar']}), | ||||||
|             # (u'PDF',       {'fields': ['pdf']}), | 			# (u'PDF',       {'fields': ['pdf']}), | ||||||
|                 ] | 				] | ||||||
|     list_display = ['nazev', 'cas', 'stran', 'org'] | 	list_display = ['nazev', 'cas', 'stran', 'org'] | ||||||
|     list_filter = [] | 	list_filter = [] | ||||||
|     search_fields = [] | 	search_fields = [] | ||||||
| 
 | 
 | ||||||
| admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin) | admin.site.register(KorekturovanePDF, KorekturovanePDFAdmin) | ||||||
|  |  | ||||||
|  | @ -1,13 +1,13 @@ | ||||||
| from django import forms | from django import forms | ||||||
| 
 | 
 | ||||||
| class OpravaForm(forms.Form): | class OpravaForm(forms.Form): | ||||||
|     text = forms.CharField(max_length=256) | 	text = forms.CharField(max_length=256) | ||||||
|     autor = forms.CharField(max_length=20) | 	autor = forms.CharField(max_length=20) | ||||||
|     x = forms.IntegerField() | 	x = forms.IntegerField() | ||||||
|     y = forms.IntegerField() | 	y = forms.IntegerField() | ||||||
|     scroll = forms.CharField(max_length=256) | 	scroll = forms.CharField(max_length=256) | ||||||
|     pdf = forms.CharField(max_length=256) | 	pdf = forms.CharField(max_length=256) | ||||||
|     img_id = forms.CharField(max_length=256) | 	img_id = forms.CharField(max_length=256) | ||||||
|     id = forms.CharField(max_length=256) | 	id = forms.CharField(max_length=256) | ||||||
|     action = forms.CharField(max_length=256) | 	action = forms.CharField(max_length=256) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ class Migration(migrations.Migration): | ||||||
|                 ('cas', models.DateTimeField(help_text=b'\xc4\x8cas zad\xc3\xa1n\xc3\xad koment\xc3\xa1\xc5\x99e', verbose_name='\u010das koment\xe1\u0159e')), |                 ('cas', models.DateTimeField(help_text=b'\xc4\x8cas zad\xc3\xa1n\xc3\xad koment\xc3\xa1\xc5\x99e', verbose_name='\u010das koment\xe1\u0159e')), | ||||||
|                 ('autor', models.TextField(help_text=b'Autor koment\xc3\xa1\xc5\x99e', verbose_name='autor koment\xe1\u0159e', blank=True)), |                 ('autor', models.TextField(help_text=b'Autor koment\xc3\xa1\xc5\x99e', verbose_name='autor koment\xe1\u0159e', blank=True)), | ||||||
|                 ('text', models.TextField(help_text=b'Text koment\xc3\xa1\xc5\x99e', verbose_name='text koment\xe1\u0159e', blank=True)), |                 ('text', models.TextField(help_text=b'Text koment\xc3\xa1\xc5\x99e', verbose_name='text koment\xe1\u0159e', blank=True)), | ||||||
|                 ('oprava', models.ForeignKey(to='korektury.Oprava')), |                 ('oprava', models.ForeignKey(to='korektury.Oprava', on_delete=models.CASCADE)), | ||||||
|             ], |             ], | ||||||
|             options={ |             options={ | ||||||
|                 'ordering': ['cas'], |                 'ordering': ['cas'], | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ class Migration(migrations.Migration): | ||||||
|                 ('cas', models.DateTimeField(default=django.utils.timezone.now, help_text=b'\xc4\x8cas zad\xc3\xa1n\xc3\xad koment\xc3\xa1\xc5\x99e', verbose_name='\u010das koment\xe1\u0159e')), |                 ('cas', models.DateTimeField(default=django.utils.timezone.now, help_text=b'\xc4\x8cas zad\xc3\xa1n\xc3\xad koment\xc3\xa1\xc5\x99e', verbose_name='\u010das koment\xe1\u0159e')), | ||||||
|                 ('autor', models.TextField(help_text=b'Autor koment\xc3\xa1\xc5\x99e', verbose_name='autor koment\xe1\u0159e', blank=True)), |                 ('autor', models.TextField(help_text=b'Autor koment\xc3\xa1\xc5\x99e', verbose_name='autor koment\xe1\u0159e', blank=True)), | ||||||
|                 ('text', models.TextField(help_text=b'Text koment\xc3\xa1\xc5\x99e', verbose_name='text koment\xe1\u0159e', blank=True)), |                 ('text', models.TextField(help_text=b'Text koment\xc3\xa1\xc5\x99e', verbose_name='text koment\xe1\u0159e', blank=True)), | ||||||
|                 ('oprava', models.ForeignKey(to='korektury.Oprava')), |                 ('oprava', models.ForeignKey(to='korektury.Oprava', on_delete=models.CASCADE)), | ||||||
|             ], |             ], | ||||||
|             options={ |             options={ | ||||||
|                 'ordering': ['cas'], |                 'ordering': ['cas'], | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ class Migration(migrations.Migration): | ||||||
|         migrations.AddField( |         migrations.AddField( | ||||||
|             model_name='oprava', |             model_name='oprava', | ||||||
|             name='pdf', |             name='pdf', | ||||||
|             field=models.ForeignKey(default=-1, to='korektury.KorekturovanePDF'), |             field=models.ForeignKey(default=-1, to='korektury.KorekturovanePDF', on_delete=models.CASCADE), | ||||||
|             preserve_default=True, |             preserve_default=True, | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
|  | @ -15,11 +15,11 @@ class Migration(migrations.Migration): | ||||||
|         migrations.AddField( |         migrations.AddField( | ||||||
|             model_name='komentar', |             model_name='komentar', | ||||||
|             name='autor_org', |             name='autor_org', | ||||||
|             field=models.ForeignKey(blank=True, to='seminar.Organizator', help_text='Autor koment\xe1\u0159e', null=True), |             field=models.ForeignKey(blank=True, to='seminar.Organizator', help_text='Autor koment\xe1\u0159e', null=True, on_delete=models.CASCADE), | ||||||
|         ), |         ), | ||||||
|         migrations.AddField( |         migrations.AddField( | ||||||
|             model_name='oprava', |             model_name='oprava', | ||||||
|             name='autor_org', |             name='autor_org', | ||||||
|             field=models.ForeignKey(blank=True, to='seminar.Organizator', help_text=b'Autor opravy', null=True), |             field=models.ForeignKey(blank=True, to='seminar.Organizator', help_text=b'Autor opravy', null=True, on_delete=models.CASCADE), | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
|  | @ -18,10 +18,10 @@ def transform_autor(apps, schema_editor): | ||||||
|                 oprava.autor_org = org |                 oprava.autor_org = org | ||||||
|                 oprava.save() |                 oprava.save() | ||||||
|             except: |             except: | ||||||
|                 print "Org nenalezen -- mažu korekturu" |                 print("Org nenalezen -- mažu korekturu") | ||||||
| #                oprava.delete() | #                oprava.delete() | ||||||
|         else: |         else: | ||||||
|             print "Org nenalezen -- mažu korekturu" |             print("Org nenalezen -- mažu korekturu") | ||||||
|             oprava.delete() |             oprava.delete() | ||||||
| 
 | 
 | ||||||
|     # preorgovani komentaru |     # preorgovani komentaru | ||||||
|  | @ -35,10 +35,10 @@ def transform_autor(apps, schema_editor): | ||||||
|                 komentar.autor_org = org |                 komentar.autor_org = org | ||||||
|                 komentar.save() |                 komentar.save() | ||||||
|             except: |             except: | ||||||
|                 print "Org nenalezen -- mažu korekturu" |                 print("Org nenalezen -- mažu korekturu") | ||||||
| #                oprava.delete() | #                oprava.delete() | ||||||
|         else: |         else: | ||||||
|             print "Org nenalezen -- mažu korekturu" |             print("Org nenalezen -- mažu korekturu") | ||||||
|             komentar.delete() |             komentar.delete() | ||||||
| 
 | 
 | ||||||
| def back(apps, schema_editor): | def back(apps, schema_editor): | ||||||
|  |  | ||||||
|  | @ -16,10 +16,10 @@ class Migration(migrations.Migration): | ||||||
|             model_name='korekturovanepdf', |             model_name='korekturovanepdf', | ||||||
|             name='org', |             name='org', | ||||||
|             field=models.ForeignKey(default=None, |             field=models.ForeignKey(default=None, | ||||||
|                                     blank=True, |                   blank=True, | ||||||
|                                     to='seminar.Organizator', |                   to='seminar.Organizator', | ||||||
|                                     help_text=b'Zodpov\xc4\x9bdn\xc3\xbd\ |                   help_text=b'Zodpov\xc4\x9bdn\xc3\xbd\ | ||||||
|                                             organiz\xc3\xa1tor za obsah', |                           organiz\xc3\xa1tor za obsah', | ||||||
|                                     null=True), |                   null=True, on_delete=models.CASCADE), | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
|  | @ -14,6 +14,6 @@ class Migration(migrations.Migration): | ||||||
|         migrations.AlterField( |         migrations.AlterField( | ||||||
|             model_name='korekturovanepdf', |             model_name='korekturovanepdf', | ||||||
|             name='org', |             name='org', | ||||||
|             field=models.ForeignKey(default=None, blank=True, to='seminar.Organizator', help_text=b'Zodpov\xc4\x9bdn\xc3\xbd organiz\xc3\xa1tor za obsah', null=True), |             field=models.ForeignKey(default=None, blank=True, to='seminar.Organizator', help_text=b'Zodpov\xc4\x9bdn\xc3\xbd organiz\xc3\xa1tor za obsah', null=True, on_delete=models.CASCADE), | ||||||
|         ), |         ), | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
							
								
								
									
										77
									
								
								korektury/migrations/0016_auto_20190430_2340.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,77 @@ | ||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | # Generated by Django 1.11.20 on 2019-04-30 21:40 | ||||||
|  | from __future__ import unicode_literals | ||||||
|  | 
 | ||||||
|  | from django.db import migrations, models | ||||||
|  | import django.db.models.deletion | ||||||
|  | import django.utils.timezone | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  | 
 | ||||||
|  |     dependencies = [ | ||||||
|  |         ('korektury', '0015_auto_20161004_2005'), | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     operations = [ | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='komentar', | ||||||
|  |             name='cas', | ||||||
|  |             field=models.DateTimeField(default=django.utils.timezone.now, help_text='Čas zadání komentáře', verbose_name='čas komentáře'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='komentar', | ||||||
|  |             name='text', | ||||||
|  |             field=models.TextField(blank=True, help_text='Text komentáře', verbose_name='text komentáře'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='korekturovanepdf', | ||||||
|  |             name='cas', | ||||||
|  |             field=models.DateTimeField(default=django.utils.timezone.now, help_text='Čas vložení PDF', verbose_name='čas vložení PDF'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='korekturovanepdf', | ||||||
|  |             name='komentar', | ||||||
|  |             field=models.TextField(blank=True, help_text='Komentář ke korekturovanému PDF (např. na co se zaměřit)', verbose_name='komentář k PDF'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='korekturovanepdf', | ||||||
|  |             name='nazev', | ||||||
|  |             field=models.CharField(blank=True, help_text='Název (např. 22.1 verze 4) korekturovaného PDF', max_length=50, verbose_name='název PDF'), | ||||||
|  |         ), | ||||||
|  |         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.CASCADE, to='seminar.Organizator'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='korekturovanepdf', | ||||||
|  |             name='status', | ||||||
|  |             field=models.CharField(choices=[('pridavani', 'Přidávání korektur'), ('zanaseni', 'Korektury jsou zanášeny'), ('zastarale', 'Stará verze, nekorigovat')], default='pridavani', max_length=16, verbose_name='stav PDF'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='korekturovanepdf', | ||||||
|  |             name='stran', | ||||||
|  |             field=models.IntegerField(default=0, help_text='Počet stran PDF', verbose_name='počet stran'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='oprava', | ||||||
|  |             name='autor', | ||||||
|  |             field=models.ForeignKey(blank=True, help_text='Autor opravy', null=True, on_delete=django.db.models.deletion.CASCADE, to='seminar.Organizator'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='oprava', | ||||||
|  |             name='status', | ||||||
|  |             field=models.CharField(choices=[('k_oprave', 'K opravě'), ('opraveno', 'Opraveno'), ('neni_chyba', 'Není chyba'), ('k_zaneseni', 'K zanesení do TeXu')], default='k_oprave', max_length=16, verbose_name='stav opravy'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='oprava', | ||||||
|  |             name='strana', | ||||||
|  |             field=models.IntegerField(help_text='Strana s opravou (od 0)', verbose_name='strana s opravou'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='oprava', | ||||||
|  |             name='text', | ||||||
|  |             field=models.TextField(blank=True, help_text='Text opravy', verbose_name='text opravy'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
							
								
								
									
										36
									
								
								korektury/migrations/0017_auto_20190610_2358.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,36 @@ | ||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | # Generated by Django 1.11.21 on 2019-06-10 21:58 | ||||||
|  | from __future__ import unicode_literals | ||||||
|  | 
 | ||||||
|  | from django.db import migrations, models | ||||||
|  | import django.db.models.deletion | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  | 
 | ||||||
|  |     dependencies = [ | ||||||
|  |         ('korektury', '0016_auto_20190430_2340'), | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     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='seminar.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='seminar.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='seminar.Organizator'), | ||||||
|  |         ), | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='oprava', | ||||||
|  |             name='pdf', | ||||||
|  |             field=models.ForeignKey(default=-1, on_delete=django.db.models.deletion.PROTECT, to='korektury.KorekturovanePDF'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
|  | @ -3,8 +3,7 @@ import os | ||||||
| from django.db import models | from django.db import models | ||||||
| from django.utils import timezone | from django.utils import timezone | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.utils.encoding import python_2_unicode_compatible | from django.utils.encoding import force_text | ||||||
| from django.utils.encoding import force_unicode |  | ||||||
| from django.core.exceptions import ObjectDoesNotExist | from django.core.exceptions import ObjectDoesNotExist | ||||||
| from django.utils.text import get_valid_filename | from django.utils.text import get_valid_filename | ||||||
| 
 | 
 | ||||||
|  | @ -17,180 +16,176 @@ from unidecode import unidecode | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def generate_filename(self, filename): | def generate_filename(self, filename): | ||||||
|     clean = get_valid_filename( | 	clean = get_valid_filename( | ||||||
|         unidecode( | 		unidecode( | ||||||
|             filename.replace('/', '-').replace('\0', '').replace(":", "_") | 			filename.replace('/', '-').replace('\0', '').replace(":", "_") | ||||||
|         ) | 		) | ||||||
|     ) | 	) | ||||||
|     fname = "%s_%s" % ( | 	fname = "%s_%s" % ( | ||||||
|         timezone.now().strftime('%Y-%m-%d-%H_%M'), | 		timezone.now().strftime('%Y-%m-%d-%H_%M'), | ||||||
|         clean) | 		clean) | ||||||
|     return os.path.join(settings.KOREKTURY_PDF_DIR, fname) | 	return os.path.join(settings.KOREKTURY_PDF_DIR, fname) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #@reversion.register(ignore_duplicates=True) | #@reversion.register(ignore_duplicates=True) | ||||||
| #@python_2_unicode_compatible |  | ||||||
| class KorekturovanePDF(models.Model): | class KorekturovanePDF(models.Model): | ||||||
|     class Meta: | 	class Meta: | ||||||
|         ordering = ['-cas'] | 		ordering = ['-cas'] | ||||||
|         db_table = 'korekturovane_cislo' | 		db_table = 'korekturovane_cislo' | ||||||
|         verbose_name = u'PDF k opravám' | 		verbose_name = u'PDF k opravám' | ||||||
|         verbose_name_plural = u'PDF k opravám' | 		verbose_name_plural = u'PDF k opravám' | ||||||
| 	 | 	 | ||||||
|     #Interní ID | 	#Interní ID | ||||||
|     id  = models.AutoField(primary_key = True) | 	id = models.AutoField(primary_key = True) | ||||||
| 
 | 
 | ||||||
|     cas = models.DateTimeField(u'čas vložení PDF',default=timezone.now,help_text = 'Čas vložení PDF') | 	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 = True,max_length=50, help_text='Název (např. 22.1 verze 4) 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)') | 	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) | 	pdf = models.FileField(u'PDF', upload_to = generate_filename) | ||||||
| 
 | 
 | ||||||
|     org = models.ForeignKey(Organizator, blank=True, | 	org = models.ForeignKey(Organizator, blank=True, | ||||||
|                             help_text='Zodpovědný organizátor za obsah', | 		help_text='Zodpovědný organizátor za obsah', | ||||||
|                             null=True, | 		null=True, default=None, on_delete=models.SET_NULL) | ||||||
|                             default=None) |  | ||||||
| 
 | 
 | ||||||
|     stran = models.IntegerField(u'počet stran', help_text='Počet stran PDF', | 	stran = models.IntegerField(u'počet stran', help_text='Počet stran PDF', | ||||||
|                                 default=0) | 								default=0) | ||||||
|     STATUS_PRIDAVANI = 'pridavani' | 	STATUS_PRIDAVANI = 'pridavani' | ||||||
|     STATUS_ZANASENI = 'zanaseni' | 	STATUS_ZANASENI = 'zanaseni' | ||||||
|     STATUS_ZASTARALE = 'zastarale' | 	STATUS_ZASTARALE = 'zastarale' | ||||||
|     STATUS_CHOICES = ( | 	STATUS_CHOICES = ( | ||||||
|             (STATUS_PRIDAVANI, u'Přidávání korektur'), | 			(STATUS_PRIDAVANI, u'Přidávání korektur'), | ||||||
|             (STATUS_ZANASENI, u'Korektury jsou zanášeny'), | 			(STATUS_ZANASENI, u'Korektury jsou zanášeny'), | ||||||
|             (STATUS_ZASTARALE, u'Stará verze, nekorigovat'), | 			(STATUS_ZASTARALE, u'Stará verze, nekorigovat'), | ||||||
|             ) | 			) | ||||||
|     status = models.CharField(u'stav PDF',max_length=16, choices=STATUS_CHOICES, blank=False, | 	status = models.CharField(u'stav PDF',max_length=16, choices=STATUS_CHOICES, blank=False, | ||||||
|             default = STATUS_PRIDAVANI) | 			default = STATUS_PRIDAVANI) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     #TODO Nepovinný foreign key k číslu | 	#TODO Nepovinný foreign key k číslu | ||||||
| 
 | 
 | ||||||
|     def get_prefix(self): | 	def get_prefix(self): | ||||||
|         """Vrať řetězec, ke kterému se připojí číslo a .png""" | 		"""Vrať řetězec, ke kterému se připojí číslo a .png""" | ||||||
|         # vrátíme jméno souboru bez cesty | 		# vrátíme jméno souboru bez cesty | ||||||
|         return os.path.basename(self.pdf.file.name) | 		return os.path.basename(self.pdf.file.name) | ||||||
| 
 | 
 | ||||||
|     def convert(self): | 	def convert(self): | ||||||
|         """Vytvoří jedno png za každou stranu pdf a uloží se""" | 		"""Vytvoří jedno png za každou stranu pdf a uloží se""" | ||||||
|         dirname = os.path.join(settings.MEDIA_ROOT, settings.KOREKTURY_IMG_DIR) | 		dirname = os.path.join(settings.MEDIA_ROOT, settings.KOREKTURY_IMG_DIR) | ||||||
|         if not os.path.exists(dirname): | 		if not os.path.exists(dirname): | ||||||
|             os.mkdir(dirname) | 			os.mkdir(dirname) | ||||||
|         self.stran = 0 | 		self.stran = 0 | ||||||
|         while True: | 		while True: | ||||||
|             res = subprocess.call([ | 			res = subprocess.call([ | ||||||
|                 #Parametry inspirovány chybovou hláškou imagemagicku | 				#Parametry inspirovány chybovou hláškou imagemagicku | ||||||
|                 "gs", | 				"gs", | ||||||
|                 "-sstdout=%stderr", | 				"-sstdout=%stderr", | ||||||
|                 "-dSAFER", | 				"-dSAFER", | ||||||
|                 "-dNOPAUSE", | 				"-dNOPAUSE", | ||||||
|                 "-dBATCH", | 				"-dBATCH", | ||||||
|                 "-dNOPROMPT", | 				"-dNOPROMPT", | ||||||
|                 "-sDEVICE=pngalpha", | 				"-sDEVICE=pngalpha", | ||||||
|                 "-r180x180", | 				"-r180x180", | ||||||
|                 "-dFirstPage=%d" % (self.stran+1), | 				"-dFirstPage=%d" % (self.stran+1), | ||||||
|                 "-dLastPage=%d" % (self.stran+1), | 				"-dLastPage=%d" % (self.stran+1), | ||||||
|                 "-sOutputFile="+os.path.join( | 				"-sOutputFile="+os.path.join( | ||||||
|                     dirname, | 					dirname, | ||||||
|                     "%s-%d.png" % (self.get_prefix(), self.stran)), | 					"%s-%d.png" % (self.get_prefix(), self.stran)), | ||||||
|                 "-f%s" % (self.pdf.path) | 				"-f%s" % (self.pdf.path) | ||||||
|             ]) | 			]) | ||||||
|             if not os.path.exists(os.path.join( | 			if not os.path.exists(os.path.join( | ||||||
|                     dirname, | 					dirname, | ||||||
|                     "%s-%d.png" % (self.get_prefix(), self.stran))): | 					"%s-%d.png" % (self.get_prefix(), self.stran))): | ||||||
|                 break | 				break | ||||||
|             self.stran += 1 | 			self.stran += 1 | ||||||
|         # Změnil se počet stran, ukládáme | 		# Změnil se počet stran, ukládáme | ||||||
|         super(KorekturovanePDF, self).save() | 		super(KorekturovanePDF, self).save() | ||||||
| 
 | 
 | ||||||
|     def save(self): | 	def save(self, **kwargs): | ||||||
|         # Pokud se nezmenilo PDF, tak nepregenerovavej nahledy | 		# Pokud se nezmenilo PDF, tak nepregenerovavej nahledy | ||||||
|         try: | 		try: | ||||||
|             original = KorekturovanePDF.objects.get(pk=self.pk) | 			original = KorekturovanePDF.objects.get(pk=self.pk) | ||||||
|             if original.pdf == self.pdf: | 			if original.pdf == self.pdf: | ||||||
|                 super(KorekturovanePDF, self).save() | 				super(KorekturovanePDF, self).save() | ||||||
|                 return | 				return | ||||||
|         except ObjectDoesNotExist: | 		except ObjectDoesNotExist: | ||||||
|             pass | 			pass | ||||||
|         # uložíme nahrávané pdf | 		# uložíme nahrávané pdf | ||||||
|         super(KorekturovanePDF, self).save() | 		super(KorekturovanePDF, self).save(kwargs) | ||||||
| 
 | 
 | ||||||
|         # uložíme png a změněný počet stran | 		# uložíme png a změněný počet stran | ||||||
|         self.convert() | 		self.convert() | ||||||
| 
 | 
 | ||||||
| @reversion.register(ignore_duplicates=True) | @reversion.register(ignore_duplicates=True) | ||||||
| @python_2_unicode_compatible |  | ||||||
| class Oprava(models.Model): | class Oprava(models.Model): | ||||||
|     class Meta: | 	class Meta: | ||||||
|         db_table = 'opravy' | 		db_table = 'opravy' | ||||||
|         verbose_name = u'Oprava' | 		verbose_name = u'Oprava' | ||||||
|         verbose_name_plural = u'Opravy' | 		verbose_name_plural = u'Opravy' | ||||||
|         ordering = ['y','x'] | 		ordering = ['y','x'] | ||||||
| 	 | 	 | ||||||
|     #Interní ID | 	#Interní ID | ||||||
|     id  = models.AutoField(primary_key = True) | 	id = models.AutoField(primary_key = True) | ||||||
| 
 | 
 | ||||||
|     pdf = models.ForeignKey(KorekturovanePDF, default=-1) | 	pdf = models.ForeignKey(KorekturovanePDF, default=-1, on_delete=models.PROTECT) | ||||||
| 
 | 
 | ||||||
|     strana = models.IntegerField(u'strana s opravou', help_text='Strana s opravou (od 0)') | 	strana = models.IntegerField(u'strana s opravou', help_text='Strana s opravou (od 0)') | ||||||
| 
 | 
 | ||||||
|     x = models.IntegerField(u'x-ová souřadnice bugu') | 	x = models.IntegerField(u'x-ová souřadnice bugu') | ||||||
|     y = models.IntegerField(u'y-ová souřadnice bugu') | 	y = models.IntegerField(u'y-ová souřadnice bugu') | ||||||
| 
 | 
 | ||||||
|     STATUS_K_OPRAVE = 'k_oprave' | 	STATUS_K_OPRAVE = 'k_oprave' | ||||||
|     STATUS_OPRAVENO = 'opraveno' | 	STATUS_OPRAVENO = 'opraveno' | ||||||
|     STATUS_NENI_CHYBA = 'neni_chyba' | 	STATUS_NENI_CHYBA = 'neni_chyba' | ||||||
|     STATUS_K_ZANESENI = 'k_zaneseni' | 	STATUS_K_ZANESENI = 'k_zaneseni' | ||||||
|     STATUS_CHOICES = ( | 	STATUS_CHOICES = ( | ||||||
|             (STATUS_K_OPRAVE, u'K opravě'), | 			(STATUS_K_OPRAVE, u'K opravě'), | ||||||
|             (STATUS_OPRAVENO, u'Opraveno'), | 			(STATUS_OPRAVENO, u'Opraveno'), | ||||||
|             (STATUS_NENI_CHYBA, u'Není chyba'), | 			(STATUS_NENI_CHYBA, u'Není chyba'), | ||||||
|             (STATUS_K_ZANESENI, u'K zanesení do TeXu'), | 			(STATUS_K_ZANESENI, u'K zanesení do TeXu'), | ||||||
|             ) | 			) | ||||||
|     status = models.CharField(u'stav opravy',max_length=16, choices=STATUS_CHOICES, blank=False, | 	status = models.CharField(u'stav opravy',max_length=16, choices=STATUS_CHOICES, blank=False, | ||||||
|             default = STATUS_K_OPRAVE) | 			default = STATUS_K_OPRAVE) | ||||||
| 
 | 
 | ||||||
|     autor = models.ForeignKey(Organizator, blank = True, | 	autor = models.ForeignKey(Organizator, blank = True, | ||||||
|             help_text='Autor opravy', | 			help_text='Autor opravy', | ||||||
|             null = True) | 			null = True, on_delete=models.SET_NULL) | ||||||
| 	 | 	 | ||||||
|     text = models.TextField(u'text opravy',blank = True, help_text='Text opravy') | 	text = models.TextField(u'text opravy',blank = True, help_text='Text opravy') | ||||||
| 
 | 
 | ||||||
| #    def __init__(self,dictionary): | #	def __init__(self,dictionary): | ||||||
| #        for k,v in dictionary.items(): | #		for k,v in dictionary.items(): | ||||||
| #            setattr(self,k,v) | #			setattr(self,k,v) | ||||||
| 
 | 
 | ||||||
|     def __str__(self): | 	def __str__(self): | ||||||
|         return force_unicode(u'%s od %s: %s'%(self.status,self.autor,self.text)) | 		return '{} od {}: {}'.format(self.status,self.autor,self.text) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @reversion.register(ignore_duplicates=True) | @reversion.register(ignore_duplicates=True) | ||||||
| @python_2_unicode_compatible |  | ||||||
| class Komentar(models.Model): | class Komentar(models.Model): | ||||||
|     class Meta: | 	class Meta: | ||||||
|         db_table = 'komentare' | 		db_table = 'komentare' | ||||||
|         verbose_name = u'Komentář k opravě' | 		verbose_name = u'Komentář k opravě' | ||||||
|         verbose_name_plural = u'Komentáře k opravě' | 		verbose_name_plural = u'Komentáře k opravě' | ||||||
|         ordering = ['cas'] | 		ordering = ['cas'] | ||||||
| 	 | 	 | ||||||
|     #Interní ID | 	#Interní ID | ||||||
|     id  = models.AutoField(primary_key = True) | 	id = models.AutoField(primary_key = True) | ||||||
| 
 | 
 | ||||||
|     cas = models.DateTimeField(u'čas komentáře',default=timezone.now,help_text = 'Čas zadání komentáře') | 	cas = models.DateTimeField(u'čas komentáře',default=timezone.now,help_text = 'Čas zadání komentáře') | ||||||
| 
 | 
 | ||||||
|     oprava = models.ForeignKey(Oprava) | 	oprava = models.ForeignKey(Oprava, on_delete=models.CASCADE) | ||||||
|     autor = models.ForeignKey(Organizator, blank = True, | 	autor = models.ForeignKey(Organizator, blank = True, | ||||||
|             help_text = u'Autor komentáře', | 			help_text = u'Autor komentáře', | ||||||
|             null = True) | 			null = True, on_delete=models.SET_NULL) | ||||||
| 	 | 	 | ||||||
|     text = models.TextField(u'text komentáře',blank = True, help_text='Text komentáře') | 	text = models.TextField(u'text komentáře',blank = True, help_text='Text komentáře') | ||||||
| 
 | 
 | ||||||
|     def __str__(self): | 	def __str__(self): | ||||||
|         return force_unicode(u'%s od %s: %s'%(self.cas,self.autor,self.text)) | 		return '{} od {}: {}'.format(self.cas,self.autor,self.text) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,72 +13,46 @@ body, | ||||||
| 
 | 
 | ||||||
| img{background:white;} | img{background:white;} | ||||||
| 
 | 
 | ||||||
|  | /* Barvy korektur */ | ||||||
|  | .k_oprave {  | ||||||
|  | 	--rgb: 255, 0, 0; | ||||||
|  | } | ||||||
|  | .opraveno { | ||||||
|  | 	--rgb: 0, 0, 255; | ||||||
|  | } | ||||||
|  | .neni_chyba { | ||||||
|  | 	--rgb: 128, 128, 128; | ||||||
|  | } | ||||||
|  | .k_zaneseni { | ||||||
|  | 	--rgb: 0, 255, 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .pointer-hi,  | .pointer-hi,  | ||||||
| .pointer,  | .pointer{  | ||||||
| .pointer-wontfix,  |  | ||||||
| .pointer-wontfix-hi,  |  | ||||||
| .pointer-ready, |  | ||||||
| .pointer-ready-hi, |  | ||||||
| .pointer-done,  |  | ||||||
| .pointer-done-hi { |  | ||||||
| 	position:absolute; | 	position:absolute; | ||||||
| 	/*border-bottom-left-radius: 10px; */ | 	/*border-bottom-left-radius: 10px; */ | ||||||
| 	border-left: 2px solid yellow; | 	border-left: 2px solid yellow; | ||||||
| 	border-bottom: 2px solid yellow; | 	border-bottom: 2px solid yellow; | ||||||
| } | 	border-color: rgb(var(--rgb),var(--alpha)); | ||||||
| 
 |  | ||||||
| .pointer-done-hi,  |  | ||||||
| .pointer-wontfix-hi,  |  | ||||||
| .pointer-ready-hi, |  | ||||||
| .pointer-hi { |  | ||||||
| 	border-width: 3px; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .pointer { | .pointer { | ||||||
| 	border-color: #F00; /*IE*/ | 	border-width: 1px; | ||||||
| 	border-color: rgba(255, 0, 0, 0.35); | 	--alpha: 0.35;	 | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .pointer-hi { | .pointer-hi { | ||||||
| 	border-color: #F00; /*IE*/ | 	border-width: 3px; | ||||||
| 	border-color: rgba(255, 0, 0, 1); | 	--alpha: 1; | ||||||
| } |  | ||||||
| .pointer-done { |  | ||||||
| 	border-color: #00F; /*IE*/ |  | ||||||
| 	border-color: rgba(0, 0, 255, 0.2); |  | ||||||
| } |  | ||||||
| .pointer-done-hi { |  | ||||||
| 	border-color: #00F; /*IE*/ |  | ||||||
| 	border-color: rgba(0, 0, 255, 1); |  | ||||||
| } |  | ||||||
| .pointer-wontfix { |  | ||||||
| 	border-color: #000; /*IE*/ |  | ||||||
| 	border-color: rgba(128, 128, 128, 0.2); |  | ||||||
| } |  | ||||||
| .pointer-wontfix-hi { |  | ||||||
| 	border-color: #000; /*IE*/ |  | ||||||
| 	border-color: rgba(128, 128, 128, 1); |  | ||||||
| } |  | ||||||
| .pointer-ready { |  | ||||||
| 	border-color: #0F0; /*IE*/ |  | ||||||
| 	border-color: rgba(0, 255, 0, 0.2); |  | ||||||
| } |  | ||||||
| .pointer-ready-hi { |  | ||||||
| 	border-color: #0F0; /*IE*/ |  | ||||||
| 	border-color: rgba(0, 255, 0, 1); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| .box:hover, | 
 | ||||||
| .box-done:hover, | .box:hover{ | ||||||
| .box-ready:hover, |  | ||||||
| .box-wontfix:hover{ |  | ||||||
| 	border-width:3px; | 	border-width:3px; | ||||||
| 	margin: 0px; | 	margin: 0px; | ||||||
| } | } | ||||||
| .box, | .box { | ||||||
| .box-done, |  | ||||||
| .box-ready, |  | ||||||
| .box-wontfix { |  | ||||||
| 	margin: 1px; | 	margin: 1px; | ||||||
| 	background-color: white; | 	background-color: white; | ||||||
| 	width:300px; | 	width:300px; | ||||||
|  | @ -86,18 +60,7 @@ img{background:white;} | ||||||
| 	padding: 3px; | 	padding: 3px; | ||||||
| 	border: 2px solid black; | 	border: 2px solid black; | ||||||
| 	border-radius: 10px; | 	border-radius: 10px; | ||||||
| } | 	border-color: rgb(var(--rgb)); | ||||||
| .box { |  | ||||||
| 	border-color: red; |  | ||||||
| } |  | ||||||
| .box-done { |  | ||||||
| 	border-color: blue; |  | ||||||
| } |  | ||||||
| .box-ready { |  | ||||||
| 	border-color: rgba(0,255,0,1); |  | ||||||
| } |  | ||||||
| .box-wontfix { |  | ||||||
| 	border-color: grey; |  | ||||||
| } | } | ||||||
| form { | form { | ||||||
| 	display:inline; | 	display:inline; | ||||||
|  |  | ||||||
|  | @ -65,6 +65,12 @@ function place_comments_one_div(img_id, comments) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | function place_comments() { | ||||||
|  |     for (var i=0; i < comments.length-1; i++) { | ||||||
|  | 	    place_comments_one_div(comments[i][0], comments[i][1]) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // ctrl-enter submits form
 | // ctrl-enter submits form
 | ||||||
| function textarea_onkey(ev) | function textarea_onkey(ev) | ||||||
| { | { | ||||||
|  | @ -212,45 +218,22 @@ function show_form(img_id, dx, dy, id, text, action) { | ||||||
| 	textarea.focus(); | 	textarea.focus(); | ||||||
| 
 | 
 | ||||||
| 	return true; | 	return true; | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function box_onmouseover(box, stat) | function box_onmouseover(box) | ||||||
| { | { | ||||||
| 	var id = box.id; | 	var id = box.id; | ||||||
| 	var pointer = document.getElementById(box.id + '-pointer'); | 	var pointer = document.getElementById(box.id + '-pointer'); | ||||||
| 	switch (stat){ | 	pointer.classList.remove('pointer'); | ||||||
| 		case 'done': | 	pointer.classList.add('pointer-hi'); | ||||||
| 			pointer.className = 'pointer-done-hi'; |  | ||||||
| 			break; |  | ||||||
| 		case 'wontfix': |  | ||||||
| 			pointer.className = 'pointer-wontfix-hi'; |  | ||||||
| 			break; |  | ||||||
| 		case 'ready': |  | ||||||
| 			pointer.className = 'pointer-ready-hi'; |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			pointer.className = 'pointer-hi'; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function box_onmouseout(box, stat) | function box_onmouseout(box) | ||||||
| { | { | ||||||
| 	var id = box.id; | 	var id = box.id; | ||||||
| 	var pointer = document.getElementById(box.id + '-pointer'); | 	var pointer = document.getElementById(box.id + '-pointer'); | ||||||
| 	switch (stat){ | 	pointer.classList.remove('pointer-hi'); | ||||||
| 		case 'done': | 	pointer.classList.add('pointer'); | ||||||
| 			pointer.className = 'pointer-done'; |  | ||||||
| 			break; |  | ||||||
| 		case 'wontfix': |  | ||||||
| 			pointer.className = 'pointer-wontfix'; |  | ||||||
| 			break; |  | ||||||
| 		case 'ready': |  | ||||||
| 			pointer.className = 'pointer-ready'; |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			pointer.className = 'pointer'; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function save_scroll(form) | function save_scroll(form) | ||||||
|  | @ -261,6 +244,33 @@ function save_scroll(form) | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | function toggle_corrections(aclass) | ||||||
|  | { | ||||||
|  | 	var stylesheets = document.styleSheets; | ||||||
|  | 	var ssheet = null; | ||||||
|  | 	for (var i=0;i<stylesheets.length; i++){ | ||||||
|  | 		if (stylesheets[i].title === "opraf-css"){ | ||||||
|  | 			ssheet = stylesheets[i]; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (! ssheet){ | ||||||
|  | 		return;	 | ||||||
|  | 	} | ||||||
|  | 	for (var i=0;i<ssheet.cssRules.length;i++){ | ||||||
|  | 		var rule = ssheet.cssRules[i];	 | ||||||
|  | 		if (rule.selectorText === '.'+aclass){ | ||||||
|  | 			if (rule.style.display === ""){ | ||||||
|  | 				rule.style.display = "none"; | ||||||
|  | 			} else { | ||||||
|  | 				rule.style.display = ""; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	place_comments(); | ||||||
|  | 		 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| String.prototype.unescapeHTML = function () {                                        | String.prototype.unescapeHTML = function () {                                        | ||||||
|         return(                                                                  |         return(                                                                  | ||||||
|  |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| {% extends "base.html" %} |  | ||||||
| 
 |  | ||||||
| {% block submenu %} |  | ||||||
|   {% include "korektury/submenu.html" %} |  | ||||||
| {% endblock %} |  | ||||||
| 
 |  | ||||||
| {% block content %} |  | ||||||
| {# blok do kterého se nacita text, v pripade jinyhc templatu obalit vlastnim blokem #} |  | ||||||
| {% endblock %} |  | ||||||
| 
 |  | ||||||
| {% block title %} |  | ||||||
| {# blok pro titulek stranky #} |  | ||||||
| {% endblock %} |  | ||||||
|  | @ -1,10 +1,4 @@ | ||||||
| {% extends "korektury/base.html" %} | {% extends "base.html" %} | ||||||
| 
 |  | ||||||
| {% block submenu %} |  | ||||||
|   {% with "help" as selected %} |  | ||||||
|     {% include "korektury/submenu.html" %} |  | ||||||
|   {% endwith %} |  | ||||||
| {% endblock %} |  | ||||||
| 
 | 
 | ||||||
| {% load staticfiles %} | {% load staticfiles %} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| <html> | <html> | ||||||
| <head> | <head> | ||||||
| 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||||||
|   <link rel="stylesheet" type="text/css" media="screen, projection" href="{% static "korektury/opraf.css"%}" /> |   <link rel="stylesheet" title="opraf-css" type="text/css" media="screen, projection" href="{% static "korektury/opraf.css"%}" /> | ||||||
|   <script src="{% static "korektury/opraf.js"%}"></script> |   <script src="{% static "korektury/opraf.js"%}"></script> | ||||||
| 	<title>Korektury {{pdf.nazev}}</title> | 	<title>Korektury {{pdf.nazev}}</title> | ||||||
| </head> | </head> | ||||||
|  | @ -20,6 +20,29 @@ | ||||||
| 	          | | 	          | | ||||||
| 	<a href="/">hlavní stránka</a> | | 	<a href="/">hlavní stránka</a> | | ||||||
| 	<a href="https://mam.mff.cuni.cz/wiki">wiki</a> | | 	<a href="https://mam.mff.cuni.cz/wiki">wiki</a> | | ||||||
|  | 	<hr /> | ||||||
|  | 	Zobrazit:  | ||||||
|  | 	<input type="checkbox"  | ||||||
|  | 		id="k_oprave_checkbox"  | ||||||
|  | 		name="k_oprave_checkbox"  | ||||||
|  | 		onchange="toggle_corrections('k_oprave')" checked> | ||||||
|  | 	<label for="k_oprave_checkbox">K opravě ({{k_oprave_cnt}})</label> | ||||||
|  | 	<input type="checkbox" | ||||||
|  | 		id="opraveno_checkbox" | ||||||
|  | 		name="opraveno_checkbox"  | ||||||
|  | 		onchange="toggle_corrections('opraveno')" checked> | ||||||
|  | 	<label for="opraveno_checkbox">Opraveno ({{opraveno_cnt}})</label> | ||||||
|  | 	<input type="checkbox" | ||||||
|  | 		id="neni_chyba_checkbox" | ||||||
|  | 		name="neni_chyba_checkbox" | ||||||
|  | 		onchange="toggle_corrections('neni_chyba')" checked> | ||||||
|  | 	<label for="neni_chyba_checkbox">Není chyba ({{neni_chyba_cnt}})</label> | ||||||
|  | 	<input type="checkbox" | ||||||
|  | 		id="k_zaneseni_checkbox" | ||||||
|  | 		name="k_zaneseni_checkbox" | ||||||
|  | 		onchange="toggle_corrections('k_zaneseni')" checked> | ||||||
|  | 	<label for="k_zaneseni_checkbox">K zanesení ({{k_zaneseni_cnt}})</label> | ||||||
|  | 
 | ||||||
| 	<hr/> | 	<hr/> | ||||||
| 
 | 
 | ||||||
| 	<div id="commform-div"> | 	<div id="commform-div"> | ||||||
|  | @ -81,12 +104,12 @@ | ||||||
| 	{% for o in opravy %} | 	{% for o in opravy %} | ||||||
| 	<div onclick='img_click(this,event)' | 	<div onclick='img_click(this,event)' | ||||||
| 		id='op{{o.id}}-pointer' | 		id='op{{o.id}}-pointer' | ||||||
| 		class='pointer{%if o.status == 'opraveno' %}-done{% elif o.status == 'neni_chyba' %}-wontfix{% elif o.status == 'k_zaneseni' %}-ready{% endif %}'> | 		class='pointer {{o.status}}'> | ||||||
| 	</div> | 	</div> | ||||||
| 	<div name='op{{o.id}}' id='op{{o.id}}'  | 	<div name='op{{o.id}}' id='op{{o.id}}'  | ||||||
| 	    class='box{%if o.status == 'opraveno' %}-done{% elif o.status == 'neni_chyba' %}-wontfix{% elif o.status == 'k_zaneseni' %}-ready{% endif %}'  | 	    class='box {{o.status}}'  | ||||||
| 	    onmouseover='box_onmouseover(this,{% if o.status == 'opraveno' %}"done"{% elif o.status == 'neni_chyba' %}"wontfix"{% elif o.status == 'k_zaneseni' %}"ready"{% else %}""{% endif %})'  | 	    onmouseover='box_onmouseover(this)'  | ||||||
| 	    onmouseout='box_onmouseout(this,  {% if o.status == 'opraveno' %}"done"{% elif o.status == 'neni_chyba' %}"wontfix"{% elif o.status == 'k_zaneseni' %}"ready"{% else %}""{% endif %})'>  | 	    onmouseout='box_onmouseout(this)'>  | ||||||
| 
 | 
 | ||||||
|     	<div class='corr-header'>  |     	<div class='corr-header'>  | ||||||
| 			<span class='author' id='op{{o.id}}-autor'>{{o.autor}}</span> | 			<span class='author' id='op{{o.id}}-autor'>{{o.autor}}</span> | ||||||
|  | @ -211,11 +234,6 @@ | ||||||
| 		["img-{{s.strana}}", [{% for o in s.op_id %}["op{{o.id}}",{{o.x}},{{o.y}}],{% endfor %}[]]], | 		["img-{{s.strana}}", [{% for o in s.op_id %}["op{{o.id}}",{{o.x}},{{o.y}}],{% endfor %}[]]], | ||||||
| 	{% endfor %} | 	{% endfor %} | ||||||
| 	[]] | 	[]] | ||||||
|         function place_comments() { |  | ||||||
|             for (var i=0; i < comments.length-1; i++) { |  | ||||||
|                     place_comments_one_div(comments[i][0], comments[i][1]) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 	{% if scroll %} | 	{% if scroll %} | ||||||
| 		window.scrollTo(0,{{scroll}}); | 		window.scrollTo(0,{{scroll}}); | ||||||
| 	{% endif %} | 	{% endif %} | ||||||
|  |  | ||||||
|  | @ -1,10 +1,6 @@ | ||||||
| {% extends "korektury/base.html" %} | {% extends "base.html" %} | ||||||
| {% load staticfiles %} | {% load staticfiles %} | ||||||
| 
 | 
 | ||||||
| {% block submenu %} |  | ||||||
|   {% include "korektury/submenu.html" %} |  | ||||||
| {% endblock %} |  | ||||||
| 
 |  | ||||||
| {% block script%} | {% block script%} | ||||||
|   <link rel="stylesheet" type="text/css" media="screen, projection" href="{% static "korektury/opraf-list.css" %}" /> |   <link rel="stylesheet" type="text/css" media="screen, projection" href="{% static "korektury/opraf-list.css" %}" /> | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  | @ -21,7 +17,14 @@ | ||||||
| 
 | 
 | ||||||
| <ul> | <ul> | ||||||
|   {% for pdf in object_list  %} |   {% for pdf in object_list  %} | ||||||
| 	  <li><span {% if pdf.status == 'zanaseni'%} class="comitting-text" {% elif pdf.status == 'zastarale' %} class="deprecated-text" {% endif %}> <b>{{ pdf.nazev }}</b> <i>{{pdf.komentar}}</i> <a href="/korektury/{{pdf.id}}">{{pdf.pdf.name}}</a> </span> </li> | 	  <li><span {% if pdf.status == 'zanaseni'%} class="comitting-text" {% elif pdf.status == 'zastarale' %} class="deprecated-text" {% endif %}> | ||||||
|  | 	  	<b>{{ pdf.nazev }}</b> | ||||||
|  | 		<i>{{pdf.komentar}}</i> | ||||||
|  | 		<a href="/korektury/{{pdf.id}}">{{pdf.pdf.name}}</a> | ||||||
|  | 		(k opravě: {{pdf.k_oprave_cnt}},  | ||||||
|  | 		opraveno: {{pdf.opraveno_cnt}}, | ||||||
|  | 		není chyba: {{pdf.neni_chyba_cnt}}, | ||||||
|  | 		k zanesení: {{pdf.k_zaneseni_cnt}}) </span> </li> | ||||||
|   {% empty %} |   {% empty %} | ||||||
|     <li> Nejsou žádné dokumenty ke korekturování. |     <li> Nejsou žádné dokumenty ke korekturování. | ||||||
|   {% endfor %} |   {% endfor %} | ||||||
|  |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| {% with "/korektury" as cesta %} |  | ||||||
| 
 |  | ||||||
| <div id='submenu'> |  | ||||||
| <ul> |  | ||||||
|   <li class="{% if selected == "aktualni" %}selected{% endif %}"><a href="{{cesta}}/">Aktuální</a> |  | ||||||
|   <li class="{% if selected == "zastarale" %}selected{% endif %}"><a href="{{cesta}}/zastarale/">Zastaralé</a> |  | ||||||
|   <li class="{% if selected == "help" %}selected{% endif %}"><a href="{{cesta}}/help/">Nápověda</a> |  | ||||||
| </ul> |  | ||||||
| </div> |  | ||||||
| 
 |  | ||||||
| {% endwith %} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								korektury/testpdfs/A.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										5125
									
								
								korektury/testpdfs/B.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										69
									
								
								korektury/testutils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,69 @@ | ||||||
|  | import logging | ||||||
|  | import os | ||||||
|  | from shutil import copyfile, rmtree | ||||||
|  | 
 | ||||||
|  | from django.db import transaction | ||||||
|  | from django.conf import settings | ||||||
|  | 
 | ||||||
|  | from korektury.models import KorekturovanePDF, generate_filename | ||||||
|  | 
 | ||||||
|  | logger = logging.getLogger(__name__) | ||||||
|  | 
 | ||||||
|  | @transaction.atomic | ||||||
|  | def create_test_pdf(rnd, organizatori): | ||||||
|  | 	logger.info('Vyrábím testovací pdf ke korekturovani') | ||||||
|  | 	try: | ||||||
|  | 		testpdfs = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'testpdfs') | ||||||
|  | 
 | ||||||
|  | 		# smaže minulé pdfka a obrázky k nim a vytvoří (znovu) jejich složky | ||||||
|  | 		pdf_dir = os.path.join(settings.BASE_DIR, os.path.join('media', settings.KOREKTURY_PDF_DIR)) | ||||||
|  | 		img_dir = os.path.join(settings.BASE_DIR, os.path.join('media', settings.KOREKTURY_IMG_DIR)) | ||||||
|  | 		rmtree(pdf_dir, ignore_errors=True) | ||||||
|  | 		os.makedirs(pdf_dir) | ||||||
|  | 		rmtree(img_dir, ignore_errors=True) | ||||||
|  | 		os.makedirs(img_dir) | ||||||
|  | 
 | ||||||
|  | 		def gen_filename(filename): | ||||||
|  | 			name = generate_filename(None, filename) | ||||||
|  | 			print(name) | ||||||
|  | 			copyfile(os.path.join(testpdfs, filename), os.path.join(settings.BASE_DIR, os.path.join('media', name))) | ||||||
|  | 			return name | ||||||
|  | 
 | ||||||
|  | 		# TODO silent ghostscript (vypisuje odstavec za každou stránku…) | ||||||
|  | 
 | ||||||
|  | 		KorekturovanePDF.objects.create( | ||||||
|  | 			nazev='B', komentar='Neuronové sítě', org=rnd.choice(organizatori), pdf=gen_filename(filename='B.pdf') | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		KorekturovanePDF.objects.create( | ||||||
|  | 			nazev='A', komentar='M&M: Jak řešit?', org=rnd.choice(organizatori), pdf=gen_filename(filename='A.pdf') | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		korekturovane_pdf = KorekturovanePDF.objects.create( | ||||||
|  | 			nazev='A', komentar='M&M: Jak řešit?', org=rnd.choice(organizatori), pdf=gen_filename(filename='A.pdf'), | ||||||
|  | 			status='zanaseni' | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		KorekturovanePDF.objects.create( | ||||||
|  | 			nazev='A', komentar='M&M: Jak řešit?', org=rnd.choice(organizatori), pdf=gen_filename(filename='A.pdf'), | ||||||
|  | 			status='zastarale' | ||||||
|  | 		) | ||||||
|  | 	except (FileNotFoundError, Exception) as e: | ||||||
|  | 		# TODO najít správné chyby, které vyhazují různé systémy při neexistenci ImageMagick, nebo knihoven | ||||||
|  | 		logger.error(str(e)) | ||||||
|  | 		logger.error( | ||||||
|  | 			'Chyba vytváření testovacích korektur, pravděpodobně není nainstalován ImageMagick nebo některá z knihoven' | ||||||
|  | 			'pro práci se soubory pdf (ghostscript) nebo png (libpng?).\n' | ||||||
|  | 			''' | ||||||
|  | 				Instalaci na linux provedete např. příkazy: | ||||||
|  | 				sudo apt-get build-dep imagemagick | ||||||
|  | 				git clone https://github.com/ImageMagick/ImageMagick.git | ||||||
|  | 				cd ImageMagick/ | ||||||
|  | 				./configure | ||||||
|  | 				make | ||||||
|  | 				sudo make install | ||||||
|  | 				sudo ldconfig /usr/local/lib | ||||||
|  | 				cd .. | ||||||
|  | 				rm -r ImageMagick/ | ||||||
|  | 			''' | ||||||
|  | 		) | ||||||
|  | @ -1,13 +1,10 @@ | ||||||
| from django.conf.urls import *  # NOQA | from django.urls import path | ||||||
| from django.conf.urls import url | from seminar.utils import org_required | ||||||
| from django.contrib.auth.decorators import user_passes_test |  | ||||||
| from . import views | from . import views | ||||||
| 
 | 
 | ||||||
| staff_member_required = user_passes_test(lambda u: u.is_staff) |  | ||||||
| 
 |  | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|     url(r'^korektury/$', staff_member_required(views.KorekturyAktualniListView.as_view()), name='korektury-list'), | 	path('korektury/', org_required(views.KorekturyAktualniListView.as_view()), name='korektury_list'), | ||||||
|     url(r'^korektury/zastarale/$', staff_member_required(views.KorekturyZastaraleListView.as_view()), name='korektury-list-zastarale'), | 	path('korektury/zastarale/', org_required(views.KorekturyZastaraleListView.as_view()), name='korektury_stare_list'), | ||||||
|     url(r'^korektury/(?P<pdf>\d+)/$', staff_member_required(views.KorekturyView.as_view()), name='korektury'), | 	path('korektury/<int:pdf>/', org_required(views.KorekturyView.as_view()), name='korektury'), | ||||||
|     url(r'^korektury/help/', staff_member_required(views.KorekturyHelpView.as_view()), name='korektury-help'), | 	path('korektury/help/', org_required(views.KorekturyHelpView.as_view()), name='korektury-help'), | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ from django.utils.translation import ugettext as _ | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.http import HttpResponseForbidden | from django.http import HttpResponseForbidden | ||||||
| from django.core.mail import send_mail | from django.core.mail import send_mail | ||||||
|  | from django.db.models import Count,Q | ||||||
| 
 | 
 | ||||||
| from .models import Oprava,Komentar,KorekturovanePDF, Organizator | from .models import Oprava,Komentar,KorekturovanePDF, Organizator | ||||||
| from .forms import OpravaForm | from .forms import OpravaForm | ||||||
|  | @ -12,14 +13,21 @@ from .forms import OpravaForm | ||||||
| import subprocess | import subprocess | ||||||
| import shutil | import shutil | ||||||
| import os | import os | ||||||
| import unicodedata |  | ||||||
| 
 | 
 | ||||||
| class KorekturyHelpView(generic.TemplateView): | class KorekturyHelpView(generic.TemplateView): | ||||||
|     template_name = 'korektury/help.html' | 	template_name = 'korektury/help.html' | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class KorekturyListView(generic.ListView): | class KorekturyListView(generic.ListView): | ||||||
|     model = KorekturovanePDF | 	model = KorekturovanePDF | ||||||
|     template_name = 'korektury/seznam.html' | 	# Nefunguje, filtry se vubec nepouziji | ||||||
|  | 	queryset = KorekturovanePDF.objects.annotate( | ||||||
|  | 		k_oprave_cnt=Count('oprava',distinct=True,filter=Q(oprava__status='k_oprave')), | ||||||
|  | 		opraveno_cnt=Count('oprava',distinct=True,filter=Q(oprava__status='opraveno')), | ||||||
|  | 		neni_chyba_cnt=Count('oprava',distinct=True,filter=Q(oprava__status='neni_chyba')), | ||||||
|  | 		k_zaneseni_cnt=Count('oprava',distinct=True,filter=Q(oprava__status='k_zaneseni')), | ||||||
|  | 		) | ||||||
|  | 	template_name = 'korektury/seznam.html' | ||||||
| 
 | 
 | ||||||
| class KorekturyAktualniListView(KorekturyListView): | class KorekturyAktualniListView(KorekturyListView): | ||||||
|     def get_queryset(self, *args, **kwargs): |     def get_queryset(self, *args, **kwargs): | ||||||
|  | @ -45,178 +53,185 @@ class KorekturyZastaraleListView(KorekturyListView): | ||||||
| 
 | 
 | ||||||
| ### Korektury | ### Korektury | ||||||
| class KorekturyView(generic.TemplateView): | class KorekturyView(generic.TemplateView): | ||||||
|     model = Oprava | 	model = Oprava | ||||||
|     template_name = 'korektury/opraf.html' | 	template_name = 'korektury/opraf.html' | ||||||
|     form_class = OpravaForm | 	form_class = OpravaForm | ||||||
| 
 | 
 | ||||||
|     def post(self, request, *args, **kwargs): | 	def post(self, request, *args, **kwargs): | ||||||
|         form = self.form_class(request.POST) | 		form = self.form_class(request.POST) | ||||||
|         q = request.POST | 		q = request.POST | ||||||
|         scroll = q.get('scroll') | 		scroll = q.get('scroll') | ||||||
| 
 | 
 | ||||||
|         # prirazeni autora podle prihlaseni | 		# prirazeni autora podle prihlaseni | ||||||
|         autor_user = request.user | 		autor_user = request.user | ||||||
|         # pokud existuje ucet (user), ale neni to organizator = 403 | 		# pokud existuje ucet (user), ale neni to organizator = 403 | ||||||
|         autor = Organizator.objects.filter(user=autor_user).first() | 		autor = Organizator.objects.filter(osoba__user=autor_user).first() | ||||||
|         if not autor: | 		if not autor: | ||||||
|             return HttpResponseForbidden() | 			return HttpResponseForbidden() | ||||||
| 
 | 
 | ||||||
|         if not scroll: | 		if not scroll: | ||||||
|             scroll = 0 | 			scroll = 0 | ||||||
| 
 | 
 | ||||||
|         action = q.get('action') | 		action = q.get('action') | ||||||
|         if (action == u''):  # Přidej | 		if (action == ''):  # Přidej | ||||||
|             x = int(q.get('x')) | 			x = int(q.get('x')) | ||||||
|             y = int(q.get('y')) | 			y = int(q.get('y')) | ||||||
|             text = q.get('txt') | 			text = q.get('txt') | ||||||
|             strana = int(q.get('img-id')[4:]) | 			strana = int(q.get('img-id')[4:]) | ||||||
|             pdf = KorekturovanePDF.objects.get(id=q.get('pdf')) | 			pdf = KorekturovanePDF.objects.get(id=q.get('pdf')) | ||||||
| 
 | 
 | ||||||
|             op = Oprava(x=x,y=y, autor=autor, text=text, strana=strana,pdf = pdf) | 			op = Oprava(x=x,y=y, autor=autor, text=text, strana=strana,pdf = pdf) | ||||||
|             op.save() | 			op.save() | ||||||
|             self.send_email_notification_komentar(op, autor, text) | 			self.send_email_notification_komentar(op, autor, text) | ||||||
|         elif (action == u'del'): | 		elif (action == 'del'): | ||||||
|             id = int(q.get('id')) | 			id = int(q.get('id')) | ||||||
|             op = Oprava.objects.get(id=id) | 			op = Oprava.objects.get(id=id) | ||||||
|             op.delete() | 			op.delete() | ||||||
|         elif (action == u'update'): | 		elif (action == 'update'): | ||||||
|             id = int(q.get('id')) | 			id = int(q.get('id')) | ||||||
|             op = Oprava.objects.get(id=id) | 			op = Oprava.objects.get(id=id) | ||||||
|             text = q.get('txt') | 			text = q.get('txt') | ||||||
|             op.autor = autor | 			op.autor = autor | ||||||
|             op.text = text | 			op.text = text | ||||||
|             op.save() | 			op.save() | ||||||
|         elif (action == u'undone'): | 		elif (action == 'undone'): | ||||||
|             id = int(q.get('id')) | 			id = int(q.get('id')) | ||||||
|             op = Oprava.objects.get(id=id) | 			op = Oprava.objects.get(id=id) | ||||||
|             op.status = op.STATUS_K_OPRAVE | 			op.status = op.STATUS_K_OPRAVE | ||||||
|             op.save() | 			op.save() | ||||||
|         elif (action == u'done'): | 		elif (action == 'done'): | ||||||
|             id = int(q.get('id')) | 			id = int(q.get('id')) | ||||||
|             op = Oprava.objects.get(id=id) | 			op = Oprava.objects.get(id=id) | ||||||
|             op.status = op.STATUS_OPRAVENO | 			op.status = op.STATUS_OPRAVENO | ||||||
|             op.save() | 			op.save() | ||||||
| 	elif (action == u'ready'): | 		elif (action == 'ready'): | ||||||
| 	    id = int(q.get('id')) | 			id = int(q.get('id')) | ||||||
| 	    op = Oprava.objects.get(id=id) | 			op = Oprava.objects.get(id=id) | ||||||
| 	    op.status = op.STATUS_K_ZANESENI | 			op.status = op.STATUS_K_ZANESENI | ||||||
| 	    op.save() | 			op.save() | ||||||
|         elif (action == u'wontfix'): | 		elif (action == 'wontfix'): | ||||||
|             id = int(q.get('id')) | 			id = int(q.get('id')) | ||||||
|             op = Oprava.objects.get(id=id) | 			op = Oprava.objects.get(id=id) | ||||||
|             op.status = op.STATUS_NENI_CHYBA | 			op.status = op.STATUS_NENI_CHYBA | ||||||
|             op.save() | 			op.save() | ||||||
|         elif (action == u'comment'): | 		elif (action == 'comment'): | ||||||
|             id = int(q.get('id')) | 			id = int(q.get('id')) | ||||||
|             op = Oprava.objects.get(id=id) | 			op = Oprava.objects.get(id=id) | ||||||
|             text = q.get('txt') | 			text = q.get('txt') | ||||||
|             kom = Komentar(oprava=op,autor=autor,text=text) | 			kom = Komentar(oprava=op,autor=autor,text=text) | ||||||
|             kom.save() | 			kom.save() | ||||||
|             self.send_email_notification_komentar(op, autor, text) | 			self.send_email_notification_komentar(op, autor, text) | ||||||
|         elif (action == u'update-comment'): | 		elif (action == 'update-comment'): | ||||||
|             id = int(q.get('id')) | 			id = int(q.get('id')) | ||||||
|             kom = Komentar.objects.get(id=id) | 			kom = Komentar.objects.get(id=id) | ||||||
|             text = q.get('txt') | 			text = q.get('txt') | ||||||
|             kom.text = text | 			kom.text = text | ||||||
|             kom.autor = autor | 			kom.autor = autor | ||||||
|             kom.save() | 			kom.save() | ||||||
|         elif (action == u'del-comment'): | 		elif (action == 'del-comment'): | ||||||
|             id = int(q.get('id')) | 			id = int(q.get('id')) | ||||||
|             kom = Komentar.objects.get(id=id) | 			kom = Komentar.objects.get(id=id) | ||||||
|             kom.delete() | 			kom.delete() | ||||||
|         elif (action == u'set-state'): | 		elif (action == 'set-state'): | ||||||
|             pdf = KorekturovanePDF.objects.get(id=q.get('pdf')) | 			pdf = KorekturovanePDF.objects.get(id=q.get('pdf')) | ||||||
|             if (q.get('state') == u'adding'): | 			if (q.get('state') == 'adding'): | ||||||
|                 pdf.status = pdf.STATUS_PRIDAVANI | 				pdf.status = pdf.STATUS_PRIDAVANI | ||||||
|             elif (q.get('state') == u'comitting'): | 			elif (q.get('state') == 'comitting'): | ||||||
|                 pdf.status = pdf.STATUS_ZANASENI | 				pdf.status = pdf.STATUS_ZANASENI | ||||||
|             elif (q.get('state') == u'deprecated'): | 			elif (q.get('state') == 'deprecated'): | ||||||
|                 pdf.status = pdf.STATUS_ZASTARALE | 				pdf.status = pdf.STATUS_ZASTARALE | ||||||
|             pdf.save() | 			pdf.save() | ||||||
|         context = self.get_context_data() | 		context = self.get_context_data() | ||||||
|         context['scroll'] = scroll | 		context['scroll'] = scroll | ||||||
|         context['autor'] = autor | 		context['autor'] = autor | ||||||
|         return render(request, 'korektury/opraf.html',context) | 		return render(request, 'korektury/opraf.html',context) | ||||||
| 
 | 
 | ||||||
|     def send_email_notification_komentar(self, oprava, autor, text): | 	def send_email_notification_komentar(self, oprava, autor, text): | ||||||
|         ''' Rozesle e-mail pri pridani komentare, | 		''' Rozesle e-mail pri pridani komentare, | ||||||
|             ktery obsahuje text komentare. | 			ktery obsahuje text komentare. | ||||||
|         ''' | 		''' | ||||||
| 
 | 
 | ||||||
|         # parametry e-mailu | 		# parametry e-mailu | ||||||
|         odkaz = "https://mam.mff.cuni.cz/korektury/{}/".format(oprava.pdf.pk) | 		#odkaz = "https://mam.mff.cuni.cz/korektury/{}/".format(oprava.pdf.pk) | ||||||
|         from_email = 'korekturovatko@mam.mff.cuni.cz' | 		from django.urls import reverse | ||||||
|         subject = u'Nová korektura od {} v {}'.format(autor, | 		odkaz = self.request.build_absolute_uri(reverse('korektury', kwargs={'pdf': oprava.pdf.pk})) | ||||||
|                                                      oprava.pdf.nazev) | 		from_email = 'korekturovatko@mam.mff.cuni.cz' | ||||||
|         text = u"Text komentáře:\n\n{}\n\n=== Konec textu komentáře ===\n\ | 		subject = 'Nová korektura od {} v {}'.format(autor, | ||||||
|                 \nodkaz do korekturovátka: {}\n\ | 													 oprava.pdf.nazev) | ||||||
|                 \nVaše korekturovátko\n".format(text, odkaz) | 		text = u"Text komentáře:\n\n{}\n\n=== Konec textu komentáře ===\n\ | ||||||
|  | 				\nodkaz do korekturovátka: {}\n\ | ||||||
|  | 				\nVaše korekturovátko\n".format(text, odkaz) | ||||||
| 
 | 
 | ||||||
|         # Prijemci e-mailu | 		# Prijemci e-mailu | ||||||
|         emails = set() | 		emails = set() | ||||||
|         # e-mail autora korektury | 		# e-mail autora korektury | ||||||
|         email = oprava.autor.user.email | 		email = oprava.autor.osoba.email | ||||||
|         if email: | 		if email: | ||||||
|             emails.add(email) | 			emails.add(email) | ||||||
| 
 | 
 | ||||||
|         # nalezeni e-mailu na autory komentaru | 		# nalezeni e-mailu na autory komentaru | ||||||
|         for komentar in oprava.komentar_set.all(): | 		for komentar in oprava.komentar_set.all(): | ||||||
|             email_komentujiciho = komentar.autor.user.email | 			email_komentujiciho = komentar.autor.osoba.email | ||||||
|             if email_komentujiciho: | 			if email_komentujiciho: | ||||||
|                 emails.add(email_komentujiciho) | 				emails.add(email_komentujiciho) | ||||||
| 
 | 
 | ||||||
|         # zodpovedny org | 		# zodpovedny org | ||||||
|         if oprava.pdf.org: | 		if oprava.pdf.org: | ||||||
|             email_zobpovedny = oprava.pdf.org.user.email | 			email_zobpovedny = oprava.pdf.org.osoba.email | ||||||
|             if email_zobpovedny: | 			if email_zobpovedny: | ||||||
|                 emails.add(email_zobpovedny) | 				emails.add(email_zobpovedny) | ||||||
| 
 | 
 | ||||||
|         # odstran e-mail autora opravy | 		# odstran e-mail autora opravy | ||||||
|         email = autor.user.email | 		email = autor.osoba.email | ||||||
|         if email: | 		if email: | ||||||
|             emails.discard(email) | 			emails.discard(email) | ||||||
| 
 | 
 | ||||||
|         if not settings.SEND_EMAIL_NOTIFICATIONS: | 		if not settings.POSLI_MAILOVOU_NOTIFIKACI: | ||||||
|             print "Poslal bych upozornění na tyto adresy: ", " ".join(emails) | 			print("Poslal bych upozornění na tyto adresy: ", " ".join(emails)) | ||||||
|             return | 			return | ||||||
| 
 | 
 | ||||||
|         send_mail(subject, text, from_email, list(emails)) | 		send_mail(subject, text, from_email, list(emails)) | ||||||
| 
 | 
 | ||||||
|     def get_context_data(self, **kwargs): | 	def get_context_data(self, **kwargs): | ||||||
|         context = super(KorekturyView,self).get_context_data(**kwargs) | 		context = super(KorekturyView,self).get_context_data(**kwargs) | ||||||
|         pdf = get_object_or_404(KorekturovanePDF, id=self.kwargs['pdf']) | 		pdf = get_object_or_404(KorekturovanePDF, id=self.kwargs['pdf']) | ||||||
|         context['pdf'] = pdf | 		context['pdf'] = pdf | ||||||
|         context['img_prefix'] = pdf.get_prefix() | 		context['img_prefix'] = pdf.get_prefix() | ||||||
|         context['img_path'] = settings.KOREKTURY_IMG_DIR | 		context['img_path'] = settings.KOREKTURY_IMG_DIR | ||||||
|         context['img_indexes'] = range(pdf.stran)  | 		context['img_indexes'] = range(pdf.stran)  | ||||||
|         context['form_oprava'] = OpravaForm() | 		context['form_oprava'] = OpravaForm() | ||||||
|         opravy = Oprava.objects.filter(pdf=self.kwargs['pdf']) | 		opravy = Oprava.objects.filter(pdf=self.kwargs['pdf']) | ||||||
|         zasluhy = {} | 		zasluhy = {} | ||||||
|         for o in opravy: | 		for o in opravy: | ||||||
|             if o.autor in zasluhy: | 			if o.autor in zasluhy: | ||||||
|                 zasluhy[o.autor]+=1 | 				zasluhy[o.autor]+=1 | ||||||
|             else: | 			else: | ||||||
|                 zasluhy[o.autor]=1 | 				zasluhy[o.autor]=1 | ||||||
|             o.komentare = o.komentar_set.all() | 			o.komentare = o.komentar_set.all() | ||||||
|             for k in o.komentare: | 			for k in o.komentare: | ||||||
|                 if k.autor in zasluhy: | 				if k.autor in zasluhy: | ||||||
|                     zasluhy[k.autor] += 1 | 					zasluhy[k.autor] += 1 | ||||||
|                 else: | 				else: | ||||||
|                     zasluhy[k.autor] = 1 | 					zasluhy[k.autor] = 1 | ||||||
|         zasluhy = [ | 		zasluhy = [ | ||||||
|             {'autor': jmeno, 'pocet': pocet} | 			{'autor': jmeno, 'pocet': pocet} | ||||||
|             for (jmeno, pocet) in zasluhy.items() | 			for (jmeno, pocet) in zasluhy.items() | ||||||
|         ] | 		] | ||||||
|         zasluhy.sort(key=lambda z: z['pocet'], reverse=True) | 		zasluhy.sort(key=lambda z: z['pocet'], reverse=True) | ||||||
| 
 | 
 | ||||||
|         strany = set(o.strana for o in opravy) | 		strany = set(o.strana for o in opravy) | ||||||
|         opravy_na_stranu = [{'strana': s, 'op_id': opravy.filter(strana=s)} for s in strany] | 		opravy_na_stranu = [{'strana': s, 'op_id': opravy.filter(strana=s)} for s in strany] | ||||||
|         context['opravy_strany'] = opravy_na_stranu | 		context['opravy_strany'] = opravy_na_stranu | ||||||
| 
 | 
 | ||||||
|         context['opravy'] = opravy | 		context['k_oprave_cnt'] = opravy.filter(status='k_oprave').count()  | ||||||
|         context['zasluhy'] = zasluhy | 		context['opraveno_cnt'] = opravy.filter(status='opraveno').count()  | ||||||
|         return context | 		context['neni_chyba_cnt'] = opravy.filter(status='neni_chyba').count()  | ||||||
|  | 		context['k_zaneseni_cnt'] = opravy.filter(status='k_zaneseni').count()  | ||||||
| 		 | 		 | ||||||
|     def form_valid(self,form): | 		context['opravy'] = opravy | ||||||
|         return super(KorekturyView,self).form_valid(form) | 		context['zasluhy'] = zasluhy | ||||||
|  | 		return context | ||||||
|  | 
 | ||||||
|  | 	def form_valid(self,form): | ||||||
|  | 		return super(KorekturyView,self).form_valid(form) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ from django.contrib.flatpages.admin import FlatpageForm as FlatpageFormOld | ||||||
| from django import forms | from django import forms | ||||||
| from ckeditor_uploader.widgets import CKEditorUploadingWidget | from ckeditor_uploader.widgets import CKEditorUploadingWidget | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class FlatpageForm(FlatpageFormOld): | class FlatpageForm(FlatpageFormOld): | ||||||
|     content = forms.CharField(widget=CKEditorUploadingWidget()) |     content = forms.CharField(widget=CKEditorUploadingWidget()) | ||||||
|     class Meta: |     class Meta: | ||||||
|  | @ -22,3 +23,4 @@ class FlatPageAdmin(FlatPageAdminOld): | ||||||
| # We have to unregister the normal admin, and then reregister ours | # We have to unregister the normal admin, and then reregister ours | ||||||
| admin.site.unregister(FlatPage) | admin.site.unregister(FlatPage) | ||||||
| admin.site.register(FlatPage, FlatPageAdmin) | admin.site.register(FlatPage, FlatPageAdmin) | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -1,27 +0,0 @@ | ||||||
| 
 |  | ||||||
| from datetime import datetime, date |  | ||||||
| 
 |  | ||||||
| def vzhled(request): |  | ||||||
|     ''' Podle casu prida do templatu, zdali je nebo neni noc ''' |  | ||||||
|     hodin = datetime.now().hour |  | ||||||
|     if (hodin <= 6) or (hodin >= 20): |  | ||||||
|         noc = True |  | ||||||
|     else: |  | ||||||
|         noc = False |  | ||||||
|     return {'noc' : noc} |  | ||||||
| 
 |  | ||||||
| def april(req): |  | ||||||
|     if 'HTTP_X_APRIL' in req.META: |  | ||||||
|         try: |  | ||||||
|             year = int(req.META['HTTP_X_APRIL']) |  | ||||||
|             return {'april': year} |  | ||||||
|         except: |  | ||||||
|             pass # Fall-back to regular behaviour |  | ||||||
| 
 |  | ||||||
|     import datetime |  | ||||||
|     today = datetime.date.today() |  | ||||||
|     if today.day == 1 and today.month == 4: |  | ||||||
|         return {'april': today.year} |  | ||||||
|     return {} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
							
								
								
									
										15
									
								
								mamweb/routers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,15 @@ | ||||||
|  | from rest_framework import routers | ||||||
|  | from seminar import viewsets as vs | ||||||
|  | 
 | ||||||
|  | router = routers.DefaultRouter() | ||||||
|  | 
 | ||||||
|  | router.register(r'ulohavzoraknode', vs.UlohaVzorakNodeViewSet,basename='ulohavzoraknode') | ||||||
|  | router.register(r'reseninode', vs.ReseniNodeViewSet,basename='reseninode') | ||||||
|  | router.register(r'text', vs.TextViewSet) | ||||||
|  | router.register(r'textnode', vs.TextNodeViewSet) | ||||||
|  | router.register(r'castnode', vs.CastNodeViewSet) | ||||||
|  | router.register(r'problem', vs.ProblemViewSet, basename='problem') | ||||||
|  | router.register(r'uloha', vs.UlohaViewSet, basename='uloha') | ||||||
|  | router.register(r'reseni', vs.ReseniViewSet, basename='reseni') | ||||||
|  | router.register(r'ulohazadaninode', vs.UlohaZadaniNodeViewSet) | ||||||
|  | 
 | ||||||
|  | @ -43,7 +43,8 @@ STATICFILES_FINDERS = ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| # Where redirect for login required services | # Where redirect for login required services | ||||||
| LOGIN_URL = '/admin/login' | LOGIN_URL = 'login' | ||||||
|  | LOGIN_REDIRECT_URL = 'profil' | ||||||
| 
 | 
 | ||||||
| # Modules configuration | # Modules configuration | ||||||
| 
 | 
 | ||||||
|  | @ -52,14 +53,15 @@ AUTHENTICATION_BACKENDS = ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| MIDDLEWARE_CLASSES = ( | MIDDLEWARE = ( | ||||||
|     'reversion.middleware.RevisionMiddleware', | #    'reversion.middleware.RevisionMiddleware', | ||||||
|     'django.contrib.sessions.middleware.SessionMiddleware', |     'django.contrib.sessions.middleware.SessionMiddleware', | ||||||
|     'django.middleware.common.CommonMiddleware', |     'django.middleware.common.CommonMiddleware', | ||||||
|     'django.middleware.csrf.CsrfViewMiddleware', |     'django.middleware.csrf.CsrfViewMiddleware', | ||||||
|     'mamweb.middleware.LoggedInHintCookieMiddleware', | #	FIXME: rozbilo se při přechodu na Django 2.0, nevím, jestli  | ||||||
|  | #	se to dá zahodit bez náhrady | ||||||
|  | #    'mamweb.middleware.LoggedInHintCookieMiddleware', | ||||||
|     'django.contrib.auth.middleware.AuthenticationMiddleware', |     'django.contrib.auth.middleware.AuthenticationMiddleware', | ||||||
|     'django.contrib.auth.middleware.SessionAuthenticationMiddleware', |  | ||||||
|     'django.contrib.messages.middleware.MessageMiddleware', |     'django.contrib.messages.middleware.MessageMiddleware', | ||||||
|     'django.middleware.clickjacking.XFrameOptionsMiddleware', |     'django.middleware.clickjacking.XFrameOptionsMiddleware', | ||||||
|     'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware', |     'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware', | ||||||
|  | @ -73,10 +75,11 @@ TEMPLATES = [ | ||||||
|         'OPTIONS': { |         'OPTIONS': { | ||||||
|             'context_processors': ( |             'context_processors': ( | ||||||
|                 'django.contrib.auth.context_processors.auth', |                 'django.contrib.auth.context_processors.auth', | ||||||
|  | 		'django.template.context_processors.request', | ||||||
|                 'django.contrib.messages.context_processors.messages', |                 'django.contrib.messages.context_processors.messages', | ||||||
|                 'sekizai.context_processors.sekizai', |                 'sekizai.context_processors.sekizai', | ||||||
|                 'mamweb.context_processors.vzhled', |                 'header_fotky.context_processors.vzhled', | ||||||
|                 'mamweb.context_processors.april', |                 'various.context_processors.april', | ||||||
|             ) |             ) | ||||||
|         }, |         }, | ||||||
|     }, |     }, | ||||||
|  | @ -103,7 +106,8 @@ INSTALLED_APPS = ( | ||||||
|     'ckeditor', |     'ckeditor', | ||||||
|     'ckeditor_uploader', |     'ckeditor_uploader', | ||||||
|     'taggit', |     'taggit', | ||||||
|     'autocomplete_light', |     'dal', | ||||||
|  |     'dal_select2', | ||||||
| 
 | 
 | ||||||
|     'fluent_comments', |     'fluent_comments', | ||||||
|     'crispy_forms', |     'crispy_forms', | ||||||
|  | @ -113,14 +117,24 @@ INSTALLED_APPS = ( | ||||||
|     'django.contrib.flatpages', |     'django.contrib.flatpages', | ||||||
|     'django.contrib.humanize', |     'django.contrib.humanize', | ||||||
| 
 | 
 | ||||||
|  |     'sitetree', | ||||||
|  | 
 | ||||||
|     'imagekit', |     'imagekit', | ||||||
| 
 | 
 | ||||||
|  |     'polymorphic', | ||||||
|  |      | ||||||
|  |     'webpack_loader', | ||||||
|  |     'rest_framework', | ||||||
|  |     'rest_framework.authtoken', | ||||||
|  | 
 | ||||||
|     # MaMweb |     # MaMweb | ||||||
|     'mamweb', |     'mamweb', | ||||||
|     'seminar', |     'seminar', | ||||||
|     'galerie', |     'galerie', | ||||||
|     'korektury', |     'korektury', | ||||||
|     'prednasky', |     'prednasky', | ||||||
|  |     'header_fotky', | ||||||
|  |     'various', | ||||||
| 
 | 
 | ||||||
|     # Admin upravy: |     # Admin upravy: | ||||||
| 
 | 
 | ||||||
|  | @ -177,6 +191,27 @@ CKEDITOR_CONFIGS = { | ||||||
|     }, |     }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | # Webpack loader | ||||||
|  | VUE_FRONTEND_DIR = os.path.join(BASE_DIR, 'vue_frontend') | ||||||
|  | 
 | ||||||
|  | WEBPACK_LOADER = { | ||||||
|  |     'DEFAULT': { | ||||||
|  |         'CACHE': False, | ||||||
|  |         'BUNDLE_DIR_NAME': 'vue/',  # must end with slash | ||||||
|  |         'STATS_FILE': os.path.join(VUE_FRONTEND_DIR, 'webpack-stats.json'), | ||||||
|  |         'POLL_INTERVAL': 0.1, | ||||||
|  |         'TIMEOUT': None, | ||||||
|  |         'IGNORE': [r'.+\.hot-update.js', r'.+\.map'] | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Dajngo REST Framework | ||||||
|  | 
 | ||||||
|  | REST_FRAMEWORK = { | ||||||
|  |     'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', | ||||||
|  |     'PAGE_SIZE': 100 | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| # Comments | # Comments | ||||||
| 
 | 
 | ||||||
|  | @ -212,6 +247,14 @@ LOGGING = { | ||||||
|                 'handlers': ['console'], |                 'handlers': ['console'], | ||||||
|                 'level': 'DEBUG', |                 'level': 'DEBUG', | ||||||
|                 }, |                 }, | ||||||
|  |             'seminar.prihlaska.form':{ | ||||||
|  | 		'handlers': ['console','registration_logfile'], | ||||||
|  | 		'level': 'INFO' | ||||||
|  | 		}, | ||||||
|  |             'seminar.prihlaska.problem':{ | ||||||
|  | 		'handlers': ['console','mail_registration','registration_error_log'], | ||||||
|  | 		'level': 'INFO' | ||||||
|  | 		}, | ||||||
| 
 | 
 | ||||||
|             # Catch-all logger |             # Catch-all logger | ||||||
|             '': { |             '': { | ||||||
|  | @ -230,10 +273,28 @@ LOGGING = { | ||||||
|                 }, |                 }, | ||||||
| 
 | 
 | ||||||
|             'mail_admins': { |             'mail_admins': { | ||||||
|                 'level': 'ERROR', |                 'level': 'WARNING', | ||||||
|                 'class': 'django.utils.log.AdminEmailHandler', |                 'class': 'django.utils.log.AdminEmailHandler', | ||||||
|                 'formatter': 'verbose',  |                 'formatter': 'verbose',  | ||||||
|                 }, |                 }, | ||||||
|  |             'mail_registration': { | ||||||
|  |                 'level': 'WARNING', | ||||||
|  |                 'class': 'django.utils.log.AdminEmailHandler', | ||||||
|  |                 'formatter': 'verbose',  | ||||||
|  |                 }, | ||||||
|  |             'registration_logfile':{ | ||||||
|  |                 'level': 'INFO', | ||||||
|  | 		'class': 'logging.FileHandler', | ||||||
|  | 		# filename declared in specific configuration files | ||||||
|  |                 'formatter': 'verbose',  | ||||||
|  | 		}, | ||||||
|  | 	    'registration_error_log':{ | ||||||
|  |                 'level': 'INFO', | ||||||
|  | 		'class': 'logging.FileHandler', | ||||||
|  | 		# filename declared in specific configuration files | ||||||
|  |                 'formatter': 'verbose',  | ||||||
|  | 		}, | ||||||
|  | 		 | ||||||
|             }, |             }, | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -250,4 +311,4 @@ CISLO_IMG_DIR = os.path.join('cislo', 'img') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # E-MAIL NOTIFICATIONS | # E-MAIL NOTIFICATIONS | ||||||
| SEND_EMAIL_NOTIFICATIONS = False | POSLI_MAILOVOU_NOTIFIKACI = False | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								mamweb/settings_debug.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,13 @@ | ||||||
|  | # Debugovaci nastaveni settings.py | ||||||
|  | # Pro vyber tohoto nastaveni muzete pouzit tez: | ||||||
|  | # DJANGO_SETTINGS_MODULE=mamweb.settings_debug ./manage.py ... | ||||||
|  | 
 | ||||||
|  | # Import local settings | ||||||
|  | from .settings_local import * | ||||||
|  | 
 | ||||||
|  | # Vypisovani databazovych dotazu do konzole | ||||||
|  | LOGGING['loggers']['django.db.backends'] = { | ||||||
|  | 	'level': 'DEBUG', | ||||||
|  | 	'handlers': ['console'], | ||||||
|  | 	'propagate': False, | ||||||
|  | } | ||||||
|  | @ -10,7 +10,7 @@ import os.path | ||||||
| # Import common settings | # Import common settings | ||||||
| from .settings_common import * | from .settings_common import * | ||||||
| 
 | 
 | ||||||
| MIDDLEWARE_CLASSES += ( | MIDDLEWARE += ( | ||||||
|     'debug_toolbar.middleware.DebugToolbarMiddleware', |     'debug_toolbar.middleware.DebugToolbarMiddleware', | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|  | @ -24,10 +24,11 @@ INSTALLED_APPS += ( | ||||||
| 
 | 
 | ||||||
| # SECURITY WARNING: don't run with debug turned on in production! | # SECURITY WARNING: don't run with debug turned on in production! | ||||||
| DEBUG = True | DEBUG = True | ||||||
|  | INTERNAL_IPS = ['127.0.0.1'] | ||||||
| 
 | 
 | ||||||
| TEMPLATES[0]['OPTIONS']['debug'] = True | TEMPLATES[0]['OPTIONS']['debug'] = True | ||||||
| 
 | 
 | ||||||
| ALLOWED_HOSTS = ['127.0.0.1'] | ALLOWED_HOSTS = ['127.0.0.1', '192.168.43.34'] | ||||||
| 
 | 
 | ||||||
| # Database | # Database | ||||||
| # https://docs.djangoproject.com/en/1.7/ref/settings/#databases | # https://docs.djangoproject.com/en/1.7/ref/settings/#databases | ||||||
|  | @ -47,7 +48,52 @@ DATABASES = { | ||||||
| #} | #} | ||||||
| 
 | 
 | ||||||
| # LOGGING | # LOGGING | ||||||
|  | LOGGING = { | ||||||
|  |     'version': 1, | ||||||
|  |     'disable_existing_loggers': True, | ||||||
|  |     'filters': { | ||||||
|  |         'require_debug_false': { | ||||||
|  |             '()': 'django.utils.log.RequireDebugFalse' | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     'formatters': { | ||||||
|  |         'simple': { | ||||||
|  |             'format': '%(asctime)s - %(name)s - %(levelname)-8s - %(message)s', | ||||||
|  |         }, | ||||||
|  |     }, | ||||||
|  |     'handlers': { | ||||||
|  |         'dummy': { | ||||||
|  |             'class': 'logging.NullHandler', | ||||||
|  |         }, | ||||||
|  |         'console': { | ||||||
|  |             'level': 'DEBUG', | ||||||
|  |             'class': 'logging.StreamHandler', | ||||||
|  |             'formatter': 'simple', | ||||||
|  |         }, | ||||||
|  |     }, | ||||||
|  |     'loggers': { | ||||||
|  | 	 # Vypisovani databazovych dotazu do konzole | ||||||
|  |          #'django.db.backends': { | ||||||
|  |          #    'level': 'DEBUG', | ||||||
|  |          #    'handlers': ['console'], | ||||||
|  |          #    'propagate': False, | ||||||
|  |          #}, | ||||||
|  |         'werkzeug': { | ||||||
|  |         	'handlers': ['console'], | ||||||
|  |         	'level': 'DEBUG', | ||||||
|  |         	'propagate': True, | ||||||
|  |         }, | ||||||
|  |         '': { | ||||||
|  |             'handlers': ['console'], | ||||||
|  |             'level': 'DEBUG', | ||||||
|  |             'propagate': False, | ||||||
|  |         }, | ||||||
|  |     }, | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| # set to 'DEBUG' for EXTRA verbose output | # set to 'DEBUG' for EXTRA verbose output | ||||||
| LOGGING['handlers']['console']['level'] = 'INFO' | # LOGGING['handlers']['console']['level'] = 'INFO' | ||||||
| 
 | 
 | ||||||
|  | # E-maily posílat chceme, ale do terminálu :-) | ||||||
|  | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' | ||||||
|  | SEND_EMAIL_NOTIFICATIONS = True | ||||||
|  |  | ||||||
|  | @ -61,7 +61,9 @@ CSRF_COOKIE_SECURE = True | ||||||
| 
 | 
 | ||||||
| LOGGING['loggers']['']['handlers'] = ['console', 'mail_admins'] | LOGGING['loggers']['']['handlers'] = ['console', 'mail_admins'] | ||||||
| LOGGING['loggers']['django']['handlers'] = ['console', 'mail_admins'] | LOGGING['loggers']['django']['handlers'] = ['console', 'mail_admins'] | ||||||
|  | LOGGING['handlers']['registration_logfile']['filename'] = '/home/mam-web/logs/prod/registration.log' | ||||||
|  | LOGGING['handlers']['registration_error_log']['filename'] = '/home/mam-web/logs/prod/registration_errors.log' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # E-MAIL NOTIFICATIONS | # E-MAIL NOTIFICATIONS | ||||||
| SEND_EMAIL_NOTIFICATIONS = True | POSLI_MAILOVOU_NOTIFIKACI = True | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ import os.path | ||||||
| # Import common settings | # Import common settings | ||||||
| from .settings_common import * # zatim nutne, casem snad vyresime # noqa | from .settings_common import * # zatim nutne, casem snad vyresime # noqa | ||||||
| 
 | 
 | ||||||
| MIDDLEWARE_CLASSES += ( | MIDDLEWARE += ( | ||||||
|     'debug_toolbar.middleware.DebugToolbarMiddleware', |     'debug_toolbar.middleware.DebugToolbarMiddleware', | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|  | @ -32,7 +32,7 @@ DEBUG = True | ||||||
| 
 | 
 | ||||||
| TEMPLATES[0]['OPTIONS']['debug'] = True | TEMPLATES[0]['OPTIONS']['debug'] = True | ||||||
| 
 | 
 | ||||||
| ALLOWED_HOSTS = ['*.mam.mff.cuni.cz', 'atrey.karlin.mff.cuni.cz', 'mam.mff.cuni.cz', 'mam-test.kam.mff.cuni.cz', 'gimli.ms.mff.cuni.cz'] | ALLOWED_HOSTS = ['*.mam.mff.cuni.cz', 'atrey.karlin.mff.cuni.cz', 'mam.mff.cuni.cz', 'mam-test.kam.mff.cuni.cz', 'gimli.ms.mff.cuni.cz', 'mam-test.ks.matfyz.cz'] | ||||||
| 
 | 
 | ||||||
| # Database | # Database | ||||||
| # https://docs.djangoproject.com/en/1.7/ref/settings/#databases | # https://docs.djangoproject.com/en/1.7/ref/settings/#databases | ||||||
|  | @ -65,3 +65,14 @@ CSRF_COOKIE_SECURE = True | ||||||
| 
 | 
 | ||||||
| LOGGING['loggers']['']['handlers'] = ['console', 'mail_admins'] | LOGGING['loggers']['']['handlers'] = ['console', 'mail_admins'] | ||||||
| LOGGING['loggers']['django']['handlers'] = ['console', 'mail_admins'] | LOGGING['loggers']['django']['handlers'] = ['console', 'mail_admins'] | ||||||
|  | LOGGING['handlers']['registration_logfile']['filename'] = '/home/mam-web/logs/test/registration.log' | ||||||
|  | LOGGING['handlers']['registration_error_log']['filename'] = '/home/mam-web/logs/test/registration_errors.log' | ||||||
|  | 
 | ||||||
|  | FILE_UPLOAD_PERMISSIONS = 0o440 | ||||||
|  | 
 | ||||||
|  | # Testování e-mailů | ||||||
|  | POSLI_MAILOVOU_NOTIFIKACI = True | ||||||
|  | EMAIL_BACKEND = 'various.mail_prefixer.PrefixingMailBackend' | ||||||
|  | # TODO Pouze na otestování testu… Zvolit konferu! | ||||||
|  | # XXX: Je to pole, protože implementační detail backendu. | ||||||
|  | TESTOVACI_EMAILOVA_KONFERENCE = ['betatest@mam.mff.cuni.cz'] | ||||||
|  |  | ||||||
							
								
								
									
										38
									
								
								mamweb/static/css/mamweb-dev.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,38 @@ | ||||||
|  | /* | ||||||
|  | .pink { | ||||||
|  | 	background-color: #ffc0cb; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div.borderized { | ||||||
|  | 	border-style: solid; | ||||||
|  | 	border-radius: 5px; | ||||||
|  | 	padding: 5px; | ||||||
|  | 	padding-right: 20px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div.tnmenu { | ||||||
|  | 	float: right; | ||||||
|  | 	margin-right: 0px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | div.parent { | ||||||
|  | 	border-width: 2px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div.children { | ||||||
|  | 	border-width: 1px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div.node_type { | ||||||
|  | 	background-color: #d4d4d4; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .hidden-tn { | ||||||
|  | 	display: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*test*/ | ||||||
|  | h1 { | ||||||
|  | 	color: chartreuse; | ||||||
|  | } | ||||||
| Before Width: | Height: | Size: 218 B | 
							
								
								
									
										201
									
								
								mamweb/static/fonts/OpenSans/Apache License.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,201 @@ | ||||||
|  | Apache License | ||||||
|  |                            Version 2.0, January 2004 | ||||||
|  |                         http://www.apache.org/licenses/ | ||||||
|  | 
 | ||||||
|  |    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||||
|  | 
 | ||||||
|  |    1. Definitions. | ||||||
|  | 
 | ||||||
|  |       "License" shall mean the terms and conditions for use, reproduction, | ||||||
|  |       and distribution as defined by Sections 1 through 9 of this document. | ||||||
|  | 
 | ||||||
|  |       "Licensor" shall mean the copyright owner or entity authorized by | ||||||
|  |       the copyright owner that is granting the License. | ||||||
|  | 
 | ||||||
|  |       "Legal Entity" shall mean the union of the acting entity and all | ||||||
|  |       other entities that control, are controlled by, or are under common | ||||||
|  |       control with that entity. For the purposes of this definition, | ||||||
|  |       "control" means (i) the power, direct or indirect, to cause the | ||||||
|  |       direction or management of such entity, whether by contract or | ||||||
|  |       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||||
|  |       outstanding shares, or (iii) beneficial ownership of such entity. | ||||||
|  | 
 | ||||||
|  |       "You" (or "Your") shall mean an individual or Legal Entity | ||||||
|  |       exercising permissions granted by this License. | ||||||
|  | 
 | ||||||
|  |       "Source" form shall mean the preferred form for making modifications, | ||||||
|  |       including but not limited to software source code, documentation | ||||||
|  |       source, and configuration files. | ||||||
|  | 
 | ||||||
|  |       "Object" form shall mean any form resulting from mechanical | ||||||
|  |       transformation or translation of a Source form, including but | ||||||
|  |       not limited to compiled object code, generated documentation, | ||||||
|  |       and conversions to other media types. | ||||||
|  | 
 | ||||||
|  |       "Work" shall mean the work of authorship, whether in Source or | ||||||
|  |       Object form, made available under the License, as indicated by a | ||||||
|  |       copyright notice that is included in or attached to the work | ||||||
|  |       (an example is provided in the Appendix below). | ||||||
|  | 
 | ||||||
|  |       "Derivative Works" shall mean any work, whether in Source or Object | ||||||
|  |       form, that is based on (or derived from) the Work and for which the | ||||||
|  |       editorial revisions, annotations, elaborations, or other modifications | ||||||
|  |       represent, as a whole, an original work of authorship. For the purposes | ||||||
|  |       of this License, Derivative Works shall not include works that remain | ||||||
|  |       separable from, or merely link (or bind by name) to the interfaces of, | ||||||
|  |       the Work and Derivative Works thereof. | ||||||
|  | 
 | ||||||
|  |       "Contribution" shall mean any work of authorship, including | ||||||
|  |       the original version of the Work and any modifications or additions | ||||||
|  |       to that Work or Derivative Works thereof, that is intentionally | ||||||
|  |       submitted to Licensor for inclusion in the Work by the copyright owner | ||||||
|  |       or by an individual or Legal Entity authorized to submit on behalf of | ||||||
|  |       the copyright owner. For the purposes of this definition, "submitted" | ||||||
|  |       means any form of electronic, verbal, or written communication sent | ||||||
|  |       to the Licensor or its representatives, including but not limited to | ||||||
|  |       communication on electronic mailing lists, source code control systems, | ||||||
|  |       and issue tracking systems that are managed by, or on behalf of, the | ||||||
|  |       Licensor for the purpose of discussing and improving the Work, but | ||||||
|  |       excluding communication that is conspicuously marked or otherwise | ||||||
|  |       designated in writing by the copyright owner as "Not a Contribution." | ||||||
|  | 
 | ||||||
|  |       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||||
|  |       on behalf of whom a Contribution has been received by Licensor and | ||||||
|  |       subsequently incorporated within the Work. | ||||||
|  | 
 | ||||||
|  |    2. Grant of Copyright License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       copyright license to reproduce, prepare Derivative Works of, | ||||||
|  |       publicly display, publicly perform, sublicense, and distribute the | ||||||
|  |       Work and such Derivative Works in Source or Object form. | ||||||
|  | 
 | ||||||
|  |    3. Grant of Patent License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       (except as stated in this section) patent license to make, have made, | ||||||
|  |       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||||
|  |       where such license applies only to those patent claims licensable | ||||||
|  |       by such Contributor that are necessarily infringed by their | ||||||
|  |       Contribution(s) alone or by combination of their Contribution(s) | ||||||
|  |       with the Work to which such Contribution(s) was submitted. If You | ||||||
|  |       institute patent litigation against any entity (including a | ||||||
|  |       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||||
|  |       or a Contribution incorporated within the Work constitutes direct | ||||||
|  |       or contributory patent infringement, then any patent licenses | ||||||
|  |       granted to You under this License for that Work shall terminate | ||||||
|  |       as of the date such litigation is filed. | ||||||
|  | 
 | ||||||
|  |    4. Redistribution. You may reproduce and distribute copies of the | ||||||
|  |       Work or Derivative Works thereof in any medium, with or without | ||||||
|  |       modifications, and in Source or Object form, provided that You | ||||||
|  |       meet the following conditions: | ||||||
|  | 
 | ||||||
|  |       (a) You must give any other recipients of the Work or | ||||||
|  |           Derivative Works a copy of this License; and | ||||||
|  | 
 | ||||||
|  |       (b) You must cause any modified files to carry prominent notices | ||||||
|  |           stating that You changed the files; and | ||||||
|  | 
 | ||||||
|  |       (c) You must retain, in the Source form of any Derivative Works | ||||||
|  |           that You distribute, all copyright, patent, trademark, and | ||||||
|  |           attribution notices from the Source form of the Work, | ||||||
|  |           excluding those notices that do not pertain to any part of | ||||||
|  |           the Derivative Works; and | ||||||
|  | 
 | ||||||
|  |       (d) If the Work includes a "NOTICE" text file as part of its | ||||||
|  |           distribution, then any Derivative Works that You distribute must | ||||||
|  |           include a readable copy of the attribution notices contained | ||||||
|  |           within such NOTICE file, excluding those notices that do not | ||||||
|  |           pertain to any part of the Derivative Works, in at least one | ||||||
|  |           of the following places: within a NOTICE text file distributed | ||||||
|  |           as part of the Derivative Works; within the Source form or | ||||||
|  |           documentation, if provided along with the Derivative Works; or, | ||||||
|  |           within a display generated by the Derivative Works, if and | ||||||
|  |           wherever such third-party notices normally appear. The contents | ||||||
|  |           of the NOTICE file are for informational purposes only and | ||||||
|  |           do not modify the License. You may add Your own attribution | ||||||
|  |           notices within Derivative Works that You distribute, alongside | ||||||
|  |           or as an addendum to the NOTICE text from the Work, provided | ||||||
|  |           that such additional attribution notices cannot be construed | ||||||
|  |           as modifying the License. | ||||||
|  | 
 | ||||||
|  |       You may add Your own copyright statement to Your modifications and | ||||||
|  |       may provide additional or different license terms and conditions | ||||||
|  |       for use, reproduction, or distribution of Your modifications, or | ||||||
|  |       for any such Derivative Works as a whole, provided Your use, | ||||||
|  |       reproduction, and distribution of the Work otherwise complies with | ||||||
|  |       the conditions stated in this License. | ||||||
|  | 
 | ||||||
|  |    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||||
|  |       any Contribution intentionally submitted for inclusion in the Work | ||||||
|  |       by You to the Licensor shall be under the terms and conditions of | ||||||
|  |       this License, without any additional terms or conditions. | ||||||
|  |       Notwithstanding the above, nothing herein shall supersede or modify | ||||||
|  |       the terms of any separate license agreement you may have executed | ||||||
|  |       with Licensor regarding such Contributions. | ||||||
|  | 
 | ||||||
|  |    6. Trademarks. This License does not grant permission to use the trade | ||||||
|  |       names, trademarks, service marks, or product names of the Licensor, | ||||||
|  |       except as required for reasonable and customary use in describing the | ||||||
|  |       origin of the Work and reproducing the content of the NOTICE file. | ||||||
|  | 
 | ||||||
|  |    7. Disclaimer of Warranty. Unless required by applicable law or | ||||||
|  |       agreed to in writing, Licensor provides the Work (and each | ||||||
|  |       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||||
|  |       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||||
|  |       implied, including, without limitation, any warranties or conditions | ||||||
|  |       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||||
|  |       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||||
|  |       appropriateness of using or redistributing the Work and assume any | ||||||
|  |       risks associated with Your exercise of permissions under this License. | ||||||
|  | 
 | ||||||
|  |    8. Limitation of Liability. In no event and under no legal theory, | ||||||
|  |       whether in tort (including negligence), contract, or otherwise, | ||||||
|  |       unless required by applicable law (such as deliberate and grossly | ||||||
|  |       negligent acts) or agreed to in writing, shall any Contributor be | ||||||
|  |       liable to You for damages, including any direct, indirect, special, | ||||||
|  |       incidental, or consequential damages of any character arising as a | ||||||
|  |       result of this License or out of the use or inability to use the | ||||||
|  |       Work (including but not limited to damages for loss of goodwill, | ||||||
|  |       work stoppage, computer failure or malfunction, or any and all | ||||||
|  |       other commercial damages or losses), even if such Contributor | ||||||
|  |       has been advised of the possibility of such damages. | ||||||
|  | 
 | ||||||
|  |    9. Accepting Warranty or Additional Liability. While redistributing | ||||||
|  |       the Work or Derivative Works thereof, You may choose to offer, | ||||||
|  |       and charge a fee for, acceptance of support, warranty, indemnity, | ||||||
|  |       or other liability obligations and/or rights consistent with this | ||||||
|  |       License. However, in accepting such obligations, You may act only | ||||||
|  |       on Your own behalf and on Your sole responsibility, not on behalf | ||||||
|  |       of any other Contributor, and only if You agree to indemnify, | ||||||
|  |       defend, and hold each Contributor harmless for any liability | ||||||
|  |       incurred by, or claims asserted against, such Contributor by reason | ||||||
|  |       of your accepting any such warranty or additional liability. | ||||||
|  | 
 | ||||||
|  |    END OF TERMS AND CONDITIONS | ||||||
|  | 
 | ||||||
|  |    APPENDIX: How to apply the Apache License to your work. | ||||||
|  | 
 | ||||||
|  |       To apply the Apache License to your work, attach the following | ||||||
|  |       boilerplate notice, with the fields enclosed by brackets "[]" | ||||||
|  |       replaced with your own identifying information. (Don't include | ||||||
|  |       the brackets!)  The text should be enclosed in the appropriate | ||||||
|  |       comment syntax for the file format. We also recommend that a | ||||||
|  |       file or class name and description of purpose be included on the | ||||||
|  |       same "printed page" as the copyright notice for easier | ||||||
|  |       identification within third-party archives. | ||||||
|  | 
 | ||||||
|  |    Copyright [yyyy] [name of copyright owner] | ||||||
|  | 
 | ||||||
|  |    Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |    you may not use this file except in compliance with the License. | ||||||
|  |    You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |        http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | 
 | ||||||
|  |    Unless required by applicable law or agreed to in writing, software | ||||||
|  |    distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |    See the License for the specific language governing permissions and | ||||||
|  |    limitations under the License. | ||||||
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-BoldItalic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-ExtraBold.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-ExtraBoldItalic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-Italic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-Light.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-LightItalic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-Semibold.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/fonts/OpenSans/OpenSans-SemiboldItalic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										120
									
								
								mamweb/static/images/MATFYZ_MM_barevne.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,120 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||||
|  | 
 | ||||||
|  | <svg | ||||||
|  |    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||||
|  |    xmlns:cc="http://creativecommons.org/ns#" | ||||||
|  |    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg2" | ||||||
|  |    xml:space="preserve" | ||||||
|  |    width="873.38959" | ||||||
|  |    height="697.76959" | ||||||
|  |    viewBox="0 0 873.38957 697.7696" | ||||||
|  |    sodipodi:docname="MATFYZ_MM_barevne.svg" | ||||||
|  |    inkscape:version="0.92.3 (2405546, 2018-03-11)"><metadata | ||||||
|  |      id="metadata8"><rdf:RDF><cc:Work | ||||||
|  |          rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | ||||||
|  |            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs | ||||||
|  |      id="defs6" /><sodipodi:namedview | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#666666" | ||||||
|  |      borderopacity="1" | ||||||
|  |      objecttolerance="10" | ||||||
|  |      gridtolerance="10" | ||||||
|  |      guidetolerance="10" | ||||||
|  |      inkscape:pageopacity="0" | ||||||
|  |      inkscape:pageshadow="2" | ||||||
|  |      inkscape:window-width="1853" | ||||||
|  |      inkscape:window-height="1025" | ||||||
|  |      id="namedview4" | ||||||
|  |      showgrid="false" | ||||||
|  |      inkscape:zoom="0.29733907" | ||||||
|  |      inkscape:cx="436.69495" | ||||||
|  |      inkscape:cy="348.92161" | ||||||
|  |      inkscape:window-x="67" | ||||||
|  |      inkscape:window-y="27" | ||||||
|  |      inkscape:window-maximized="1" | ||||||
|  |      inkscape:current-layer="g10" /><g | ||||||
|  |      id="g10" | ||||||
|  |      inkscape:groupmode="layer" | ||||||
|  |      inkscape:label="ink_ext_XXXXXX" | ||||||
|  |      transform="matrix(1.3333333,0,0,-1.3333333,-124.56506,745.70131)"><g | ||||||
|  |        id="g12" | ||||||
|  |        transform="scale(0.1)"><path | ||||||
|  |          d="M 7483.93,3086.74 6136.77,1739.57 h -1324.9 l 1347.41,1347.17 h 1324.65" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path14" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 7210.43,1001.61 v -88.579 h -308.59 v 91.489 l 179.35,190.24 H 6909.1 v 88.58 h 294.07 v -91.49 l -179.35,-190.24 h 186.61" | ||||||
|  |          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path16" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="M 6847.38,1283.34 6704.34,793.219 h -100.93 l 34.85,119.812 H 6578 l -108.19,370.309 h 114.72 l 73.34,-298.43 74.06,298.43 h 115.45" | ||||||
|  |          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path18" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 6437.13,1415.49 -5.08,-72.61 c -21.06,2.18 -37.76,2.9 -50.1,2.9 -52.28,0 -60.99,-6.53 -62.45,-63.17 h 94.4 v -87.85 h -94.4 V 913.031 h -108.91 v 387.009 c 0,96.57 32.67,128.52 129.24,128.52 36.31,0 74.07,-5.81 97.3,-13.07" | ||||||
|  |          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path20" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="M 6151.29,3087.46 C 5702.07,2638.25 5252.62,2188.79 4803.4,1739.57 h -3.15 l -0.72,0.73 1347.4,1347.16 h 4.36" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path22" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 6116.92,998.711 5.81,-78.422 c -24.69,-7.988 -67.53,-14.519 -99.48,-14.519 -80.59,0 -119.8,25.41 -119.8,124.16 v 321.66 l 108.91,30.5 v -98.75 h 87.13 v -88.58 h -87.13 V 1056.8 c 0,-54.46 6.54,-62.448 48.65,-62.448 15.98,0 37.76,1.449 55.91,4.359" | ||||||
|  |          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path24" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 5685.62,1068.41 c -26.14,1.45 -52.28,2.91 -68.26,2.91 -38.48,-0.73 -53,-15.98 -53,-44.3 0,-26.86 18.87,-44.29 56.63,-44.29 24.69,0 46.47,8.719 64.63,21.06 z m 0,67.53 v 3.63 c 0,55.91 -17.43,65.35 -74.07,65.35 -38.48,0 -80.59,-2.9 -122.71,-6.53 l -5.08,77.69 c 43.56,7.99 104.56,14.52 147.4,14.52 124.16,0 163.37,-31.95 163.37,-148.13 V 913.031 h -72.61 l -22.51,37.75 c -31.22,-27.59 -69.7,-45.011 -116.9,-45.011 -79.15,0 -124.16,47.921 -124.16,119.8 0,84.96 47.92,113.28 153.2,113.28 23.24,0.72 49.38,-0.73 74.07,-2.91" | ||||||
|  |          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path26" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 5424.22,522.629 -17.19,-154.66 h -50.58 l 31.71,231.859 h 50.1 l 51.31,-134.078 50.58,134.078 h 51.56 l 30.49,-231.859 h -50.82 l -16.7,156.351 -45.27,-119.082 h -41.62 l -43.57,117.391" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path28" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 5204.69,402.09 c 9.93,0 18.64,2.91 26.87,8.23 l -54.7,56.399 c -8.47,-7.02 -12.83,-16.457 -12.83,-28.559 0,-21.789 17.43,-36.07 40.66,-36.07 z m -88.58,30.98 c 0,25.168 13.31,48.172 35.58,61.239 -13.07,16.461 -19.61,31.953 -19.61,47.203 0,19.84 6.78,35.57 20.33,47.918 13.8,12.582 31.71,18.879 53.98,18.879 52.04,0 77.93,-20.817 81.81,-65.11 h -53.74 c -1.45,16.942 -11.13,25.903 -28.07,25.903 -13.56,0 -23.96,-8.481 -23.96,-23.243 0,-11.859 4.6,-19.847 20.09,-35.82 l 56.39,-58.09 c 3.87,13.563 5.81,27.84 5.81,43.813 h 50.83 c 0,-28.563 -7.51,-54.942 -22.76,-79.153 l 47.2,-48.64 h -67.04 l -13.07,13.07 c -17.19,-12.109 -36.07,-18.16 -57.36,-18.16 -24.21,0 -45.02,6.051 -61.72,18.402 -16.7,12.578 -24.69,29.77 -24.69,51.789" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path30" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 5130.87,1248.49 c 39.94,25.41 89.31,42.11 127.8,42.11 72.61,0 109.64,-39.94 109.64,-121.98 V 913.031 h -108.92 v 212.019 c 0,67.53 -7.26,76.97 -53,76.97 -17.43,0 -38.49,-2.18 -58.09,-6.54 0.73,-8.71 1.45,-17.43 1.45,-26.86 V 913.031 h -108.91 v 212.019 c 0,67.53 -7.26,76.97 -53.01,76.97 -17.43,0 -38.48,-2.18 -58.09,-6.54 V 913.031 h -108.91 v 370.309 h 72.61 l 19.6,-34.13 c 39.21,24.69 88.59,41.39 127.07,41.39 42.84,0 73.34,-13.79 90.76,-42.11" | ||||||
|  |          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path32" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 5019.05,524.32 -45.26,-119.082 h -41.63 l -43.56,117.391 -17.43,-154.66 h -50.34 l 31.7,231.859 h 50.1 l 51.07,-134.078 50.83,134.078 h 51.55 l 30.5,-231.859 h -50.83 l -16.7,156.351" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path34" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="M 6159.28,3086.74 4811.87,1739.57 h -8.47 c 449.22,449.22 898.67,898.68 1347.89,1347.89 h 1333.37 l -0.73,-0.72 H 6159.28" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path36" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 4800.25,1739.57 h -1.45 l 0.73,0.73 z" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path38" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 4782.34,1740.3 -0.24,-0.24 H 2883.34 v 1899 l 1899,-1898.76" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path40" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="M 4481.01,1707.38 V 359.488 H 3133.12 V 1707.38 h 1347.89" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path42" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="M 2850.67,5592.76 V 3710.7 l -941.27,941.03 z" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path44" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="m 2845.59,3672.94 -953.14,-953.13 -953.126,953.13 953.126,953.14 953.14,-953.14" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path46" | ||||||
|  |          inkscape:connector-curvature="0" /><path | ||||||
|  |          d="M 1875.27,4651.73 934.238,3710.7 v 1882.06 z" | ||||||
|  |          style="fill:#e94e0f;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||||
|  |          id="path48" | ||||||
|  |          inkscape:connector-curvature="0" /></g></g></svg> | ||||||
| After Width: | Height: | Size: 7.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/images/MSMT_logo_bez_textu_black.eps
									
									
									
									
									
										Normal file
									
								
							
							
						
						| Before Width: | Height: | Size: 13 KiB | 
| Before Width: | Height: | Size: 15 KiB | 
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/images/graf/adrenalinove.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 568 KiB | 
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/images/graf/behaci.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 203 KiB | 
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/images/graf/ceny.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.4 MiB | 
							
								
								
									
										
											BIN
										
									
								
								mamweb/static/images/graf/deskovky.jpeg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 56 KiB | 
 Pavel "LEdoian" Turinsky
						Pavel "LEdoian" Turinsky