Browse Source

merge

export_seznamu_prednasek
Kateřina Č 4 years ago
parent
commit
d873544f8a
  1. 6
      .gitignore
  2. 187
      MIGRATIONS
  3. 8
      Makefile
  4. 2
      flat.json
  5. 4
      galerie/admin.py
  6. 18
      galerie/migrations/0010_auto_20200819_0947.py
  7. 2
      galerie/models.py
  8. 4
      galerie/templates/galerie/GalerieNahled.html
  9. 7
      galerie/urls.py
  10. 62
      galerie/views.py
  11. 29
      korektury/models.py
  12. 4
      korektury/templates/korektury/base.html
  13. 7
      korektury/templates/korektury/help.html
  14. 4
      korektury/templates/korektury/opraf.html
  15. 4
      korektury/templates/korektury/seznam.html
  16. 13
      korektury/templates/korektury/submenu.html
  17. BIN
      korektury/testpdfs/A.pdf
  18. 5125
      korektury/testpdfs/B.pdf
  19. 69
      korektury/testutils.py
  20. 11
      korektury/urls.py
  21. 26
      korektury/views.py
  22. 8
      mamweb/settings_common.py
  23. 2
      mamweb/settings_local.py
  24. 4
      mamweb/settings_test.py
  25. 4
      mamweb/static/css/mamweb.css
  26. 0
      mamweb/static/images/logo_1.svg
  27. 0
      mamweb/static/images/logo_2.svg
  28. 0
      mamweb/static/images/logo_3.svg
  29. 0
      mamweb/static/images/logo_4.svg
  30. 0
      mamweb/static/images/logo_5.svg
  31. 0
      mamweb/static/images/logo_6.svg
  32. 6
      mamweb/templates/base.html
  33. 26
      mamweb/templates/logo.html
  34. 4
      mamweb/templates/menu.html
  35. 4
      mamweb/templates/menu_mobile.html
  36. 2
      mamweb_prod.ini
  37. 2
      mamweb_test.ini
  38. 10
      prednasky/templates/prednasky/base.html
  39. 2
      prednasky/templates/prednasky/metaseznam_prednasek.html
  40. 2
      prednasky/templates/prednasky/seznam_prednasek.html
  41. 14
      prednasky/templates/prednasky/seznam_prednasek_export.txt
  42. 27
      prednasky/urls.py
  43. 55
      prednasky/views.py
  44. 3
      seminar/admin.py
  45. 6
      seminar/management/commands/auth.py
  46. 21
      seminar/migrations/0001_squashed_0067_auto_20190814_0805.py
  47. 3
      seminar/migrations/0019_rocnik_ciselne.py
  48. 8
      seminar/migrations/0052_user_to_organizator.py
  49. 2
      seminar/migrations/0056_vrcholy_pro_rocniky_a_cisla.py
  50. 2
      seminar/migrations/0057_reseni_to_reseni_hodnoceni.py
  51. 8
      seminar/migrations/0058_problem_to_uloha_tema_clanek.py
  52. 4
      seminar/migrations/0059_vytvorit_pohadkanode.py
  53. 2
      seminar/migrations/0060_spoj_stromy.py
  54. 4
      seminar/migrations/0065_treenode_polymorphic_ctype.py
  55. 4
      seminar/migrations/0066_problem_polymorphic_ctype.py
  56. 2
      seminar/migrations/0068_treenode_nazev.py
  57. 6
      seminar/migrations/0080_zruseni_claneknode_a_konferanode.py
  58. 8
      seminar/migrations/0084_clanek_cislo.py
  59. 17
      seminar/migrations/0086_auto_20200819_0959.py
  60. 49
      seminar/migrations/0087_fix_polymorphism.py
  61. 35
      seminar/migrations/0088_perm_org_a_ucastnik.py
  62. 14
      seminar/migrations/fix_0058.py
  63. 7
      seminar/models.py
  64. 22
      seminar/templates/seminar/archiv/cislo.html
  65. 4
      seminar/templates/seminar/archiv/problem.html
  66. 4
      seminar/templates/seminar/archiv/rocnik.html
  67. 2
      seminar/templates/seminar/clanky/resitelske_clanky.html
  68. 10
      seminar/templates/seminar/formular_ok.html
  69. 8
      seminar/templates/seminar/novinky.html
  70. 87
      seminar/templates/seminar/orgorozcestnik.html
  71. 3
      seminar/templates/seminar/profil/gdpr.html
  72. 6
      seminar/templates/seminar/profil/nahraj_reseni.html
  73. 2
      seminar/templates/seminar/profil/prihlaska_field.html
  74. 14
      seminar/templates/seminar/soustredeni/seznam_soustredeni.html
  75. 1
      seminar/templates/seminar/soustredeni/seznam_ucastniku.html
  76. 2
      seminar/templates/seminar/titulnistrana.html
  77. 2
      seminar/templates/seminar/treenode.html
  78. 2
      seminar/templates/seminar/zadani/AktualniVysledkovka.html
  79. 55
      seminar/templates/seminar/zadani/AktualniZadani.html
  80. 14
      seminar/templates/seminar/zadani/Temata.html
  81. 55
      seminar/testutils.py
  82. 112
      seminar/urls.py
  83. 14
      seminar/utils.py
  84. 2
      seminar/views/utils.py
  85. 224
      seminar/views/views_all.py
  86. 661
      sitetree_new.json

6
.gitignore

@ -24,3 +24,9 @@ TODO
# .htpasswd kvůli přihlášení
.htpasswd
# reversion kvůli historii objektů v reversion
**/reversion
# pro lidi, co programují v nástrojích od JetBrains
.idea

187
MIGRATIONS

@ -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

8
Makefile

@ -65,7 +65,7 @@ schema_all.pdf: venv_check
# Deploy to current *mamweb-test* directory
deploy_test: venv_check
@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi
@if [ `pwd` != "/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/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 ..."
git pull origin test
git clean -f
@ -81,9 +81,9 @@ deploy_test: venv_check
# Deploy to current *mamweb-prod* directory
deploy_prod: venv_check
@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi
@if [ `pwd` != "/akce/mam/www/mamweb-prod" ]; then echo "Only possible in /akce/mam/www/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 ..."
( cd .. && ./backup_prod_db.sh )
( cd -P .. && ./backup_prod_db.sh )
@echo "Installing version from origin/master ..."
git pull origin master
git clean -f
@ -109,7 +109,7 @@ sync_prod_flatpages: venv_check
# Sync test media directory with production
sync_test_media:
@if [ ${USER} != "mam-web" ]; then echo "Only possible by user mam-web"; exit 1; fi
@if [ `pwd` != "/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/mamweb-test"; exit 1; fi
@if [ `readlink -f .` != "/aux/akce/mam/www/mamweb-test" ]; then echo "Only possible in /akce/mam/www/mamweb-test"; exit 1; fi
rsync -av --delete /akce/mam/www/mamweb-prod/media/ ./media
# Sync test database with production database

2
flat.json

File diff suppressed because one or more lines are too long

4
galerie/admin.py

@ -30,14 +30,14 @@ def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset):
class GalerieInline(admin.TabularInline):
model = Obrazek
fields = ['obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag']
fields = ['obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi']
readonly_fields = ['nazev', 'obrazek_maly_tag']
formfield_overrides = {
models.TextField: {'widget': forms.TextInput},
}
class ObrazekAdmin(admin.ModelAdmin):
list_display = ('obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag')
list_display = ('obrazek_velky', 'nazev', 'popis', 'obrazek_maly_tag', 'poradi')
search_fields = ['nazev','popis']
class GalerieAdmin(admin.ModelAdmin):

18
galerie/migrations/0010_auto_20200819_0947.py

@ -0,0 +1,18 @@
# Generated by Django 2.2.15 on 2020-08-19 07:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('galerie', '0009_auto_20190610_2358'),
]
operations = [
migrations.AlterField(
model_name='galerie',
name='poradi',
field=models.IntegerField(blank=True, default=0, verbose_name='Pořadí'),
),
]

2
galerie/models.py

@ -94,7 +94,7 @@ class Galerie(models.Model):
on_delete=models.SET_NULL)
soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True,
on_delete=models.PROTECT)
poradi = models.IntegerField('Pořadí', blank = True, null = True)
poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0)
def __str__(self):
return self.nazev

4
galerie/templates/galerie/GalerieNahled.html

@ -61,7 +61,7 @@ Galerie {{galerie.nazev}}
{{ galerie|truncatechars:max_delka_nazvu }}
</div>
</a>
{% if user.is_staff and galerie.zobrazit > 0 %}
{% if user.je_org and galerie.zobrazit > 0 %}
<div class="mam-org-only-galerie">
({{galerie.poradi}})
<span class="plus"><a href="plus/{{galerie.pk}}/">+</a></span>
@ -73,7 +73,7 @@ Galerie {{galerie.nazev}}
{% endwith %}
{% endif %}
{% endif %}
{% if user.is_staff and galerie.zobrazit > 0 %}
{% if user.je_org and galerie.zobrazit > 0 %}
<div class="mam-org-only">
<a href="./new">Vytvořit novou podgalerii </a>
</div>

7
galerie/urls.py

@ -1,13 +1,14 @@
# coding: utf-8
from django.urls import path
from seminar.utils import org_required
from . import views
urlpatterns = [
path('<int:pk>/', views.nahled),
path('<int:pk>/<int:fotka>/', views.detail),
path('<int:galerie>/new/', views.new_galerie),
path('<int:galerie>/plus/<int:subgalerie>/', views.plus_galerie),
path('<int:galerie>/minus/<int:subgalerie>/', views.minus_galerie),
path('<int:galerie>/new/', org_required(views.new_galerie)),
path('<int:galerie>/plus/<int:subgalerie>/', org_required(views.plus_galerie)),
path('<int:galerie>/minus/<int:subgalerie>/', org_required(views.minus_galerie)),
]

62
galerie/views.py

@ -14,7 +14,7 @@ from galerie.forms import KomentarForm, NewGalerieForm
def zobrazit(galerie, request):
preview = False
if galerie.zobrazit >= 1:
if request.user.is_staff:
if request.user.je_org:
preview = True;
else:
raise Http404
@ -35,16 +35,16 @@ def nahled(request, pk, soustredeni):
galerie = get_object_or_404(Galerie, pk=pk)
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)
obrazky = Obrazek.objects.filter(galerie = galerie)
obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev')
preview = zobrazit(galerie, request)
sourozenci = []
if galerie.galerie_up:
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)
predchozi = None
@ -82,7 +82,7 @@ def detail(request, pk, fotka, soustredeni):
galerie = get_object_or_404(Galerie, pk=pk)
preview = zobrazit(galerie, request)
obrazek = get_object_or_404(Obrazek, pk=fotka)
obrazky = galerie.obrazek_set.all()
obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev')
# vytvoreni a obslouzeni formulare
if request.method == 'POST':
@ -96,22 +96,23 @@ def detail(request, pk, fotka, soustredeni):
# Poradi aktualniho obrazku v galerii/stitku.
for i in range(len(obrazky)):
if obrazky[i] == obrazek:
znacka = i
poradi = i
break
else:
# Obrazek neni v galerii/stitku.
raise Http404
# Nacteni okolnich obrazku a galerii
# TODO vyjmout zjisteni predchozich a nasledujicich galerii
# a udelat z toho funkci, ktera se pouzije u nahledu
predchozi_galerie = None
nasledujici_galerie = None
obrazky_dalsi = obrazky[znacka+1:znacka+NAHLEDU+1]
if (znacka+1) > NAHLEDU:
obrazky_predchozi = obrazky[znacka-NAHLEDU:znacka]
obrazky_dalsi = obrazky[poradi+1:poradi+NAHLEDU+1]
if (poradi+1) > NAHLEDU:
obrazky_predchozi = obrazky[poradi-NAHLEDU:poradi]
else:
obrazky_predchozi = obrazky[0:znacka]
obrazky_predchozi = obrazky[0:poradi]
if galerie.poradi > 1:
predchozi_galerie = Galerie.objects.\
filter(galerie_up=galerie.galerie_up).\
@ -120,41 +121,44 @@ def detail(request, pk, fotka, soustredeni):
predchozi_galerie = predchozi_galerie[0]
else:
predchozi_galerie = None
if (znacka+1) == len(obrazky):
nasledujici_galerie = Galerie.objects.\
filter(galerie_up=galerie.galerie_up).\
filter(poradi=(galerie.poradi+1))
if (poradi+1) == len(obrazky): # Tohle je poslední obrázek
if (galerie.poradi is not None
and galerie.galerie_up is not None):
nasledujici_galerie = Galerie.objects.\
filter(galerie_up=galerie.galerie_up).\
filter(poradi=(galerie.poradi+1))
else:
nasledujici_galerie = None
if nasledujici_galerie:
nasledujici_galerie = nasledujici_galerie[0]
else:
nasledujici_galerie = None
# Preskalovani obrazku do vybraneho prostoru.
vyska = obrazek.obrazek_stredni.height
sirka = obrazek.obrazek_stredni.width
if vyska > MAX_VYSKA:
sirka = sirka * MAX_VYSKA / vyska
sirka = sirka * MAX_VYSKA / vyska
vyska = MAX_VYSKA
if sirka > MAX_SIRKA:
vyska = vyska * MAX_SIRKA / 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),
})
{'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):

29
korektury/models.py

@ -79,22 +79,31 @@ class KorekturovanePDF(models.Model):
self.stran = 0
while True:
res = subprocess.call([
"convert",
"-density", "180x180",
"-geometry", " 1024x1448",
"%s[%d]" % (self.pdf.path, self.stran),
os.path.join(
#Parametry inspirovány chybovou hláškou imagemagicku
"gs",
"-sstdout=%stderr",
"-dSAFER",
"-dNOPAUSE",
"-dBATCH",
"-dNOPROMPT",
"-sDEVICE=pngalpha",
"-r180x180",
"-dFirstPage=%d" % (self.stran+1),
"-dLastPage=%d" % (self.stran+1),
"-sOutputFile="+os.path.join(
dirname,
"%s-%d.png" % (self.get_prefix(), self.stran)
)
"%s-%d.png" % (self.get_prefix(), self.stran)),
"-f%s" % (self.pdf.path)
])
if res == 1:
if not os.path.exists(os.path.join(
dirname,
"%s-%d.png" % (self.get_prefix(), self.stran))):
break
self.stran += 1
# Změnil se počet stran, ukládáme
super(KorekturovanePDF, self).save()
def save(self):
def save(self, **kwargs):
# Pokud se nezmenilo PDF, tak nepregenerovavej nahledy
try:
original = KorekturovanePDF.objects.get(pk=self.pk)
@ -104,7 +113,7 @@ class KorekturovanePDF(models.Model):
except ObjectDoesNotExist:
pass
# uložíme nahrávané pdf
super(KorekturovanePDF, self).save()
super(KorekturovanePDF, self).save(kwargs)
# uložíme png a změněný počet stran
self.convert()

4
korektury/templates/korektury/base.html

@ -1,5 +1,9 @@
{% 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 %}

7
korektury/templates/korektury/help.html

@ -1,4 +1,11 @@
{% extends "korektury/base.html" %}
{% block submenu %}
{% with "help" as selected %}
{% include "korektury/submenu.html" %}
{% endwith %}
{% endblock %}
{% load staticfiles %}
{% block title %} Nápověda ke korigovátku {% endblock title %}

4
korektury/templates/korektury/opraf.html

@ -36,12 +36,12 @@
id="neni_chyba_checkbox"
name="neni_chyba_checkbox"
onchange="toggle_corrections('neni_chyba')" checked>
<label for="neni_chyba_checkbox">Není chyba ({{neni_chyba_cnt}})</labe>
<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}})</labe>
<label for="k_zaneseni_checkbox">K zanesení ({{k_zaneseni_cnt}})</label>
<hr/>

4
korektury/templates/korektury/seznam.html

@ -1,6 +1,10 @@
{% extends "korektury/base.html" %}
{% load staticfiles %}
{% block submenu %}
{% include "korektury/submenu.html" %}
{% endblock %}
{% block script%}
<link rel="stylesheet" type="text/css" media="screen, projection" href="{% static "korektury/opraf-list.css" %}" />
{% endblock %}

13
korektury/templates/korektury/submenu.html

@ -0,0 +1,13 @@
{% 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

Binary file not shown.

5125
korektury/testpdfs/B.pdf

File diff suppressed because one or more lines are too long

69
korektury/testutils.py

@ -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/
'''
)

11
korektury/urls.py

@ -1,11 +1,10 @@
from django.urls import path
from django.contrib.auth.decorators import user_passes_test
from seminar.utils import org_required
from . import views
staff_member_required = user_passes_test(lambda u: u.is_staff)
urlpatterns = [
path('korektury/', staff_member_required(views.KorekturyListView.as_view()), name='korektury-list'),
path('korektury/<int:pdf>/', staff_member_required(views.KorekturyView.as_view()), name='korektury'),
path('korektury/help/', staff_member_required(views.KorekturyHelpView.as_view()), name='korektury-help'),
path('korektury/', org_required(views.KorekturyAktualniListView.as_view()), name='korektury-list'),
path('korektury/zastarale/', org_required(views.KorekturyZastaraleListView.as_view()), name='korektury-list'),
path('korektury/<int:pdf>/', org_required(views.KorekturyView.as_view()), name='korektury'),
path('korektury/help/', org_required(views.KorekturyHelpView.as_view()), name='korektury-help'),
]

26
korektury/views.py

@ -29,6 +29,28 @@ class KorekturyListView(generic.ListView):
)
template_name = 'korektury/seznam.html'
class KorekturyAktualniListView(KorekturyListView):
def get_queryset(self, *args, **kwargs):
queryset=super(KorekturyAktualniListView,self).get_queryset()
queryset=queryset.exclude(status="zastarale")
return queryset
def get_context_data(self, **kwargs):
context = super(KorekturyAktualniListView,self).get_context_data(**kwargs)
context['selected'] = 'aktualni'
return context
class KorekturyZastaraleListView(KorekturyListView):
def get_queryset(self, *args, **kwargs):
queryset=super(KorekturyZastaraleListView,self).get_queryset()
queryset=queryset.filter(status="zastarale")
return queryset
def get_context_data(self, **kwargs):
context = super(KorekturyZastaraleListView,self).get_context_data(**kwargs)
context['selected'] = 'zastarale'
return context
### Korektury
class KorekturyView(generic.TemplateView):
model = Oprava
@ -130,7 +152,9 @@ class KorekturyView(generic.TemplateView):
'''
# 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 django.urls import reverse
odkaz = self.request.build_absolute_uri(reverse('korektury', kwargs={'pdf': oprava.pdf.pk}))
from_email = 'korekturovatko@mam.mff.cuni.cz'
subject = 'Nová korektura od {} v {}'.format(autor,
oprava.pdf.nazev)

8
mamweb/settings_common.py

@ -98,7 +98,7 @@ INSTALLED_APPS = (
# Utilities
'sekizai',
# 'reversion',
'reversion',
'django_countries',
'solo',
'ckeditor',
@ -136,7 +136,6 @@ INSTALLED_APPS = (
# 'admin_tools.theming',
# 'admin_tools.menu',
# 'admin_tools.dashboard',
'flat',
'django.contrib.admin',
)
@ -179,7 +178,8 @@ CKEDITOR_CONFIGS = {
# 'toolbar': 'full',
'height': '40em',
'width': '100%',
'toolbarStartupExpanded': False
'toolbarStartupExpanded': False,
'allowedContent' : True,
},
}
@ -248,7 +248,7 @@ LOGGING = {
'class': 'django.utils.log.AdminEmailHandler',
'formatter': 'verbose',
},
'mail_registraion': {
'mail_registration': {
'level': 'WARN',
'class': 'django.utils.log.AdminEmailHandler',
'formatter': 'verbose',

2
mamweb/settings_local.py

@ -94,4 +94,6 @@ LOGGING = {
# set to 'DEBUG' for EXTRA verbose output
# 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

4
mamweb/settings_test.py

@ -12,7 +12,7 @@ import os.path
# Import common settings
from .settings_common import * # zatim nutne, casem snad vyresime # noqa
MIDDLEWARE_CLASSES += (
MIDDLEWARE += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
@ -32,7 +32,7 @@ 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
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases

4
mamweb/static/css/mamweb.css

@ -338,6 +338,10 @@ ul.submenu li>a:hover {
color: black;
}
ul.menu li.active>a, ul.submenu li.active>a {
color: black;
}
/* konec nového menu */
div.novinky_name {

0
mamweb/static/images/logo_co-je-mam.svg → mamweb/static/images/logo_1.svg

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
mamweb/static/images/logo_jak-resit.svg → mamweb/static/images/logo_2.svg

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
mamweb/static/images/logo_aktualni.svg → mamweb/static/images/logo_3.svg

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
mamweb/static/images/logo_soustredeni.svg → mamweb/static/images/logo_4.svg

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
mamweb/static/images/logo_archiv.svg → mamweb/static/images/logo_5.svg

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
mamweb/static/images/logo_profil.svg → mamweb/static/images/logo_6.svg

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

6
mamweb/templates/base.html

@ -12,7 +12,7 @@
<link href="{% static 'css/mamweb.css' %}" rel="stylesheet">
<link href="{% static 'css/prettyPhoto.css' %}" rel="stylesheet" type="text/css" media="screen" charset="utf-8" />
<script src="{% static 'js/jquery-1.11.1.js' %}"></script>
<script src="{% static '/jquery-3.4.1.js' %}"></script>
<script src="{% static 'js/jquery-3.4.1.js' %}"></script>
<link rel="stylesheet" type="text/css" href="{% static 'fluent_comments/css/ajaxcomments.css' %}" />
<script type="text/javascript" src="{% static 'fluent_comments/js/ajaxcomments.js' %}"></script>
@ -57,7 +57,7 @@
<a href='/'>
<div id="title" >M&M - korespondenční seminář a časopis MFF&nbspUK</div>
<div id="header" class="{% if noc %}NOC{% endif %}{% block header %}{% endblock %}">
<img class="logo" src="{% static 'images/logo.svg' %}" />
{% sitetree_menu from "main_menu" include "trunk" template "logo.html" %}
<img class="logo-mobile" src="{% static 'images/logo-mobile.svg' %}" />
</div>
</a>
@ -106,7 +106,7 @@
<div id="footer">
<p class="license">S obsahem webu M&amp;M je možné nakládat dle licence <a href="https://creativecommons.org/licenses/by/3.0/cz/">Creative Commons Attribution 3.0</a>.</p>
</div>
<p class="license-mobile">Korespondenční seminář M&M organizují převážně studenti <a herf="https://www.mff.cuni.cz/">MFF UK</a>. Organizaci semináře a vydávání časopisu podporuje <a href="https://jcmf.cz/">Jednota českých matematiků a fyziků</a>. S obsahem webu M&amp;M je možné nakládat dle licence <a href="https://creativecommons.org/licenses/by/3.0/cz/">Creative Commons Attribution 3.0</a>.</p>
<p class="license-mobile">Korespondenční seminář M&M organizují převážně studenti <a href="https://www.mff.cuni.cz/">MFF UK</a>. Organizaci semináře a vydávání časopisu podporuje <a href="https://jcmf.cz/">Jednota českých matematiků a fyziků</a>. S obsahem webu M&amp;M je možné nakládat dle licence <a href="https://creativecommons.org/licenses/by/3.0/cz/">Creative Commons Attribution 3.0</a>.</p>
</div>
</div>
</div>

26
mamweb/templates/logo.html

@ -0,0 +1,26 @@
{% load staticfiles %}
<img class="logo"
{% for item in sitetree_items %}
{% if item.is_active or item.in_current_branch %}
{% if forloop.counter == 1 %}
src="{% static 'images/logo_1.svg' %}"
{% endif %}
{% if forloop.counter == 2 %}
src="{% static 'images/logo_2.svg' %}"
{% endif %}
{% if forloop.counter == 3 %}
src="{% static 'images/logo_3.svg' %}"
{% endif %}
{% if forloop.counter == 4 %}
src="{% static 'images/logo_4.svg' %}"
{% endif %}
{% if forloop.counter == 5 %}
src="{% static 'images/logo_5.svg' %}"
{% endif %}
{% if forloop.counter == 6 %}
src="{% static 'images/logo_6.svg' %}"
{% endif %}
{% endif %}
{% endfor %}
src="{% static 'images/logo.svg' %}"
/>

4
mamweb/templates/menu.html

@ -3,7 +3,9 @@
{% autoescape off %}
<ul class="menu">
{% for item in sitetree_items %}
<li class="{% if item.has_children %}dropdown{% endif %} {% if item.is_current or item.in_current_branch %}active{% endif %}" >
<li class="{% if item.has_children %}dropdown{% endif %} {% if item.is_current or item.in_current_branch %}active{% endif %}"
style="{% if item.title == "HIDDEN" %}display:none{% endif %}"
>
<a href="{% sitetree_url for item %}" >
{{ item.title_resolved }}
</a>

4
mamweb/templates/menu_mobile.html

@ -3,7 +3,9 @@
{% autoescape off %}
<ul class="menu_mobile">
{% for item in sitetree_items %}
<li class="{% if item.has_children %}dropdown{% endif %} {% if item.is_current or item.in_current_branch %}active{% endif %}">
<li class="{% if item.has_children %}dropdown{% endif %} {% if item.is_current or item.in_current_branch %}active{% endif %}"
style="{% if item.title == "HIDDEN" %}display:none{% endif %}"
>
<a href="{% if item.has_children %}#{% else %}{% sitetree_url for item %}{% endif %}" {% if item.has_children %}class="dropdown-toggle" data-toggle="dropdown"{% endif %}>
{{ item.title_resolved }}
</a>

2
mamweb_prod.ini

@ -5,7 +5,7 @@ chdir = /akce/mam/www/mamweb-prod/
home = /akce/mam/www/mamweb-prod/
module = mamweb.wsgi
plugin = python
plugin = python3
virtualenv = env
master = True
vacuum = True

2
mamweb_test.ini

@ -5,7 +5,7 @@ chdir = /akce/mam/www/mamweb-test/
home = /akce/mam/www/mamweb-test/
module = mamweb.wsgi
plugin = python
plugin = python3
virtualenv = env
master = True
vacuum = True

10
prednasky/templates/prednasky/base.html

@ -17,19 +17,17 @@ Jak moc by ses chtěl(a) zúčastnit následujících přednášek?
<form enctype="multipart/form-data" action="." method="post">
{% csrf_token %}
<table>{{form.as_table}}
</table>
<table>
{% for p in prednasky.prednaska_set.all %}
{% for p, h in prednasky %}
<tr><td><label>{{p.org}}: <span style="font-size: 175%">{{p.nazev}}</span></label></td></tr>
<tr><td><p><i>{{p.anotace}}</i></p></td></tr>
<tr><td><label>Obor: </label> {{p.obor}}</td></tr>
<tr><td><label>Obtížnost: </label> {{p.obtiznost}}</td> </tr>
{% if p.klicova %}<tr><td><label>Klíčová slova: </label> {{p.klicova}}</td></tr>{% endif%}
<tr><td>Hodnocení:
<INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="-1"> rozhodně nechci
<INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="0" checked> je mi to jedno
<INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="1"> rozhodně chci
<INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="-1" {% if h == -1 %} CHECKED="checked" {% endif %} > rozhodně nechci
<INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="0" {% if h == 0 %} CHECKED="checked" {% endif %}> je mi to jedno
<INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="1" {% if h == 1 %} CHECKED="checked" {% endif %}> rozhodně chci
</td></tr>
<tr><td>&nbsp;</td></tr>
{% endfor %}

2
prednasky/templates/prednasky/metaseznam_prednasek.html

@ -19,6 +19,8 @@
<a href="/prednasky/seznam_prednasek/{{seznam.id}}/export">Export</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}

2
prednasky/templates/prednasky/seznam_prednasek.html

@ -15,5 +15,7 @@
{{ prednaska.body }} b</i>) &ndash; {{ prednaska.org }}
</li>
{% endfor %}
</ul>
</div>
{% endblock %}

14
prednasky/templates/prednasky/seznam_prednasek_export.txt

@ -1,19 +1,7 @@
{% block content %}
{% spaceless %}
{% for hlas in hlasovani %}
hlas({{hlas.ucastnik}},{{hlas.prednaska.id}},{{hlas.body}})
{% endfor %}
{% for prednaska in prednasky %}
prednaska({{prednaska.id}},{{prednaska.org.id}},{{prednaska.obtiznost}},{{prednaska.obor}})
{% endfor %}
{% for org in orgove %}
org({{org.id}},4,0,15)
{% endfor %}
{% for org in orgove %}
{{org.id}};{{org}}
{% endfor %}
{% for prednaska in prednasky %}
{{prednaska.id}};{{prednaska.nazev}};{{prednaska.org.id}}
{{prednaska.id}};{{prednaska.nazev}};{{prednaska.org}}
{{prednaska.body}}
{% endfor %}
{% endspaceless %}

27
prednasky/urls.py

@ -1,14 +1,25 @@
from django.urls import path
from django.contrib.auth.decorators import user_passes_test
from seminar.utils import org_required, resitel_required
from . import views
staff_member_required = user_passes_test(lambda u: u.is_staff)
urlpatterns = [
path('prednasky/', views.newPrednaska),
path(
'prednasky/',
resitel_required(views.newPrednaska)
),
path('prednasky/hotovo', views.Prednaska_hotovo),
path('prednasky/metaseznam_prednasek', staff_member_required(views.MetaSeznamListView.as_view()), name='metaseznam-list'),
path('prednasky/seznam_prednasek/<int:seznam>/export', staff_member_required(views.SeznamExportView), name='seznam-export'),
path('prednasky/seznam_prednasek/<int:seznam>/', staff_member_required(views.SeznamListView.as_view()), name='seznam-list'),
# path('korektury/help/', staff_member_required(views.KorekturyHelpView.as_view()), name='korektury-help'),
path(
'prednasky/metaseznam_prednasek',
org_required(views.MetaSeznamListView.as_view()),
name='metaseznam-list'),
path(
'prednasky/seznam_prednasek/<int:seznam>/export',
org_required(views.SeznamExportView),
name='seznam-export'
),
path(
'prednasky/seznam_prednasek/<int:seznam>/',
org_required(views.SeznamListView.as_view()),
name='seznam-list'
),
]

55
prednasky/views.py

@ -4,41 +4,52 @@ from django.views import generic
from django.shortcuts import HttpResponseRedirect
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Sum
from django.forms import Form
from prednasky.models import Prednaska, Hlasovani, Seznam, STAV_NAVRH
from seminar.models import Soustredeni
from prednasky.forms import NewPrednaskyForm
from seminar.models import Soustredeni, Osoba
def newPrednaska(request):
# hlasovani se vztahuje k nejnovejsimu soustredeni
sous = Soustredeni.objects.first()
seznam = Seznam.objects.filter(soustredeni = sous, stav = STAV_NAVRH).first()
print(seznam)
osoba = Osoba.objects.filter(user=request.user).first()
ucastnik = osoba.plne_jmeno() + ' ' + str(osoba.id)
# obsluha formulare
if request.method == 'POST':
form = NewPrednaskyForm(request.POST, request.FILES)
form = Form(request.POST, request.FILES)
if form.is_valid():
jmeno = form.cleaned_data['ucastnik']
# id z důvodu duplicitních jmen (přechod z jména na objekt Osoby nějak kape na tom,
# že všechna předchozí hlasování zde mají náhodný string…)
# TODO Změnit to na Osobu
# TODO v následujících řádcích je zbytečně mnoho dotazů na QuerySet (pokud účastník hlasoval, hlasoval u všech)
for i in request.POST:
if i[0] == 'q':
hlasovani = Hlasovani()
print("q:"+i[1:])
hlasovani.prednaska = Prednaska.objects.filter(pk = int(i[1:]))[0]
prednaska = Prednaska.objects.filter(pk=int(i[1:]))[0]
hlasovani = Hlasovani.objects.filter(ucastnik=ucastnik, prednaska=prednaska).first()
if not hlasovani:
hlasovani = Hlasovani()
hlasovani.prednaska = prednaska
hlasovani.ucastnik = ucastnik
hlasovani.seznam = seznam
hlasovani.body = int(request.POST[i])
hlasovani.ucastnik = jmeno
hlasovani.seznam = seznam
hlasovani.save()
# presmerovani na prave vzniklou galerii
return HttpResponseRedirect('./hotovo')
else:
form = NewPrednaskyForm()
def prednaska_hodnoceni(prednaska):
h = Hlasovani.objects.filter(ucastnik=ucastnik, prednaska=prednaska).first()
if h:
return prednaska, h.body
else:
return prednaska, 0
return render(
request,
'prednasky/base.html',
{'form': form, 'prednasky': seznam}
{'prednasky': map(prednaska_hodnoceni, seznam.prednaska_set.all())}
)
@ -57,12 +68,26 @@ class SeznamListView(generic.ListView):
self.seznam = get_object_or_404(Seznam, id=self.kwargs["seznam"])
prednasky = Prednaska.objects.filter(seznamy=self.seznam).order_by(
'org__user__first_name', 'org__user__last_name'
).annotate(body=Sum('hlasovani__body'))
)
return prednasky
# FIXME nahradit anotaci s filtrem po prechodu na Django 2.2
def get_context_data(self,**kwargs):
context = super(SeznamListView, self).get_context_data(**kwargs)
# hlasovani se vztahuje k nejnovejsimu soustredeni
sous = Soustredeni.objects.first()
seznam = Seznam.objects.filter(soustredeni = sous, stav = STAV_NAVRH).first()
for obj in self.object_list:
hlasovani_set = obj.hlasovani_set.filter(seznam=seznam).only('body')
obj.body = sum(map(lambda x: x.body,hlasovani_set))
return context
def SeznamExportView(request, seznam):
u"""Vypíše výsledky hlasování ve formátu pro prologovský optimalizátor"""
"""Vypíše výsledky hlasování ve formátu pro prologovský optimalizátor"""
# TODO zřejmě se nepoužívá, časem vyřadit? nahradit tabulkou vhodnější pro
# lidi?
hlasovani = Hlasovani.objects.filter(seznam=seznam)

3
seminar/admin.py

@ -3,6 +3,7 @@ from django.contrib import admin
from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter
from reversion.admin import VersionAdmin
from django_reverse_admin import ReverseModelAdmin
from solo.admin import SingletonModelAdmin
# Todo: reversion
@ -160,5 +161,5 @@ class TextNodeAdmin(PolymorphicChildModelAdmin):
show_in_index = True
admin.site.register(m.Nastaveni)
admin.site.register(m.Nastaveni, SingletonModelAdmin)
admin.site.register(m.Novinky)

6
seminar/management/commands/auth.py

@ -1,17 +1,17 @@
# -*- coding: utf-8 -*-
from django.core.management.base import NoArgsCommand
from django.core.management.base import BaseCommand
from django.contrib.sessions.models import Session
from django.contrib.auth.models import User
class Command(NoArgsCommand):
class Command(BaseCommand):
u"""Vypiš username přihlášeného orga s daným session_key.
Příkaz pro manage.py, který ze vstupu přečte session_key (tak, jak je
uložen v cookie sessionid) a pokud session existuje a příslušný přihlášený
uživatel právo přihlásit se do admina, vypíše jeho username.
"""
def handle_noargs(self, **options):
def handle(self, *args, **options):
session_key = raw_input()
s = Session.objects.get(pk=session_key).get_decoded()
user_id = s['_auth_user_id']

21
seminar/migrations/0001_squashed_0067_auto_20190814_0805.py

@ -511,7 +511,7 @@ def vyrob_problemum_ctypes(apps, schema_editor):
class Migration(migrations.Migration):
atomic = False
replaces = [('seminar', '0001_initial'), ('seminar', '0002_add_body_views'), ('seminar', '0003_add_skola_zs_ss'), ('seminar', '0004_add_old_dakos_id'), ('seminar', '0005_alter_problem_autor'), ('seminar', '0006_problem_add_timestamp'), ('seminar', '0007_problem_zamereni'), ('seminar', '0008_reseni_forma'), ('seminar', '0009_rename_imported_IDs'), ('seminar', '0010_alter_rok_maturity'), ('seminar', '0011_alter_timestamp_def'), ('seminar', '0012_remove_soustredeni_ucastnici'), ('seminar', '0013_soustredeni_ucastnici_through_model'), ('seminar', '0014_uprava_poznamek'), ('seminar', '0015_soustredeni_text'), ('seminar', '0016_texty_problemu'), ('seminar', '0017_texty_problemu_minor'), ('seminar', '0018_problemnavrh_problemzadany'), ('seminar', '0019_rocnik_ciselne'), ('seminar', '0020_indexy_a_razeni'), ('seminar', '0021_cislo_verejna_vysledkovka'), ('seminar', '0022_decimal_body'), ('seminar', '0023_add_novinky'), ('seminar', '0024_add_organizator'), ('seminar', '0025_zmena_cesty_nahravani_obrazku'), ('seminar', '0026_soustredeni_typ'), ('seminar', '0027_export_flag_a_typ_akce'), ('seminar', '0028_add_body_celkem_views'), ('seminar', '0029_fix_body_celkem_views'), ('seminar', '0030_add_vysledky'), ('seminar', '0031_cislo_pdf'), ('seminar', '0032_cislo_pdf_blank_typos'), ('seminar', '0033_organizator_studuje_popisek'), ('seminar', '0034_reseni_forma_default_email'), ('seminar', '0035_django_imagekit'), ('seminar', '0036_add_org_to_soustredeni'), ('seminar', '0037_prispevek'), ('seminar', '0038_change_meta_prispevek'), ('seminar', '0039_pohadka'), ('seminar', '0040_pohadka_nepovinny_autor'), ('seminar', '0041_konfery'), ('seminar', '0042_cislo_faze'), ('seminar', '0043_uprava_faze'), ('seminar', '0044_uprava_faze'), ('seminar', '0045_cislo_pridani_faze_nahrano'), ('seminar', '0042_auto_20161005_0847'), ('seminar', '0046_merge'), ('seminar', '0047_auto_20170120_2118'), ('seminar', '0048_add_cislo_datum_deadline_soustredeni'), ('seminar', '0049_auto_20190430_2354'), ('seminar', '0050_auto_20190510_2228'), ('seminar', '0051_resitel_to_osoba'), ('seminar', '0052_user_to_organizator'), ('seminar', '0053_organizator_organizuje_od_do'), ('seminar', '0055_smazat_nemigrovane_zastarale_veci'), ('seminar', '0056_vrcholy_pro_rocniky_a_cisla'), ('seminar', '0057_reseni_to_reseni_hodnoceni'), ('seminar', '0058_problem_to_uloha_tema_clanek'), ('seminar', '0059_vytvorit_pohadkanode'), ('seminar', '0060_spoj_stromy'), ('seminar', '0061_kill_frankenstein'), ('seminar', '0062_redukce_modelu_pohadky'), ('seminar', '0063_procisteni_migraci'), ('seminar', '0064_auto_20190610_2358'), ('seminar', '0065_treenode_polymorphic_ctype'), ('seminar', '0066_problem_polymorphic_ctype'), ('seminar', '0067_auto_20190814_0805')]
replaces = [('seminar', '0001_initial'), ('seminar', '0002_add_body_views'), ('seminar', '0003_add_skola_zs_ss'), ('seminar', '0004_add_old_dakos_id'), ('seminar', '0005_alter_problem_autor'), ('seminar', '0006_problem_add_timestamp'), ('seminar', '0007_problem_zamereni'), ('seminar', '0008_reseni_forma'), ('seminar', '0009_rename_imported_IDs'), ('seminar', '0010_alter_rok_maturity'), ('seminar', '0011_alter_timestamp_def'), ('seminar', '0012_remove_soustredeni_ucastnici'), ('seminar', '0013_soustredeni_ucastnici_through_model'), ('seminar', '0014_uprava_poznamek'), ('seminar', '0015_soustredeni_text'), ('seminar', '0016_texty_problemu'), ('seminar', '0017_texty_problemu_minor'), ('seminar', '0018_problemnavrh_problemzadany'), ('seminar', '0019_rocnik_ciselne'), ('seminar', '0020_indexy_a_razeni'), ('seminar', '0021_cislo_verejna_vysledkovka'), ('seminar', '0022_decimal_body'), ('seminar', '0023_add_novinky'), ('seminar', '0024_add_organizator'), ('seminar', '0025_zmena_cesty_nahravani_obrazku'), ('seminar', '0026_soustredeni_typ'), ('seminar', '0027_export_flag_a_typ_akce'), ('seminar', '0028_add_body_celkem_views'), ('seminar', '0029_fix_body_celkem_views'), ('seminar', '0030_add_vysledky'), ('seminar', '0031_cislo_pdf'), ('seminar', '0032_cislo_pdf_blank_typos'), ('seminar', '0033_organizator_studuje_popisek'), ('seminar', '0034_reseni_forma_default_email'), ('seminar', '0035_django_imagekit'), ('seminar', '0036_add_org_to_soustredeni'), ('seminar', '0037_prispevek'), ('seminar', '0038_change_meta_prispevek'), ('seminar', '0039_pohadka'), ('seminar', '0040_pohadka_nepovinny_autor'), ('seminar', '0041_konfery'), ('seminar', '0042_cislo_faze'), ('seminar', '0043_uprava_faze'), ('seminar', '0044_uprava_faze'), ('seminar', '0045_cislo_pridani_faze_nahrano'), ('seminar', '0042_auto_20161005_0847'), ('seminar', '0046_merge'), ('seminar', '0047_auto_20170120_2118'), ('seminar', '0048_add_cislo_datum_deadline_soustredeni'), ('seminar', '0049_auto_20190430_2354'), ('seminar', '0050_auto_20190510_2228'), ('seminar', '0051_resitel_to_osoba'), ('seminar', '0052_user_to_organizator'), ('seminar', '0053_organizator_organizuje_od_do'), ('seminar', '0055_smazat_nemigrovane_zastarale_veci'), ('seminar', '0056_vrcholy_pro_rocniky_a_cisla'), ('seminar', '0057_reseni_to_reseni_hodnoceni'), ('seminar', '0058_problem_to_uloha_tema_clanek'), ('seminar', 'fix_0058'), ('seminar', '0059_vytvorit_pohadkanode'), ('seminar', '0060_spoj_stromy'), ('seminar', '0061_kill_frankenstein'), ('seminar', '0062_redukce_modelu_pohadky'), ('seminar', '0063_procisteni_migraci'), ('seminar', '0064_auto_20190610_2358'), ('seminar', '0065_treenode_polymorphic_ctype'), ('seminar', '0066_problem_polymorphic_ctype'), ('seminar', '0067_auto_20190814_0805')]
initial = True
@ -877,6 +877,7 @@ class Migration(migrations.Migration):
),
migrations.RunSQL(
sql='update seminar_rocniky set rocnik_n = cast (rocnik as integer)',
reverse_sql='update seminar_rocniky set rocnik_n = cast (rocnik as nvarchar(16))',
),
migrations.RemoveField(
model_name='rocnik',
@ -1733,15 +1734,19 @@ class Migration(migrations.Migration):
# migr 0052
migrations.RunPython(
spoj_k_organizatorum_osoby,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
fix_problem,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
fix_pohadka,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
fix_novinka,
reverse_code=migrations.RunPython.noop,
),
# migr 0053
@ -1795,35 +1800,49 @@ class Migration(migrations.Migration):
# migr 0056
migrations.RunPython(
generuj_RocnikNody_a_CisloNody,
reverse_code=migrations.RunPython.noop,
),
# migr 0057
migrations.RunPython(
reseni_to_Reseni,
reverse_code=migrations.RunPython.noop,
),
# migr 0058
migrations.RunPython(
uloha_to_Uloha,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
tema_to_Tema,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
clanek_to_Clanek,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
konfery_rucne,
reverse_code=migrations.RunPython.noop,
),
# migr "fix 0058"
migrations.RunSQL(
"update seminar_problemy set typ = 'uloha' where typ like 'b_uloha_';",
"update seminar_problemy set typ = 'uloha' where typ like 'b_uloha_';"
),
# migr 0059
migrations.RunPython(
vytvor_pohadkanode,
reverse_code=migrations.RunPython.noop,
),
# migr 0060
migrations.RunPython(
pokacej_les,
reverse_code=migrations.RunPython.noop,
),
migrations.RemoveField(

3
seminar/migrations/0019_rocnik_ciselne.py

@ -18,7 +18,8 @@ class Migration(migrations.Migration):
preserve_default=False,
),
migrations.RunSQL(
sql="update seminar_rocniky set rocnik_n = cast (rocnik as integer)"
sql="update seminar_rocniky set rocnik_n = cast (rocnik as integer)",
reverse_sql='update seminar_rocniky set rocnik_n = cast (rocnik as nvarchar(16))',
),
migrations.RemoveField(
model_name='rocnik',

8
seminar/migrations/0052_user_to_organizator.py

@ -75,8 +75,8 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RunPython(spoj_k_organizatorum_osoby),
migrations.RunPython(fix_problem),
migrations.RunPython(fix_pohadka),
migrations.RunPython(fix_novinka),
migrations.RunPython(spoj_k_organizatorum_osoby, migrations.RunPython.noop),
migrations.RunPython(fix_problem, migrations.RunPython.noop),
migrations.RunPython(fix_pohadka, migrations.RunPython.noop),
migrations.RunPython(fix_novinka, migrations.RunPython.noop),
]

2
seminar/migrations/0056_vrcholy_pro_rocniky_a_cisla.py

@ -43,5 +43,5 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RunPython(generuj_RocnikNody_a_CisloNody),
migrations.RunPython(generuj_RocnikNody_a_CisloNody, migrations.RunPython.noop),
]

2
seminar/migrations/0057_reseni_to_reseni_hodnoceni.py

@ -30,5 +30,5 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RunPython(reseni_to_Reseni)
migrations.RunPython(reseni_to_Reseni, migrations.RunPython.noop)
]

8
seminar/migrations/0058_problem_to_uloha_tema_clanek.py

@ -154,8 +154,8 @@ class Migration(migrations.Migration):
operations = [
# ashes to Ashes, dust to Dust....
migrations.RunPython(uloha_to_Uloha),
migrations.RunPython(tema_to_Tema),
migrations.RunPython(clanek_to_Clanek),
migrations.RunPython(konfery_rucne),
migrations.RunPython(uloha_to_Uloha, migrations.RunPython.noop),
migrations.RunPython(tema_to_Tema, migrations.RunPython.noop),
migrations.RunPython(clanek_to_Clanek, migrations.RunPython.noop),
migrations.RunPython(konfery_rucne, migrations.RunPython.noop),
]

4
seminar/migrations/0059_vytvorit_pohadkanode.py

@ -21,9 +21,9 @@ def vytvor_pohadkanode(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [
('seminar', '0058_problem_to_uloha_tema_clanek'),
('seminar', 'fix_0058'),
]
operations = [
migrations.RunPython(vytvor_pohadkanode),
migrations.RunPython(vytvor_pohadkanode, migrations.RunPython.noop),
]

2
seminar/migrations/0060_spoj_stromy.py

@ -108,5 +108,5 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RunPython(pokacej_les),
migrations.RunPython(pokacej_les, migrations.RunPython.noop),
]

4
seminar/migrations/0065_treenode_polymorphic_ctype.py

@ -5,7 +5,7 @@ import django.db.models.deletion
def vyrob_treenodum_ctypes(apps, schema_editor):
# Kód zkopírovaný z dokumentace: https://django-polymorphic.readthedocs.io/en/stable/migrating.html
# XXX: Nevím, jestli se tohle náhodou nemělo spustit na všech childech (jen/i)
# NOTE: Tahle migrace je špatně, 0087 ji opravuje. Možno squashnout pryč.
TreeNode = apps.get_model('seminar', 'TreeNode')
ContentType = apps.get_model('contenttypes', 'ContentType')
@ -27,5 +27,5 @@ class Migration(migrations.Migration):
name='polymorphic_ctype',
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_seminar.treenode_set+', to='contenttypes.ContentType'),
),
migrations.RunPython(vyrob_treenodum_ctypes, migrations.RunPython.noop),
migrations.RunPython(vyrob_treenodum_ctypes, migrations.RunPython.noop, elidable=True),
]

4
seminar/migrations/0066_problem_polymorphic_ctype.py

@ -5,7 +5,7 @@ import django.db.models.deletion
def vyrob_problemum_ctypes(apps, schema_editor):
# Kód zkopírovaný z dokumentace: https://django-polymorphic.readthedocs.io/en/stable/migrating.html
# XXX: Nevím, jestli se tohle náhodou nemělo spustit na všech childech (jen/i)
# NOTE: Tahle migrace je špatně, 0087 ji opravuje. Možno squashnout pryč.
Problem = apps.get_model('seminar', 'Problem')
ContentType = apps.get_model('contenttypes', 'ContentType')
@ -25,5 +25,5 @@ class Migration(migrations.Migration):
name='polymorphic_ctype',
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_seminar.problem_set+', to='contenttypes.ContentType'),
),
migrations.RunPython(vyrob_problemum_ctypes, migrations.RunPython.noop),
migrations.RunPython(vyrob_problemum_ctypes, migrations.RunPython.noop, elidable=True),
]

2
seminar/migrations/0068_treenode_nazev.py

@ -103,5 +103,5 @@ class Migration(migrations.Migration):
name='nazev',
field=models.TextField(help_text='Tento název se zobrazuje v nabídkách pro výběr vhodného TreeNode', null=True, verbose_name='název tohoto node'),
),
migrations.RunPython(fix_all_names),
migrations.RunPython(fix_all_names, migrations.RunPython.noop),
]

6
seminar/migrations/0080_zruseni_claneknode_a_konferanode.py

@ -65,6 +65,9 @@ class Migration(migrations.Migration):
model_name='reseni',
name='text_zkraceny',
),
migrations.DeleteModel( # nejdříve musím smazat objekt ukazující na konferu,
name='KonferaNode', # pak až změnit klíč konferám (viz další operace)
),
migrations.AddField(
model_name='konfera',
name='problem_ptr',
@ -95,9 +98,6 @@ class Migration(migrations.Migration):
migrations.DeleteModel(
name='ClanekNode',
),
migrations.DeleteModel(
name='KonferaNode',
),
migrations.CreateModel(
name='Konfery_Ucastnici',
fields=[

8
seminar/migrations/0084_clanek_cislo.py

@ -4,6 +4,9 @@ from django.db import migrations, models
import django.db.models.deletion
from seminar.treelib import get_parent
import logging
logger = logging.getLogger(__name__)
def najdi_cislo(apps, schema_editor):
Clanek = apps.get_model('seminar', 'Clanek')
Hodnoceni = apps.get_model('seminar', 'Hodnoceni')
@ -15,7 +18,10 @@ def najdi_cislo(apps, schema_editor):
for c in Clanek.objects.all():
reseni = c.reseni_set
if (reseni.count() != 1): # Pozor, reseni_set je Manager, takže se na něj musí trošku jinak
raise ValueError("Článek k sobě má nejedno řešení!")
logger.warn(f"Více než jedno řešení pro článek {c}")
c.cislo = None
c.save()
continue
r = reseni.first()
aktualniNode = r.text_cely # Hlavní ReseniNode pro řešení
while aktualniNode is not None:

17
seminar/migrations/0086_auto_20200819_0959.py

@ -0,0 +1,17 @@
# Generated by Django 2.2.15 on 2020-08-19 07:59
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('seminar', '0085_nepovinna_prezdivka'),
]
operations = [
migrations.AlterModelOptions(
name='organizator',
options={'ordering': ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni'], 'verbose_name': 'Organizátor', 'verbose_name_plural': 'Organizátoři'},
),
]

49
seminar/migrations/0087_fix_polymorphism.py

@ -0,0 +1,49 @@
# Generated by Django 2.2.16 on 2020-09-04 12:06
from django.db import migrations
from logging import getLogger
log = getLogger(__name__)
# Oprava migrací 0065 a 0066, kde jsem špatně pochopil django-polymorphic
# Pomocná funkce -- děláme to samé pro obě polymorfní hierarchie
def fix_ctypes(parent: str, children, apps, schema_editor):
Parent = apps.get_model('seminar', parent)
ContentType = apps.get_model('contenttypes', 'ContentType')
# Nejdřív všechno smažeme:
Parent.objects.update(polymorphic_ctype=None)
# Opravíme děti
for clsname in children:
Model = apps.get_model('seminar', clsname)
ct = ContentType.objects.get_for_model(Model)
Model.objects.update(polymorphic_ctype=ct)
# Ostatní instance mají mít explicitně content type pro rodiče
new_ct = ContentType.objects.get_for_model(Parent)
for obj in Parent.objects.filter(polymorphic_ctype__isnull=True):
log.warn(f"{parent} \"{obj}\" neměl content type -- nejspíš to je instance přímo {parent}!")
obj.polymorphic_ctype=new_ct
obj.save()
def fix_treenode(apps, schema_editor):
children = ['RocnikNode', 'CisloNode', 'MezicisloNode', 'TemaVCisleNode',
'OrgTextNode', 'UlohaZadaniNode', 'UlohaVzorakNode', 'PohadkaNode',
'TextNode', 'CastNode', 'ReseniNode']
fix_ctypes("TreeNode", children, apps, schema_editor)
def fix_problem(apps, schema_editor):
children = ['Tema', 'Clanek', 'Uloha'] # FIXME: Konfera z nějakého důvodu tenhle field vůbec nemá, asi je to špatně.
fix_ctypes("Problem", children, apps, schema_editor)
class Migration(migrations.Migration):
dependencies = [
('seminar', '0086_auto_20200819_0959'),
]
operations = [
migrations.RunPython(fix_treenode, migrations.RunPython.noop),
migrations.RunPython(fix_problem, migrations.RunPython.noop),
]

35
seminar/migrations/0088_perm_org_a_ucastnik.py

@ -0,0 +1,35 @@
# Generated by Django 2.2.15 on 2020-09-05 10:10
from django.db import migrations
def add_perms(apps, schema_editor):
ContentType = apps.get_model('contenttypes', 'ContentType')
User = apps.get_model('auth', 'User')
Permission = apps.get_model('auth', 'Permission')
Resitel = apps.get_model('seminar', 'Resitel')
c = ContentType.objects.get_for_model(User)
org_perm = Permission.objects.filter(codename__exact='org').first()
if not org_perm:
org_perm = Permission.objects.create(codename='org', name='org', content_type=c)
resitel_perm = Permission.objects.filter(codename__exact='resitel').first()
if not resitel_perm:
resitel_perm = Permission.objects.create(codename='resitel', name='resitel', content_type=c)
for r in Resitel.objects.all():
u = r.osoba.user
if u:
u.user_permissions.add(resitel_perm)
for org in User.objects.all():
if org and org.is_staff:
org.user_permissions.add(org_perm)
class Migration(migrations.Migration):
dependencies = [
('seminar', '0087_fix_polymorphism'),
]
operations = [
migrations.RunPython(add_perms, migrations.RunPython.noop),
]

14
seminar/migrations/fix_0058.py

@ -0,0 +1,14 @@
from django.db import migrations
sql = "update seminar_problemy set typ = 'uloha' where typ like 'b_uloha_';"
class Migration(migrations.Migration):
dependencies = [
('seminar', '0058_problem_to_uloha_tema_clanek'),
]
operations = [
migrations.RunSQL(sql, sql),
]

7
seminar/models.py

@ -582,7 +582,7 @@ class Organizator(SeminarModelBase):
"školu, ale jen obor, možnost zobrazit zvlášť")
def clean(self):
if self.organizuje_od > self.organizuje_do:
if self.organizuje_od and self.organizuje_do and (self.organizuje_od > self.organizuje_do):
raise ValidationError("Organizátor nemůže skončit s organizováním dříve než začal!")
super().clean()
@ -597,6 +597,11 @@ class Organizator(SeminarModelBase):
class Meta:
verbose_name = 'Organizátor'
verbose_name_plural = 'Organizátoři'
# Řadí aktivní orgy na začátek, pod tím v pořadí od nejstarších neaktivní orgy.
# TODO: Chtěl bych spíš mít nejstarší orgy dole.
# TODO: Zohledňovat přezdívky?
# TODO: Sjednotit s tím, jak se řadí organizátoři v seznau orgů na webu
ordering = ['-organizuje_do', 'osoba__jmeno', 'osoba__prijmeni']
@reversion.register(ignore_duplicates=True)
class Soustredeni(SeminarModelBase):

22
seminar/templates/seminar/archiv/cislo.html

@ -18,9 +18,9 @@
<h2>Zadané problémy</h2>
<ul>
{% for p in v_cisle_zadane %}
<li{% if user.is_staff and not cislo.verejne %} class='mam-org-only'{% endif %}>
{% if user.is_staff or cislo.verejne %}
<a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.is_staff or cislo.verejne %}</a>{% endif %}
<li{% if user.je_org and not cislo.verejne %} class='mam-org-only'{% endif %}>
{% if user.je_org or cislo.verejne %}
<a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.je_org or cislo.verejne %}</a>{% endif %}
{% endfor %}
</ul>
{% endif %}
@ -29,14 +29,14 @@
<h2>Řešené problémy</h2>
<ul>
{% for p in resene_problemy %}
<li{% if user.is_staff and not cislo.verejne %} class='mam-org-only'{% endif %}>
{% if user.is_staff or cislo.verejne %}
<a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.is_staff or cislo.verejne %}</a>{% endif %}
<li{% if user.je_org and not cislo.verejne %} class='mam-org-only'{% endif %}>
{% if user.je_org or cislo.verejne %}
<a href='{{ p.verejne_url }}'>{% endif %}{{ p.kod_v_rocniku }} {{ p.nazev }} {{ p.body_v_zavorce }}{% if user.je_org or cislo.verejne %}</a>{% endif %}
{% endfor %}
</ul>
{% endif %}
{% if user.is_staff %}
{% if user.je_org %}
<div class="mam-org-only">
<h2> Orgovské odkazy </h2>
<ul>
@ -52,13 +52,13 @@
<h2>Výsledkovka</h2>
{% else %}
{% if user.is_staff %}
{% if user.je_org %}
<div class='mam-org-only'>
<h2>Výsledkovka (neveřejná)</h2>
{% endif %}
{% endif %}
{% if cislo.verejna_vysledkovka or user.is_staff %}
{% if cislo.verejna_vysledkovka or user.je_org %}
<table class='vysledkovka'>
<tr class='border-b'>
<th class='border-r'>#
@ -66,7 +66,7 @@
{% for p in problemy %}
<th class='border-r'><a href="{{ p.verejne_url }}">{{ p.kod_v_rocniku }}</a>
{% endfor %}
<th class='border-r'>Za číslo</sup>
<th class='border-r'>Za číslo
<th class='border-r'>Za ročník
<th class='border-r'>Odjakživa
{% for rv in radky_vysledkovky %}
@ -88,7 +88,7 @@
</table>
{% endif %}
{% if not cislo.verejna_vysledkovka and user.is_staff %}
{% if not cislo.verejna_vysledkovka and user.je_org %}
</div>
{% endif %}

4
seminar/templates/seminar/archiv/problem.html

@ -3,11 +3,11 @@
{% load comments %}
{% block content %}
<div {% if not problem.verejne and user.is_staff %}class="mam-org-only"{% endif %}>
<div {% if not problem.verejne and user.je_org %}class="mam-org-only"{% endif %}>
{% block problem %}
{% endblock %}
{% if user.is_staff %}
{% if user.je_org %}
<div class='mam-org-only'>
<h2>Text - org</h2>

4
seminar/templates/seminar/archiv/rocnik.html

@ -62,7 +62,7 @@
</div>
{% if vysledkovka %}
{% if user.is_staff %}
{% if user.je_org %}
<div class='mam-org-only'>
<a href='vysledkovka.tex'>Výsledkovka ročníku (LaTeX)</a>
</div>
@ -72,7 +72,7 @@
{% include "seminar/vysledkovka_rocnik.html" %}
{% endif %}
{% if user.is_staff and vysledkovka_s_neverejnymi %}
{% if user.je_org and vysledkovka_s_neverejnymi %}
<div class='mam-org-only'>
<h2>Výsledková listina včetně neveřejných bodů</h2>
{% with radky_vyledkovky_s_neverejnymi as radky_vysledkovky %}

2
seminar/templates/seminar/clanky/resitelske_clanky.html

@ -17,7 +17,7 @@
</h1>
{% for clanek in object_list %}
{% with clanek.cislo_zadani.rocnik.rocnik as rocnik %}
{% with clanek.cislo.rocnik.rocnik as rocnik %}
{% ifchanged rocnik %}
{% if not forloop.first %}</ul>{% endif %}
<h2>{{ rocnik }}. ročník</h2>

10
seminar/templates/seminar/formular_ok.html

@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block nadpis1a %}Formulář byl odeslán{% endblock %}
{% block content %}
<h1> Formulář byl úspěšně odeslán </h1>
{% for odkaz in odkazy %}
<p><a href="{{odkaz.1}}">{{odkaz.0}}</a></p>
{% endfor %}
{% endblock %}

8
seminar/templates/seminar/novinky.html

@ -1,11 +1,13 @@
{% for novinka in object_list %}
{% if not novinka.zverejneno and user.is_staff %}
{# pripravene div-y na stylovani#}
<div>
{% if not novinka.zverejneno and user.je_org %}
<div class="mam-org-only">
<ul>
<li><a href="/admin/seminar/novinky/{{novinka.pk}}">Upravit novinku</a>
</ul>
{% endif %}
{% if novinka.zverejneno or user.is_staff %}
{% if novinka.zverejneno or user.je_org %}
{# datum #}
<div class=novinka_datum>{{novinka.datum}}</div>
{# text #}
@ -31,7 +33,7 @@
{{novinka.autor.osoba.prijmeni}}
</div>
{% endif %}
{% if not novinka.zverejneno and user.is_staff %}
{% if not novinka.zverejneno and user.je_org %}
</div>
{% endif %}
{% endfor%}

87
seminar/templates/seminar/orgorozcestnik.html

@ -0,0 +1,87 @@
{% extends "base.html" %}
{# FIXME: Použít ideálně reverse() ke zjišťování URL #}
{% block content %}
<h2><strong>Informace, komunikace</strong></h2>
<ul>
<li><strong><a href="https://wiki.mam.bezva.org/">wiki</a> </strong>obsahuje různé návody a know-how</li>
<li><strong><a href="https://riot.im/app/#/room/#orgovna:dolujeme.eu">Riot</a> </strong>chatování s dalšími orgy</li>
<li><strong>Kanboard </strong>správa TODO
<ul>
<li><a href="https://kanboard.ledoian.cz/?controller=BoardViewController&amp;action=show&amp;project_id=10">webařský</a></li>
<li>soustředění</li>
</ul>
</li>
<li><a href="/admin/seminar/novinky/add/"><strong>přidat novinku</strong></a> na web</li>
</ul>
<hr />
<h2><strong>Tvorba čísla</strong></h2>
<ul>
<li><a href="/admin/seminar/problemnavrh/add/"><strong>přidat téma</strong></a></li>
<li><strong>korektury</strong>
<ul>
<li><a href="/korektury/">korekturování</a></li>
<li><a href="/admin/korektury/korekturovanepdf/add/">přidat pdf k opravám</a></li>
</ul>
</li>
<li><a href='{{ posledni_cislo_url }}'><strong>poslední vydané číslo </strong></a></li>
</ul>
<hr />
<h2><strong>Moje problémy</strong></h2>
<h3> Témata </h3>
<ul>
{% for t in temata %}
<li> {{ t }} </li>
{% endfor %}
</ul>
<h3> Úlohy </h3>
<ul>
{% for u in ulohy %}
<li> {{ u }} </li>
{% endfor %}
</ul>
<h3> Články </h3>
<ul>
{% for c in clanky %}
<li> {{ c }} </li>
{% endfor %}
</ul>
<hr />
<h2><strong>Soustředění</strong></h2>
<ul>
<li><strong>přednášky</strong>
<ul>
<li><a href="/admin/prednasky/prednaska/">vypisování přednášek</a></li>
<li>hlasování o přednáškách</li>
</ul>
</li>
<li><a href="/soustredeni/probehlo/">proběhlá soustředění</a>
<ul>
<li>vytvoření galerie</li>
<li>stažení seznamu účastníků</li>
<li>obálky</li>
</ul>
</li>
</ul>
<hr />
<h2><strong>Můj profil</strong></h2>
<ul>
<li><a href="http://127.0.0.1:8000/admin/seminar/organizator/{{ organizator.id }}/change/"><strong>upravit </strong></a></li>
</ul>
<hr />
<p>Nemůžeš najít, co hledáš? Může to být v <a href="/admin/">administračním rozhraní webu</a>.</p>
{% endblock content %}

3
seminar/templates/seminar/profil/gdpr.html

@ -36,13 +36,14 @@ Tento souhlas uděluji ze své vlastní a svobodné vůle a beru na vědomí, ž
</p>
<p class="gdpr">
Dále máte právo:
</p>
<ul>
<li>požádat o informaci, jaké osobní údaje jsou o vás zpracovávány,
<li>požadovat opravu osobních údajů, pokud jsou neplatné nebo zastaralé,
<li>požadovat, aby nebyly vaše osobní údaje zpracovávány do doby, než bude vyřešena oprávněnost výše uvedených požadavků,
<li>požadovat, aby byly vaše osobní údaje předány jinému správci,
<li>podat stížnost u dozorového úřadu.
</p>
</ul>
<p class="gdpr">
V případě jakéhokoliv dotazu nebo uplatnění svých práv můžete kontaktovat pověřence pro ochranu osobních údajů na e-mailové adrese gdpr@cuni.cz.
</p>

6
seminar/templates/seminar/profil/nahraj_reseni.html

@ -53,7 +53,7 @@
</td>
<td {% if field.help_text %} class="field-with-comment"{% endif %}>
{{ field }}
<span class="field-comment">{{ field.help_text|safe }}
<span class="field-comment">{{ field.help_text|safe }}</span>>
</td>
<td><span class="field-error">{{ field.errors }}</span></td>
@ -74,7 +74,7 @@
<div id="empty_form" style="display:none">
<div class="attachment">
<table class='form' id="reseni" class='no_error'>
<table class='form no_error' id="reseni">
<tr>
{% for field in prilohy.empty_form.visible_fields %}
@ -86,7 +86,7 @@
</td>
<td {% if field.help_text %} class="field-with-comment"{% endif %}>
{{ field }}
<span class="field-comment">{{ field.help_text|safe }}
<span class="field-comment">{{ field.help_text|safe }}</span>
</td>
<td><span class="field-error">{{ field.errors }}</span></td>

2
seminar/templates/seminar/profil/prihlaska_field.html

@ -8,7 +8,7 @@
</td>
<td {% if field.help_text %} class="field-with-comment"{% endif %}>
{{ field }}
<span class="field-comment">{{ field.help_text|safe }}
<span class="field-comment">{{ field.help_text|safe }}</span>
</td>
</tr>

14
seminar/templates/seminar/soustredeni/seznam_soustredeni.html

@ -12,8 +12,8 @@
{# Projdi vsechna soustredeni #}
{% for soustredeni in object_list %}
{# Kdyz je verejne -> zobraz #}
{% if soustredeni.verejne_db or user.is_staff %}
{% if not soustredeni.verejne_db and user.is_staff %}
{% if soustredeni.verejne_db or user.je_org %}
{% if not soustredeni.verejne_db and user.je_org %}
<div class="mam-org-only">
<!--Groups of user: {{user.groups.all}} <br>-->
{% endif %}
@ -29,8 +29,8 @@
{# Zobrazeni odkazu na galerie #}
{% if soustredeni.galerie_set.all %}
{% for galerie in soustredeni.galerie_set.all %}
{% if galerie.zobrazit == 0 or user.is_staff %}
<li {% if galerie.zobrazit > 0 and user.is_staff %}class="mam-org-only"{% endif %}>
{% if galerie.zobrazit == 0 or user.je_org %}
<li {% if galerie.zobrazit > 0 and user.je_org %}class="mam-org-only"{% endif %}>
<a href="../{{soustredeni.pk}}/fotogalerie/{{galerie.pk}}">Fotogalerie</a>
{# TODO kdyz je titulni obrazek, tak asi i titulni obrazek #}
</li>
@ -38,7 +38,7 @@
{% endfor %}
{% endif %}
</ul>
{% if user.is_staff %}
{% if user.je_org %}
<div class="mam-org-only">
<a href="../{{soustredeni.pk}}/fotogalerie/0/new/">Vytvořit novou fotogalerii</a><br>
<a href="../{{soustredeni.pk}}/obalky.pdf">Vygenerovat obálky pro účastníky</a><br>
@ -55,7 +55,7 @@
{% if soustredeni.text %}
{% autoescape off %}{{soustredeni.text}}{% endautoescape %}
{% endif %}
{% if user.is_staff %}
{% if user.je_org %}
<div class="mam-org-only">
{# Účastníci #}
<h2>Soustředění se zúčastnili tito účastníci:</h2>
@ -77,7 +77,7 @@
</div>
{% endif %}
{% if not soustredeni.verejne_db and user.is_staff %}
{% if not soustredeni.verejne_db and user.je_org %}
</div> {# class="mam-org-only" #}
{% endif %}
{% endif %}

1
seminar/templates/seminar/soustredeni/seznam_ucastniku.html

@ -35,7 +35,6 @@
Žádní účastníci nebyli...
{% endfor %}
</table>
</ul>
</body>
</html>

2
seminar/templates/seminar/titulnistrana.html

@ -10,7 +10,7 @@
{% if dead %}
<div class="odpocet">
<p><b>Do konce <a href="https://mam.mff.cuni.cz/zadani/aktualni/">odeslání řešení</a> {% if deadline_soustredeni %}(pro účast na soustředění) {% endif %}zbývá:<br>
<p><b>Do konce <a href="/zadani/aktualni/">odeslání řešení</a> {% if deadline_soustredeni %}(pro účast na soustředění) {% endif %}zbývá:<br>
<big>{{ted|timesince:dead}}</big></b></p>
</div>
{% endif %}

2
seminar/templates/seminar/treenode.html

@ -1,4 +1,4 @@
{% extends "seminar/archiv/base_ulohy.html" %}
{% extends "seminar/archiv/base.html" %}
{% load comments %}

2
seminar/templates/seminar/zadani/AktualniVysledkovka.html

@ -27,7 +27,7 @@
v&nbsp;<a href="/archiv/cisla/">archivu</a>.
</p>
{% if user.is_staff and vysledkovka_s_neverejnymi %}
{% if user.je_org and vysledkovka_s_neverejnymi %}
<div class='mam-org-only'>
<h1>Výsledky včetně neveřejných</h1>
{% with vysledkovka_s_neverejnymi as vysledkovka %}

55
seminar/templates/seminar/zadani/AktualniZadani.html

@ -16,8 +16,8 @@
{% with nastaveni.aktualni_cislo as ac %}
{# Zobrazovani neverejnych zadani jen organizatorum #}
{% if user.is_staff or verejne %}
{% if user.is_staff and not verejne %}<div class="mam-org-only">{% endif %}
{% if user.je_org or verejne %}
{% if user.je_org and not verejne %}<div class="mam-org-only">{% endif %}
{% if ac.zadane_problemy.all %}
{% if ac.datum_deadline_soustredeni %}
@ -35,34 +35,38 @@
{% if ac.pdf %}
<p><a href="{{ac.pdf.url}}">Aktuální číslo v PDF</a></p>
<h3>Aktuální témata najdete v <a href="{{ac.pdf.url}}">aktuálním čísle v PDF</a>.</h3>
{% endif %}
{% for sada in jednorazove_problemy %}
{# podnadpisy, kdyz neni zakomentuje se nadpis #}
{% if not sada %}<!--{% endif %}
<h2>{% cycle 'Úlohy' 'Seriál' %}</h2>
{% if not sada %}-->{% endif %}
{# publikace jednotlivych zadani #}
{% for problem in sada %}
{% for tag in problem.zamereni.names %}
<a name="zam_{{tag}}"></a>
{% endfor %}
<!--Toto jsem zakomentoval, aby se tam nezobrazovala temata, ale text, že vše najdou pouze v PDF-->
{% if False %}
{% for sada in jednorazove_problemy %}
{# podnadpisy, kdyz neni zakomentuje se nadpis #}
{% if not sada %}<!--{% endif %}
<h2>{% cycle 'Úlohy' 'Seriál' %}</h2>
{% if not sada %}-->{% endif %}
{# publikace jednotlivych zadani #}
{% for problem in sada %}
{% for tag in problem.zamereni.names %}
<a name="zam_{{tag}}"></a>
{% endfor %}
{# TODO použít {{problem.kod_v_rocniku}} ? vrací 4.u1 místo 4.1 #}
<h3>{{problem.cislo_zadani.cislo}}.{{problem.kod}} {{problem.nazev}} {{ problem.body_v_zavorce }}</h3>
{% autoescape off %}{{problem.text_zadani}}{% endautoescape %}
<hr>
{% endfor %}
{% empty %}
Aktuálně nejsou zadané žádné úlohy k řešení.
{% endfor %}
{# TODO použít {{problem.kod_v_rocniku}} ? vrací 4.u1 místo 4.1 #}
<h3>{{problem.cislo_zadani.cislo}}.{{problem.kod}} {{problem.nazev}} {{ problem.body_v_zavorce }}</h3>
{% autoescape off %}{{problem.text_zadani}}{% endautoescape %}
<hr>
{% endfor %}
{% empty %}
Aktuálně nejsou zadané žádné úlohy k řešení.
{% endfor %}
{% endif %}
{% if user.is_staff and not verejne%}</div>{% endif %}
{% if user.je_org and not verejne%}</div>{% endif %}
{% else %}
<h2>Aktuálně nejsou zveřejněny žádné úlohy</h2>
{% endif %}
{% if False %}
<h2>Témata</h2>
<ul>
{% for problem in temata %}
@ -71,9 +75,14 @@
<a href="{{problem.verejne_url}}">Téma {{problem.kod}}: {{problem.nazev}}</a>
</li>
{% empty %}
Aktuálně nejsou zadána žádná témata k řešení.
{% if ac.pdf %}
<p>Aktuální témata najdete v <a href="{{ac.pdf.url}}">aktuálním čísle v PDF</a>.</p>
{% else %}
<p>Aktuálně nemáme žádná témata.</p>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endwith %}

14
seminar/templates/seminar/zadani/Temata.html

@ -16,15 +16,20 @@
{% endblock %}{% endblock %}
</h1>
<h3>
<b> Pozor, tato stránka není aktuální!</b> Aktualizovaný seznam všech čísel v PDF najdete <a href="/rocnik/26/">zde</a>. Za problémy se omlouváme.
</h3>
<p>
Témata jsou hlavním obsahem časopisu M&amp;M. Obvykle představují
složitější a obecnější problémy než samostatné úlohy. Navíc je v&nbsp;jejich
zadání vždy prostor pro tvůrčí rozšíření. Za pěkný článek k&nbsp;tématu lze
získat třeba i 20 bodů, určitě se tedy vyplatí se tématy zabývat.
Témata jsou texty nejen z oblasti matematiky, fyziky a informatiky, které
popisují nějaký problém a jsou doprovázeny návodnými úlohami. Vaším úkolem
je zamyslet se nad daným problémem a sepsat vaše úvahy ve formě krátkého
textu.
</p>
<p>
<a href="/co-je-MaM/jak-resit/">Jak řešit téma?</a>
</p>
<!--
{% if temata %}
<p>
Letos jsme pro tebe připravili tato témata:
@ -72,6 +77,7 @@
{% empty %}
Aktuálně nejsou zadána žádná témata k řešení.
{% endfor %}
-->
</div>
{% endwith %}

55
seminar/testutils.py

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
import datetime
from django.contrib.auth.models import Permission
from pytz import timezone
import random
import lorem
@ -9,6 +11,7 @@ from django.db import transaction
import unidecode
import logging
from korektury.testutils import create_test_pdf
from seminar.models import Skola, Resitel, Rocnik, Cislo, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, Hodnoceni, UlohaZadaniNode, Novinky, TreeNode
import seminar.models as m
@ -70,7 +73,7 @@ def gen_osoby(rnd, size):
if pokusy >= max_pokusy:
print("Chyba, na danou velikost testovacích dat příliš málo možných"
" jmen a příjmení")
exit
exit()
prezdivka = rnd.choice(prezdivky)
email = "@".join([unidecode.unidecode(jmeno), rnd.choice(domain)])
telefon = "".join([str(rnd.choice([k for k in range(10)])) for i in range(9)])
@ -124,9 +127,20 @@ def gen_resitele(rnd, osoby, skoly):
logger.info('Generuji řešitele...')
resitele = []
x = 0
resitel_perm = Permission.objects.filter(codename__exact='resitel').first()
for os in osoby:
rand = rnd.randint(0, 8)
if not (rand % 8 == 0):
if not os.user:
if x:
user = User.objects.create_user(username='r'+str(x), email=os.email, password='r')
else:
user = User.objects.create_user(username='r', email=os.email, password='r')
x += 1
os.user = user
os.save()
os.user.user_permissions.add(resitel_perm)
resitele.append(Resitel.objects.create(osoba=os, skola=rnd.choice(skoly),
rok_maturity=rnd.randint(2019, 2029),
zasilat=rnd.choice(Resitel.ZASILAT_CHOICES)[0]))
@ -139,7 +153,7 @@ def gen_prijemci(rnd, osoby, kolik=10):
prijemci.append(Prijemce.objects.create(osoba=i))
return prijemci
def gen_organizatori(rnd, osoby, last_rocnik, users):
def gen_organizatori(rnd, osoby, last_rocnik):
logger.info('Generuji organizátory...')
organizatori = []
@ -149,6 +163,8 @@ def gen_organizatori(rnd, osoby, last_rocnik, users):
seznam_oboru = ["matematiku", "matematiku", "matematiku", "fyziku", "literaturu",
"informatiku", "informatiku", "běhání dokolečka"]
x = 0
org_perm = Permission.objects.filter(codename__exact='org').first()
for os in osoby:
rand = rnd.randint(0, 8)
if (rand % 8 == 0):
@ -175,6 +191,15 @@ def gen_organizatori(rnd, osoby, last_rocnik, users):
if do.year > datetime.datetime.now().year:
do = None
if not os.user:
if x:
user = User.objects.create_user(username='o'+str(x), email=os.email, password='o')
else:
user = User.objects.create_user(username='o', email=os.email, password='o')
x += 1
os.user = user
os.save()
os.user.user_permissions.add(org_perm)
organizatori.append(Organizator.objects.create(osoba=os,
organizuje_od=od, organizuje_do=do, strucny_popis_organizatora = popis_orga))
return organizatori
@ -681,14 +706,14 @@ def otec_syn(otec, syn):
syn.save()
otec.save()
def gen_clanek(rnd):
def gen_clanek(rnd, organizatori, resitele):
logger.info("Generuji článek do čísla 22.2")
clanek = m.Clanek.objects.create(
nazev="Článek o Lorem ipsum",
nadproblem=None,
stav='vyreseny',
zamereni=['I'],
garant=rnd.choice(m.Organizator.objects.all()),
garant=rnd.choice(organizatori),
kod='cl',
)
clanek.save()
@ -696,7 +721,7 @@ def gen_clanek(rnd):
reseni = m.Reseni.objects.create(
zverejneno=True,
)
reseni.resitele.add(rnd.choice(m.Resitel.objects.all()))
reseni.resitele.add(rnd.choice(resitele))
reseni.save()
cislo = m.Cislo.objects.get(rocnik__rocnik=22, poradi=2)
@ -771,11 +796,22 @@ def create_test_data(size = 6, rnd = None):
# users
admin = User.objects.create_superuser(username='admin', email='', password='admin')
os_admin = Osoba.objects.create(
user=admin, jmeno='admin', prijmeni='admin',
prezdivka='admin', pohlavi_muz=1, email='admin@admin.admin',
telefon='123 456 789', datum_narozeni=datetime.date(2000, 1, 1),
ulice='admin', mesto='admin', psc='100 00',
datum_registrace=datetime.date(2020, 9, 6)
)
or_admin = Organizator.objects.create(
osoba=os_admin, organizuje_od=None, organizuje_do=None,
strucny_popis_organizatora="Organizátor k uživateli Admin"
)
usernames = ['anet', 'bara', 'cyril', 'david', 'eva', 'filip']
users = []
for usr in usernames[:size]:
u = User.objects.create(username=usr, password=usr)
u = User.objects.create_user(username=usr, password=usr)
u.first_name = usr.capitalize()
u.save()
users.append(u)
@ -789,8 +825,8 @@ def create_test_data(size = 6, rnd = None):
# resitele a organizatori
last_rocnik = 25
organizatori = gen_organizatori(rnd, osoby, last_rocnik)
resitele = gen_resitele(rnd, osoby, skoly)
organizatori = gen_organizatori(rnd, osoby, last_rocnik, users)
#generování novinek
novinky = gen_novinky(rnd, organizatori)
@ -830,6 +866,9 @@ def create_test_data(size = 6, rnd = None):
#generování konfer
konfery = gen_konfery(size, rnd, organizatori, resitele, soustredeni)
# vytvoreni pdf ke korekturam
create_test_pdf(rnd, organizatori)
# TODO: nastavi správně, kolik se čeho generuje, aby rozsahy přibližně odpovídaly
# FIXME: misto typu ruzne typy objektu a vnoreni do sebe (Tom nechápe, co je tímto fixme míněno)
# TODO: vytvorit temata s ruznymi vlakny
@ -840,7 +879,7 @@ def create_test_data(size = 6, rnd = None):
# TODO: přidat ke konferám řešení a dát je do čísel
# Dohackované vytvoření jednoho článku
gen_clanek(rnd)
gen_clanek(rnd, organizatori, resitele)
# obecné nastavení semináře, musí být už přidané ročníky a čísla, jinak se nastaví divně

112
seminar/urls.py

@ -1,11 +1,8 @@
from django.urls import path, include
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.decorators import login_required
from . import views, export
from .utils import staff_member_required
from .utils import org_required, resitel_required
from django.views.generic.base import RedirectView
from django.contrib.auth import views as auth_views
staff_member_required = user_passes_test(lambda u: u.is_staff)
urlpatterns = [
# path('aktualni/temata/', views.TemataRozcestnikView),
@ -33,17 +30,17 @@ urlpatterns = [
),
path(
'soustredeni/<int:soustredeni>/seznam_ucastniku',
staff_member_required(views.SoustredeniUcastniciView.as_view()),
org_required(views.SoustredeniUcastniciView.as_view()),
name='soustredeni_ucastnici'
),
path(
'soustredeni/<int:soustredeni>/maily_ucastniku',
staff_member_required(views.SoustredeniMailyUcastnikuView.as_view()),
org_required(views.SoustredeniMailyUcastnikuView.as_view()),
name='maily_ucastniku'
),
path(
'soustredeni/<int:soustredeni>/export_ucastniku',
staff_member_required(views.soustredeniUcastniciExportView),
org_required(views.soustredeniUcastniciExportView),
name='soustredeni_ucastnici_export'
),
path(
@ -62,58 +59,101 @@ urlpatterns = [
#path('clanky/org/', views.ClankyOrganizatorView.as_view(), name='clanky_organizator'),
# Aesop
path('aesop-export/mam-rocnik-<int:prvni_rok>.csv', export.ExportRocnikView.as_view(), name='seminar_export_rocnik'),
path('aesop-export/mam-sous-<str:datum_zacatku>.csv', export.ExportSousView.as_view(), name='seminar_export_sous'),
path('aesop-export/index.csv', export.ExportIndexView.as_view(), name='seminar_export_index'),
path(
'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
org_required(export.ExportRocnikView.as_view()),
name='seminar_export_rocnik'
),
path(
'aesop-export/mam-sous-<str:datum_zacatku>.csv',
org_required(export.ExportSousView.as_view()),
name='seminar_export_sous'
),
path(
'aesop-export/index.csv',
org_required(export.ExportIndexView.as_view()),
name='seminar_export_index'
),
# Stranky viditelne pouze pro orgy:
path(
'rocnik/<int:rocnik>/vysledkovka.tex',
staff_member_required(views.RocnikVysledkovkaView.as_view()),
name='seminar_rocnik_vysledkovka'
'rocnik/<int:rocnik>/vysledkovka.tex',
org_required(views.RocnikVysledkovkaView.as_view()),
name='seminar_rocnik_vysledkovka'
),
path('cislo/<int:rocnik>.<int:cislo>/vysledkovka.tex',
staff_member_required(views.CisloVysledkovkaView.as_view()),
name='seminar_cislo_vysledkovka'
path(
'cislo/<int:rocnik>.<int:cislo>/vysledkovka.tex',
org_required(views.CisloVysledkovkaView.as_view()),
name='seminar_cislo_vysledkovka'
),
path(
'cislo/<int:rocnik>.<int:cislo>/obalky.pdf',
org_required(views.cisloObalkyView),
name='seminar_cislo_obalky'
),
path(
'cislo/<int:rocnik>.<int:cislo>/tituly.tex',
org_required(views.TitulyView),
name='seminar_cislo_titul'
),
path(
'stav',
org_required(views.StavDatabazeView),
name='stav_databaze'
),
path(
'cislo/<int:rocnik>.<int:cislo>/obalkovani',
org_required(views.ObalkovaniView.as_view()),
name='seminar_cislo_resitel_obalkovani'
),
path(
'soustredeni/<int:soustredeni>/obalky.pdf',
org_required(views.soustredeniObalkyView),
name='seminar_soustredeni_obalky'
),
path(
'org/vloz_body/<int:tema>/',
org_required(views.VlozBodyView.as_view()),
name='seminar_org_vlozbody'
),
# příprava na nestatický orgorozcestník
path(
'org/rozcestnik/',
org_required(views.OrgoRozcestnikView.as_view()),
name='seminar_org_rozcestnik'
),
path('cislo/<int:rocnik>.<int:cislo>/obalky.pdf',
staff_member_required(views.cisloObalkyView), name='seminar_cislo_obalky'),
path('cislo/<int:rocnik>.<int:cislo>/tituly.tex',
staff_member_required(views.TitulyView), name='seminar_cislo_titul'),
path('stav',
staff_member_required(views.StavDatabazeView), name='stav_databaze'),
path('cislo/<int:rocnik>.<int:cislo>/obalkovani',
staff_member_required(views.ObalkovaniView.as_view()), name='seminar_cislo_resitel_obalkovani'),
path('soustredeni/<int:soustredeni>/obalky.pdf',
staff_member_required(views.soustredeniObalkyView), name='seminar_soustredeni_obalky'),
path('org/vloz_body/<int:tema>/',
staff_member_required(views.VlozBodyView.as_view()),name='seminar_org_vlozbody'),
path('prihlaska/',views.prihlaskaView, name='seminar_prihlaska'),
path('login/', views.LoginView.as_view(), name='login'),
path('logout/', views.LogoutView.as_view(), name='logout'),
path('resitel/', views.ResitelView.as_view(), name='seminar_resitel'),
path('resitel/', resitel_required(views.ResitelView.as_view()), name='seminar_resitel'),
path('reset_password/', views.PasswordResetView.as_view(), name='reset_password'),
path('change_password/', views.PasswordChangeView.as_view(), name='change_password'),
path('reset_password_done/', views.PasswordResetDoneView.as_view(), name='reset_password_done'),
path('reset_password_confirm/<uidb64>/<token>/', views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('reset_password_complete/', views.PasswordResetCompleteView.as_view(), name='reset_password_complete'),
path('resitel_edit', views.resitelEditView, name='seminar_resitel_edit'),
path(
'resitel_edit',
login_required(views.resitelEditView, login_url='/login/'),
name='seminar_resitel_edit'
),
# Obecný view na profil -- orgům dá rozcestník, řešitelům jejich stránku
path('profil/', views.profilView, name='profil'),
# Autocomplete
path('autocomplete/skola/',views.SkolaAutocomplete.as_view(), name='autocomplete_skola'),
path('autocomplete/resitel/',views.ResitelAutocomplete.as_view(), name='autocomplete_resitel'),
path('autocomplete/resitel/', org_required(views.ResitelAutocomplete.as_view()), name='autocomplete_resitel'),
path('autocomplete/problem/odevzdatelny',views.OdevzdatelnyProblemAutocomplete.as_view(), name='autocomplete_problem_odevzdatelny'),
path('temp/add_solution', views.AddSolutionView.as_view(),name='seminar_vloz_reseni'),
path('temp/nahraj_reseni', views.NahrajReseniView.as_view(),name='seminar_nahraj_reseni'),
path('temp/add_solution', org_required(views.AddSolutionView.as_view()), name='seminar_vloz_reseni'),
path('temp/nahraj_reseni', resitel_required(views.NahrajReseniView.as_view()), name='seminar_nahraj_reseni'),
path('', views.TitulniStranaView.as_view(), name='titulni_strana'),
# Ceka na autocomplete v3
# path('autocomplete/organizatori/',
# staff_member_required(views.OrganizatorAutocomplete.as_view()),
# org_member_required(views.OrganizatorAutocomplete.as_view()),
# name='seminar_autocomplete_organizator')

14
seminar/utils.py

@ -1,15 +1,25 @@
# -*- coding: utf-8 -*-
import datetime
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import permission_required
from html.parser import HTMLParser
from django.contrib.auth.models import AnonymousUser
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
import seminar.models as m
import seminar.treelib as t
staff_member_required = user_passes_test(lambda u: u.is_staff)
org_required = permission_required('auth.org', raise_exception=True)
resitel_required = permission_required('auth.resitel', raise_exception=True)
User = get_user_model()
User.je_org = lambda self: self.has_perm('auth.org')
User.je_resitel = lambda self: self.has_perm('auth.resitel')
AnonymousUser.je_org = lambda self: False
AnonymousUser.je_resitel = lambda self: False
class FirstTagParser(HTMLParser):

2
seminar/views/utils.py

@ -6,8 +6,6 @@ from html.parser import HTMLParser
import seminar.models as m
staff_member_required = user_passes_test(lambda u: u.is_staff)
class FirstTagParser(HTMLParser):
def __init__(self, *args, **kwargs):
self.firstTag = None

224
seminar/views/views_all.py

@ -1,6 +1,6 @@
# coding:utf-8
from django.shortcuts import get_object_or_404, render
from django.shortcuts import get_object_or_404, render, redirect
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, JsonResponse
from django.urls import reverse,reverse_lazy
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
@ -10,9 +10,10 @@ from django.http import Http404,HttpResponseBadRequest,HttpResponseRedirect
from django.db.models import Q, Sum, Count
from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.generic.edit import FormView, CreateView
from django.views.generic.base import TemplateView
from django.contrib.auth import authenticate, login, get_user_model, logout
from django.contrib.auth import views as auth_views
from django.contrib.auth.models import User
from django.contrib.auth.models import User, Permission
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db import transaction
@ -201,7 +202,7 @@ class AktualniZadaniView(TreeNodeView):
# "cisla" : cisla
# })
# return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik})
#
#
#def ZadaniAktualniVysledkovkaView(request):
# nastaveni = get_object_or_404(Nastaveni)
@ -238,8 +239,7 @@ def spravne_novinky(request):
user = request.user
# Využíváme líné vyhodnocování QuerySetů
qs = Novinky.objects.all()
# TODO: Tohle by mělo spíš kontrolovat, že je/není někdo org, než že může do Adminu.
if not user.is_staff:
if not user.je_org:
qs = qs.filter(zverejneno=True)
return qs.order_by('-datum')
@ -644,7 +644,7 @@ class ProblemView(generic.DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Musí se používat context['object'], protože nevíme, jestli dostaneme úložku, téma, článek, .... a tyhle věci vyrábějí různé klíče.
if not context['object'].verejne() and not self.request.user.is_staff:
if not context['object'].verejne() and not self.request.user.je_org:
raise PermissionDenied()
if isinstance(context['object'], Clanek):
context['reseni'] = Reseni.objects.filter(problem=context['object']).select_related('resitel').order_by('resitel__prijmeni')
@ -896,6 +896,43 @@ def oldObalkovaniView(request, rocnik, cislo):
{'cislo': cislo, 'problemy': problemy, 'reseni': reseni}
)
### Orgostránky
class OrgoRozcestnikView(TemplateView):
''' Zobrazí organizátorský rozcestník.'''
template_name = 'seminar/orgorozcestnik.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['posledni_soustredeni'] = Soustredeni.objects.order_by('-datum_konce').first()
nastaveni = Nastaveni.objects.first()
aktualni_rocnik = nastaveni.aktualni_rocnik
context['posledni_cislo_url'] = nastaveni.aktualni_cislo.verejne_url()
# TODO možná chceme odkazovat na právě rozpracované číslo, a ne to poslední vydané
# pokud nechceme haluzit kód (= poradi) dalšího čísla, bude asi potřeba jít
# přes treenody (a dát si přitom pozor na MezicisloNode)
u = self.request.user
os = s.Osoba.objects.get(user=u)
organizator = s.Organizator.objects.get(osoba=os)
temata_garant = s.Tema.objects.filter(garant=organizator,
rocnik=aktualni_rocnik)
#FIXME: přidat opravovatel, stav='STAV_ZADANY'
ulohy_garant = s.Uloha.objects.filter(garant=organizator,
cislo_zadani__rocnik=aktualni_rocnik)
clanky_garant = s.Clanek.objects.filter(garant=organizator,
cislo__rocnik=aktualni_rocnik)
context['temata'] = temata_garant
context['ulohy'] = ulohy_garant
context['clanky'] = clanky_garant
context['organizator'] = organizator
return context
#content_type = 'text/plain; charset=UTF8'
#XXX
### Tituly
def TitulyView(request, rocnik, cislo):
@ -974,12 +1011,44 @@ def soustredeniUcastniciExportView(request,soustredeni):
### Články
def group_by_rocnik(clanky):
''' Vezme zadaný seznam článků a seskupí je podle ročníku.
Vrátí seznam seznamů článků ze stejného ročníku.'''
if len(clanky) == 0:
return clanky
clanky.order_by('cislo__rocnik__rocnik')
skupiny_clanku = []
skupina = []
rocnik = clanky.first().cislo.rocnik.rocnik # první ročník
for clanek in clanky:
if clanek.cislo.rocnik.rocnik == rocnik:
skupina.append(clanek)
else:
skupiny_clanku.append(skupina)
skupina = []
skupina.append(clanek)
rocnik = clanek.cislo.rocnik.rocnik
skupiny_clanku.append(skupina)
return skupiny_clanku
# FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi
# FIXME: Původně tu byl kód přímo v těle třídy, což rozbíjelo migrace. Opravil jsem, ale vůbec nevím, jestli to funguje.
class ClankyResitelView(generic.ListView):
model = Problem
template_name = 'seminar/clanky/resitelske_clanky.html'
queryset = Clanek.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')
# FIXME: QuerySet není pole!
def get_queryset(self):
clanky = Clanek.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo__rocnik').order_by('-cislo__rocnik__rocnik')
queryset = []
skupiny_clanku = group_by_rocnik(clanky)
for skupina in skupiny_clanku:
skupina.sort(key=lambda clanek: clanek.kod_v_rocniku())
for clanek in skupina:
queryset.append(clanek)
return queryset
# FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit
#class ClankyOrganizatorView(generic.ListView)<F12>:
@ -1088,63 +1157,63 @@ def logoutView(request):
def prihlaska_log_gdpr_safe(logger, gdpr_logger, msg, form_data):
msg = "{}, form_hash:{}".format(msg,hash(form_data))
msg = "{}, form_hash:{}".format(msg,hash(frozenset(form_data.items)))
logger.warn(msg)
gdpr_logger.warn(msg+", form:{}".format(form_data))
from django.forms.models import model_to_dict
def resitelEditView(request):
err_logger = logging.getLogger('seminar.prihlaska.problem')
## Načtení objektu Osoba a Resitel, patrici k aktuálně přihlášenému uživately
u = request.user
osoba_edit = Osoba.objects.get(user=u)
resitel_edit = osoba_edit.resitel
user_edit = osoba_edit.user
## Vytvoření slovníku, kterým předvyplním formulář
prefill_1=model_to_dict(user_edit)
prefill_2=model_to_dict(resitel_edit)
prefill_3=model_to_dict(osoba_edit)
prefill_1.update(prefill_2)
prefill_1.update(prefill_3)
form = ProfileEditForm(initial=prefill_1)
## Změna údajů a jejich uložení
if request.method == 'POST':
form = ProfileEditForm(request.POST)
if form.is_valid():
## Změny v osobě
fcd = form.cleaned_data
osoba_edit.jmeno = fcd['jmeno']
osoba_edit.prijmeni = fcd['prijmeni']
osoba_edit.pohlavi_muz = fcd['pohlavi_muz']
osoba_edit.email = fcd['email']
osoba_edit.telefon = fcd['telefon']
osoba_edit.ulice = fcd['ulice']
osoba_edit.mesto = fcd['mesto']
osoba_edit.psc = fcd['psc']
## Změny v osobě s podmínkami
if fcd.get('spam',False):
osoba_edit.datum_souhlasu_zasilani = date.today()
if fcd.get('stat','') in ('CZ','SK'):
osoba_edit.stat = fcd['stat']
else:
## Neznámá země
msg = "Unknown country {}".format(fcd['stat_text'])
## Změny v řešiteli
resitel_edit.skola = fcd['skola']
resitel_edit.rok_maturity = fcd['rok_maturity']
resitel_edit.zasilat = fcd['zasilat']
if fcd.get('skola'):
resitel_edit.skola = fcd['skola']
else:
# Unknown school - log it
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa'])
resitel_edit.save()
osoba_edit.save()
return HttpResponseRedirect('/thanks/')
else:
## Stránka před odeslaním formuláře = předvyplněný formulář
return render(request, 'seminar/profil/edit.html', {'form': form})
err_logger = logging.getLogger('seminar.prihlaska.problem')
## Načtení objektu Osoba a Resitel, patrici k aktuálně přihlášenému uživately
u = request.user
osoba_edit = Osoba.objects.get(user=u)
resitel_edit = osoba_edit.resitel
user_edit = osoba_edit.user
## Vytvoření slovníku, kterým předvyplním formulář
prefill_1=model_to_dict(user_edit)
prefill_2=model_to_dict(resitel_edit)
prefill_3=model_to_dict(osoba_edit)
prefill_1.update(prefill_2)
prefill_1.update(prefill_3)
form = ProfileEditForm(initial=prefill_1)
## Změna údajů a jejich uložení
if request.method == 'POST':
form = ProfileEditForm(request.POST)
if form.is_valid():
## Změny v osobě
fcd = form.cleaned_data
osoba_edit.jmeno = fcd['jmeno']
osoba_edit.prijmeni = fcd['prijmeni']
osoba_edit.pohlavi_muz = fcd['pohlavi_muz']
osoba_edit.email = fcd['email']
osoba_edit.telefon = fcd['telefon']
osoba_edit.ulice = fcd['ulice']
osoba_edit.mesto = fcd['mesto']
osoba_edit.psc = fcd['psc']
## Změny v osobě s podmínkami
if fcd.get('spam',False):
osoba_edit.datum_souhlasu_zasilani = date.today()
if fcd.get('stat','') in ('CZ','SK'):
osoba_edit.stat = fcd['stat']
else:
## Neznámá země
msg = "Unknown country {}".format(fcd['stat_text'])
## Změny v řešiteli
resitel_edit.skola = fcd['skola']
resitel_edit.rok_maturity = fcd['rok_maturity']
resitel_edit.zasilat = fcd['zasilat']
if fcd.get('skola'):
resitel_edit.skola = fcd['skola']
else:
# Unknown school - log it
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa'])
resitel_edit.save()
osoba_edit.save()
return formularOKView(request)
else:
## Stránka před odeslaním formuláře = předvyplněný formulář
return render(request, 'seminar/profil/edit.html', {'form': form})
def prihlaskaView(request):
generic_logger = logging.getLogger('seminar.prihlaska')
@ -1156,8 +1225,8 @@ def prihlaskaView(request):
if form.is_valid():
generic_logger.info("Form valid")
fcd = form.cleaned_data
form_hash = hash(fcd)
form_logger.info(fcd,form_hash=form_hash)
form_hash = hash(frozenset(fcd.items()))
form_logger.info(str(fcd) + str(form_hash)) # TODO možná logovat jinak
with transaction.atomic():
u = User.objects.create_user(
@ -1165,6 +1234,8 @@ def prihlaskaView(request):
password=fcd['password'],
email = fcd['email'])
u.save()
resitel_perm = Permission.objects.filter(codename__exact='resitel').first()
u.user_permissions.add(resitel_perm)
o = Osoba(
jmeno = fcd['jmeno'],
@ -1187,7 +1258,7 @@ def prihlaskaView(request):
else:
# Unknown country - log it
msg = "Unknown country {}".format(fcd['stat_text'])
err_logger.warn(msg,form_hash=form_hash)
err_logger.warn(msg + str(form_hash))
o.save()
o.user = u
@ -1205,11 +1276,11 @@ def prihlaskaView(request):
else:
# Unknown school - log it
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa'])
err_logger.warn(msg,form_hash=form_hash)
err_logger.warn(msg + str(form_hash))
r.save()
return HttpResponseRedirect('/thanks/')
return formularOKView(request)
# if a GET (or any other method) we'll create a blank form
else:
@ -1259,3 +1330,28 @@ class PasswordResetCompleteView(auth_views.PasswordResetCompleteView):
class PasswordChangeView(auth_views.PasswordChangeView):
#template_name = 'seminar/password_change.html'
success_url = reverse_lazy('titulni_strana')
# Jen hloupé rozhazovátko
def profilView(request):
user = request.user
if user.has_perm('auth.org'):
return OrgoRozcestnikView.as_view()(request)
if user.has_perm('auth.resitel'):
return ResitelView.as_view()(request)
else:
return LoginView.as_view()(request)
# Interní, nemá se nikdy objevit v urls (jinak to účastníci vytrolí)
def formularOKView(request):
template_name = 'seminar/formular_ok.html'
odkazy = [
# (Text, odkaz)
('Vrátit se na titulní stránku', reverse('titulni_strana')),
('Zobrazit aktuální zadání', reverse('seminar_aktualni_zadani')),
]
context = {
'odkazy': odkazy,
}
return render(request, template_name, context)

661
sitetree_new.json

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save