Browse Source

Merge branch 'data_migrations' into odevzdavatko

export_seznamu_prednasek
Pavel "LEdoian" Turinsky 4 years ago
parent
commit
e5553126bc
  1. 6
      .gitignore
  2. 2
      data/flat.json
  3. 207
      data/fotka_header.json
  4. 1
      data/sitetree_new.json
  5. 6
      galerie/templates/galerie/Base.html
  6. 2
      galerie/templates/galerie/Galerie.html
  7. 6
      galerie/templates/galerie/GalerieNahled.html
  8. 2
      galerie/templates/galerie/GalerieNew.html
  9. 7
      galerie/urls.py
  10. 6
      galerie/views.py
  11. 0
      header_fotky/__init__.py
  12. 10
      header_fotky/admin.py
  13. 5
      header_fotky/apps.py
  14. 45
      header_fotky/context_processors.py
  15. 63
      header_fotky/migrations/0001_initial.py
  16. 0
      header_fotky/migrations/__init__.py
  17. 65
      header_fotky/models.py
  18. 4
      korektury/models.py
  19. 13
      korektury/templates/korektury/base.html
  20. 8
      korektury/templates/korektury/help.html
  21. 4
      korektury/templates/korektury/opraf.html
  22. 6
      korektury/templates/korektury/seznam.html
  23. 13
      korektury/templates/korektury/submenu.html
  24. BIN
      korektury/testpdfs/A.pdf
  25. 5125
      korektury/testpdfs/B.pdf
  26. 69
      korektury/testutils.py
  27. 12
      korektury/urls.py
  28. 4
      mamweb/admin.py
  29. 12
      mamweb/context_processors.py
  30. 3
      mamweb/settings_common.py
  31. 315
      mamweb/static/css/mamweb.css
  32. 26847
      mamweb/static/images/jakresit_1.svg
  33. 26847
      mamweb/static/images/jakresit_2.svg
  34. 26847
      mamweb/static/images/jakresit_3.svg
  35. 0
      mamweb/static/images/logo_1.svg
  36. 0
      mamweb/static/images/logo_2.svg
  37. 0
      mamweb/static/images/logo_3.svg
  38. 0
      mamweb/static/images/logo_4.svg
  39. 0
      mamweb/static/images/logo_5.svg
  40. 0
      mamweb/static/images/logo_6.svg
  41. 22
      mamweb/templates/base.html
  42. 104
      mamweb/templates/flatpages/default.html
  43. 26
      mamweb/templates/logo.html
  44. 4
      mamweb/templates/menu.html
  45. 4
      mamweb/templates/menu_mobile.html
  46. 10
      prednasky/templates/prednasky/base.html
  47. 6
      prednasky/templates/prednasky/metaseznam_prednasek.html
  48. 6
      prednasky/templates/prednasky/seznam_prednasek.html
  49. 27
      prednasky/urls.py
  50. 37
      prednasky/views.py
  51. 13
      seminar/migrations/0001_squashed_0067_auto_20190814_0805.py
  52. 3
      seminar/migrations/0019_rocnik_ciselne.py
  53. 8
      seminar/migrations/0052_user_to_organizator.py
  54. 2
      seminar/migrations/0056_vrcholy_pro_rocniky_a_cisla.py
  55. 2
      seminar/migrations/0057_reseni_to_reseni_hodnoceni.py
  56. 8
      seminar/migrations/0058_problem_to_uloha_tema_clanek.py
  57. 2
      seminar/migrations/0059_vytvorit_pohadkanode.py
  58. 2
      seminar/migrations/0060_spoj_stromy.py
  59. 2
      seminar/migrations/0068_treenode_nazev.py
  60. 6
      seminar/migrations/0080_zruseni_claneknode_a_konferanode.py
  61. 35
      seminar/migrations/0088_perm_org_a_ucastnik.py
  62. 18
      seminar/migrations/0089_cislo_datum_preddeadline.py
  63. 4
      seminar/models.py
  64. 6
      seminar/templates/seminar/archiv/base.html
  65. 8
      seminar/templates/seminar/archiv/cisla.html
  66. 24
      seminar/templates/seminar/archiv/cislo.html
  67. 2
      seminar/templates/seminar/archiv/cislo_obalkovani.html
  68. 2
      seminar/templates/seminar/archiv/prispevek.html
  69. 6
      seminar/templates/seminar/archiv/problem.html
  70. 6
      seminar/templates/seminar/archiv/rocnik.html
  71. 2
      seminar/templates/seminar/archiv/temata.html
  72. 10
      seminar/templates/seminar/clanky/base.html
  73. 6
      seminar/templates/seminar/clanky/organizatorske_clanky.html
  74. 8
      seminar/templates/seminar/clanky/resitelske_clanky.html
  75. 6
      seminar/templates/seminar/cojemam/base.html
  76. 11
      seminar/templates/seminar/cojemam/organizatori.html
  77. 16
      seminar/templates/seminar/jak-resit.html
  78. 18
      seminar/templates/seminar/novinky.html
  79. 2
      seminar/templates/seminar/profil/edit.html
  80. 3
      seminar/templates/seminar/profil/gdpr.html
  81. 2
      seminar/templates/seminar/profil/login.html
  82. 2
      seminar/templates/seminar/profil/logout.html
  83. 8
      seminar/templates/seminar/profil/nahraj_reseni.html
  84. 2
      seminar/templates/seminar/profil/prihlaska.html
  85. 2
      seminar/templates/seminar/profil/prihlaska_field.html
  86. 2
      seminar/templates/seminar/profil/resitel.html
  87. 6
      seminar/templates/seminar/soustredeni/base.html
  88. 23
      seminar/templates/seminar/soustredeni/seznam_soustredeni.html
  89. 1
      seminar/templates/seminar/soustredeni/seznam_ucastniku.html
  90. 77
      seminar/templates/seminar/titulnistrana.html
  91. 2
      seminar/templates/seminar/treenode.html
  92. 11
      seminar/templates/seminar/zadani/AktualniVysledkovka.html
  93. 14
      seminar/templates/seminar/zadani/AktualniZadani.html
  94. 9
      seminar/templates/seminar/zadani/Temata.html
  95. 10
      seminar/templates/seminar/zadani/base.html
  96. 55
      seminar/testutils.py
  97. 115
      seminar/urls.py
  98. 14
      seminar/utils.py
  99. 2
      seminar/views/utils.py
  100. 113
      seminar/views/views_all.py

6
.gitignore

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

2
flat.json → data/flat.json

@ -260,7 +260,7 @@
"fields": { "fields": {
"url": "/co-je-MaM/kontakt/", "url": "/co-je-MaM/kontakt/",
"title": "Kontakt", "title": "Kontakt",
"content": "<p>Sv\u00e1 \u0159e\u0161en\u00ed \u010di p\u0159\u00edpadn\u00e9 dotazy n\u00e1m m\u016f\u017eete&nbsp;pos\u00edlat bu\u010f klasickou, nebo elektronickou po\u0161tou:</p>\r\n\r\n<table align=\"left\" border=\"0\" cellpadding=\"1\" cellspacing=\"1\" style=\"width:100%\">\r\n\t<tbody>\r\n\t\t<tr>\r\n\t\t\t<td>\r\n\t\t\t<p><strong>Adresa redakce</strong>:</p>\r\n\r\n\t\t\t<p>M&amp;M, OPMK MFF UK<br />\r\n\t\t\tKe Karlovu 3<br />\r\n\t\t\t121&nbsp;16 Praha&nbsp;2</p>\r\n\t\t\t</td>\r\n\t\t\t<td>\r\n\t\t\t<p><strong>E-mail</strong>:&nbsp;<a href=\"mailto:mam@matfyz.cz\" style=\"color: rgb(133, 49, 1); line-height: 20.8px;\">mam@matfyz.cz</a></p>\r\n\r\n\t\t\t<p><strong>Facebook:</strong>&nbsp;<a href=\"https://www.facebook.com/casopis.MaM?fref=ts\">Koresponden\u010dn\u00ed semin\u00e1\u0159 M&amp;M</a></p>\r\n\r\n\t\t\t<p><strong>Google Kalend\u00e1\u0159:</strong>&nbsp;<a href=\"https://calendar.google.com/calendar/embed?src=casopis.mam%40gmail.com&amp;ctz=Europe%2FPrague\">casopis.mam@gmail.com</a></p>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t</tbody>\r\n</table>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>B\u011bhem \u0161koln\u00edho roku je velk\u00e1 \u010d\u00e1st <a href=\"/co-je-MaM/organizatori/\"><strong>organiz\u00e1tor\u016f</strong></a> k zasti\u017een\u00ed na koleji 17. listopadu \u010di jinde po Praze.</p>\r\n\r\n<p><strong>Adresa koleje:</strong></p>\r\n\r\n<p>P\u00e1tkova 3<br />\r\n182 00, Praha 8</p>", "content": "<p>Sv\u00e1 \u0159e\u0161en\u00ed \u010di p\u0159\u00edpadn\u00e9 dotazy n\u00e1m m\u016f\u017eete&nbsp;pos\u00edlat bu\u010f klasickou, nebo elektronickou po\u0161tou:</p>\r\n\r\n<p><strong>Adresa redakce</strong>:</p>\r\n\r\n<p>M&amp;M, OPMK MFF UK<br />\r\nKe Karlovu 3<br />\r\n121&nbsp;16 Praha&nbsp;2</p>\r\n\r\n<p><strong>E-mail</strong>:<a href=\"mailto:mam@matfyz.cz\" style=\"color: rgb(133, 49, 1); line-height: 20.8px;\"> mam@matfyz.cz</a></p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p><strong>Facebook:</strong>&nbsp;<a href=\"https://www.facebook.com/casopis.MaM?fref=ts\">Koresponden\u010dn\u00ed semin\u00e1\u0159 M&amp;M</a></p>\r\n\r\n<p><strong>Google Kalend\u00e1\u0159:</strong>&nbsp;<a href=\"https://calendar.google.com/calendar/embed?src=casopis.mam%40gmail.com&amp;ctz=Europe%2FPrague\">casopis.mam@gmail.com</a></p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>B\u011bhem \u0161koln\u00edho roku je velk\u00e1 \u010d\u00e1st <a href=\"/co-je-MaM/organizatori/\"><strong>organiz\u00e1tor\u016f</strong></a> k zasti\u017een\u00ed na koleji 17. listopadu \u010di jinde po Praze.</p>\r\n\r\n<p><strong>Adresa koleje:</strong></p>\r\n\r\n<p>P\u00e1tkova 3<br />\r\n182 00, Praha 8</p>",
"enable_comments": false, "enable_comments": false,
"template_name": "", "template_name": "",
"registration_required": false, "registration_required": false,

207
data/fotka_header.json

@ -0,0 +1,207 @@
[
{
"model": "header_fotky.fotkaheader",
"pk": "baliky.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/baliky.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "beh.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/beh.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "kryptografie.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/kryptografie.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "mam_cernobile.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/mam_cernobile.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "noc.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/noc.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "ohen.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/ohen.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "snih.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/snih.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "spolecna.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/spolecna.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "stiny.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/stiny.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "vikendovka.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/vikendovka.jpg"
}
},
{
"model": "header_fotky.fotkaheader",
"pk": "vylet.jpg",
"fields": {
"cas": "2020-09-20T09:18:34.562Z",
"fotka": "header/vylet.jpg"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 1,
"fields": {
"url": "/archiv/",
"fotka": "stiny.jpg",
"denni_doba": "oboji"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 2,
"fields": {
"url": "/clanky/",
"fotka": "kryptografie.jpg",
"denni_doba": "den"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 3,
"fields": {
"url": "/clanky/",
"fotka": "ohen.jpg",
"denni_doba": "noc"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 4,
"fields": {
"url": "/zadani/",
"fotka": "baliky.jpg",
"denni_doba": "den"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 5,
"fields": {
"url": "/zadani/",
"fotka": "stiny.jpg",
"denni_doba": "noc"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 6,
"fields": {
"url": "/co-je-MaM/",
"fotka": "vikendovka.jpg",
"denni_doba": "den"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 7,
"fields": {
"url": "/co-je-MaM/",
"fotka": "noc.jpg",
"denni_doba": "noc"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 8,
"fields": {
"url": "/soustredeni/",
"fotka": "beh.jpg",
"denni_doba": "den"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 9,
"fields": {
"url": "/soustredeni/",
"fotka": "vylet.jpg",
"denni_doba": "noc"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 10,
"fields": {
"url": "/login/",
"fotka": "baliky.jpg",
"denni_doba": "den"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 11,
"fields": {
"url": "/login/",
"fotka": "stiny.jpg",
"denni_doba": "noc"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 12,
"fields": {
"url": "/profil/",
"fotka": "baliky.jpg",
"denni_doba": "den"
}
},
{
"model": "header_fotky.fotkaurlvazba",
"pk": 13,
"fields": {
"url": "/profil/",
"fotka": "stiny.jpg",
"denni_doba": "noc"
}
}
]

1
data/sitetree_new.json

File diff suppressed because one or more lines are too long

6
galerie/templates/galerie/Base.html

@ -1,6 +0,0 @@
{% extends "base.html" %}
{# TODO predelat pres context processor #}
{% block header %}soustredeni{% endblock %}
{% block menu_soustredeni %}selected{% endblock %}
{% block submenu %}{% include 'seminar/soustredeni/submenu.html' %}{% endblock %}

2
galerie/templates/galerie/Galerie.html

@ -1,4 +1,4 @@
{% extends "galerie/Base.html" %} {% extends "base.html" %}
{% block nadpis1a %} {% block nadpis1a %}

6
galerie/templates/galerie/GalerieNahled.html

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

2
galerie/templates/galerie/GalerieNew.html

@ -1,4 +1,4 @@
{% extends "galerie/Base.html" %} {% extends "base.html" %}
{% block title %}{% block nadpis1a %} {% block title %}{% block nadpis1a %}
Vytvářím novou galerii Vytvářím novou galerii

7
galerie/urls.py

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

6
galerie/views.py

@ -14,7 +14,7 @@ from galerie.forms import KomentarForm, NewGalerieForm
def zobrazit(galerie, request): def zobrazit(galerie, request):
preview = False preview = False
if galerie.zobrazit >= 1: if galerie.zobrazit >= 1:
if request.user.is_staff: if request.user.je_org:
preview = True; preview = True;
else: else:
raise Http404 raise Http404
@ -35,7 +35,7 @@ def nahled(request, pk, soustredeni):
galerie = get_object_or_404(Galerie, pk=pk) galerie = get_object_or_404(Galerie, pk=pk)
podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi') podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi')
if not request.user.is_staff: if not request.user.je_org:
podgalerie = podgalerie.filter(zobrazit__lt=1) podgalerie = podgalerie.filter(zobrazit__lt=1)
obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev') obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev')
@ -44,7 +44,7 @@ def nahled(request, pk, soustredeni):
sourozenci = [] sourozenci = []
if galerie.galerie_up: if galerie.galerie_up:
sourozenci = galerie.galerie_up.galerie_set.all().order_by('poradi') sourozenci = galerie.galerie_up.galerie_set.all().order_by('poradi')
if not request.user.is_staff: if not request.user.je_org:
sourozenci = sourozenci.filter(zobrazit__lt=1) sourozenci = sourozenci.filter(zobrazit__lt=1)
predchozi = None predchozi = None

0
header_fotky/__init__.py

10
header_fotky/admin.py

@ -0,0 +1,10 @@
from django.contrib import admin
from django.contrib.admin import ModelAdmin
import header_fotky.models as m
class FotkaPozadiAdmin(ModelAdmin):
readonly_fields = ['cas']
admin.site.register(m.FotkaHeader, FotkaPozadiAdmin)
admin.site.register(m.FotkaUrlVazba)

5
header_fotky/apps.py

@ -0,0 +1,5 @@
from django.apps import AppConfig
class HeaderFotkyConfig(AppConfig):
name = 'header_fotky'

45
header_fotky/context_processors.py

@ -0,0 +1,45 @@
from datetime import datetime, date
import random
from django.conf import settings
from header_fotky.models import FotkaUrlVazba
def vzhled(request):
''' Podle casu prida do templatu, zdali je nebo neni noc '''
hodin = datetime.now().hour
if (hodin <= 6) or (hodin >= 20):
noc = True
nedoba = 'den'
doba = 'noc'
else:
noc = False
nedoba = 'noc'
doba = 'den'
url = request.path
fotky = FotkaUrlVazba.objects.exclude(denni_doba=nedoba)
fotka = None
# TODO rychlejší patternmatch?
while (fotka is None) and (url != ''):
presne = fotky.filter(url__exact=url)
if presne.count() > 0:
presne_doba = presne.filter(denni_doba=doba)
if presne_doba.count() > 0:
fotka = random.choice(presne_doba).url_fotky()
else:
fotka = random.choice(presne).url_fotky()
url = url[:-1]
index = url.rfind('/')
if index != -1:
url = url[:index+1]
if fotka is None:
fotka = settings.STATIC_URL + "images/header/vikendovka.jpg"
return {'noc': noc, 'fotka': fotka}

63
header_fotky/migrations/0001_initial.py

@ -0,0 +1,63 @@
# Generated by Django 2.2.15 on 2020-09-20 09:14
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
from shutil import copytree
def zkopiruj_fotky(apps, schema_editor):
try:
copytree("mamweb/static/images/header/", "media/header/") # FIXME: bylo tu dirs_exists_ok=True, nekompatibilní s Py 3.7
except FileExistsError:
pass
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='FotkaHeader',
fields=[
('cas', models.DateTimeField(default=django.utils.timezone.now, help_text='Čas vložení fotky',
verbose_name='čas vložení fotky')),
('nazev',
models.CharField(help_text='Název např. archiv_noc', max_length=50, primary_key=True, serialize=False,
unique=True, verbose_name='název fotky')),
('fotka', models.ImageField(upload_to='header')),
],
options={
'verbose_name': 'fotka do pozadí menu',
'verbose_name_plural': 'fotky do pozadí menu',
'db_table': 'fotky_header',
'ordering': ['-cas'],
},
),
migrations.CreateModel(
name='FotkaUrlVazba',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('url',
models.CharField(blank=True, help_text='url prefix stránek např: /archiv/ nebo /', max_length=100,
verbose_name='URL')),
('denni_doba', models.CharField(choices=[('den', 'Zobrazit jen ve dne'), ('noc', 'Zobrazit jen v noci'),
('oboji', 'Zobrazovat pořád')], default='oboji', max_length=16,
verbose_name='denní doba')),
('fotka', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='header_fotky.FotkaHeader',
verbose_name='fotka')),
],
options={
'verbose_name': 'vazba url a fotky do pozadí menu',
'verbose_name_plural': 'vazby url a fotek do pozadí menu',
'db_table': 'fotky_url_vazby',
'ordering': ['url'],
},
),
migrations.RunPython(zkopiruj_fotky, migrations.RunPython.noop),
]

0
header_fotky/migrations/__init__.py

65
header_fotky/models.py

@ -0,0 +1,65 @@
from django.core.exceptions import ValidationError
from django.db import models
from django.utils import timezone
class FotkaHeader(models.Model):
class Meta:
ordering = ['-cas']
db_table = 'fotky_header'
verbose_name = u'fotka do pozadí menu'
verbose_name_plural = u'fotky do pozadí menu'
cas = models.DateTimeField(u'čas vložení fotky', default=timezone.now, help_text='Čas vložení fotky')
nazev = models.CharField(
u'název fotky', null=False, blank=False, unique=True, primary_key=True,
max_length=50, help_text='Název např. archiv_noc'
)
fotka = models.ImageField(upload_to='header', null=False, blank=False)
def __str__(self):
return self.nazev
def clean(self):
if not self.fotka:
raise ValidationError("Chybí obrázek")
""" Kontroluje, zda sedí poměr stran """
if abs(self.fotka.width - (self.fotka.height * 970 / 350)) > 2:
raise ValidationError("Obrázek by měl mít rozměry 970w na 350h, nebo alespoň podobný poměr stran.")
super().clean()
class FotkaUrlVazba(models.Model):
class Meta:
ordering = ['url']
db_table = 'fotky_url_vazby'
verbose_name = u'vazba url a fotky do pozadí menu'
verbose_name_plural = u'vazby url a fotek do pozadí menu'
url = models.CharField(
u'URL', blank=True, null=False, max_length=100,
help_text='url prefix stránek např: /archiv/ nebo /'
)
fotka = models.ForeignKey(
FotkaHeader, blank=False, null=False, verbose_name='fotka',
on_delete=models.CASCADE
)
DOBA_DEN = 'den'
DOBA_NOC = 'noc'
DOBA_OBOJI = 'oboji'
DOBA_CHOICES = [
(DOBA_DEN, 'Zobrazit jen ve dne'),
(DOBA_NOC, 'Zobrazit jen v noci'),
(DOBA_OBOJI, 'Zobrazovat pořád')]
denni_doba = models.CharField('denní doba', max_length=16, choices=DOBA_CHOICES, blank=False, default=DOBA_OBOJI)
def __str__(self):
return self.url
def url_fotky(self):
return self.fotka.fotka.url

4
korektury/models.py

@ -103,7 +103,7 @@ class KorekturovanePDF(models.Model):
# Změnil se počet stran, ukládáme # Změnil se počet stran, ukládáme
super(KorekturovanePDF, self).save() super(KorekturovanePDF, self).save()
def save(self): def save(self, **kwargs):
# Pokud se nezmenilo PDF, tak nepregenerovavej nahledy # Pokud se nezmenilo PDF, tak nepregenerovavej nahledy
try: try:
original = KorekturovanePDF.objects.get(pk=self.pk) original = KorekturovanePDF.objects.get(pk=self.pk)
@ -113,7 +113,7 @@ class KorekturovanePDF(models.Model):
except ObjectDoesNotExist: except ObjectDoesNotExist:
pass pass
# uložíme nahrávané pdf # uložíme nahrávané pdf
super(KorekturovanePDF, self).save() super(KorekturovanePDF, self).save(kwargs)
# uložíme png a změněný počet stran # uložíme png a změněný počet stran
self.convert() self.convert()

13
korektury/templates/korektury/base.html

@ -1,13 +0,0 @@
{% extends "base.html" %}
{% block submenu %}
{% include "korektury/submenu.html" %}
{% endblock %}
{% block content %}
{# blok do kterého se nacita text, v pripade jinyhc templatu obalit vlastnim blokem #}
{% endblock %}
{% block title %}
{# blok pro titulek stranky #}
{% endblock %}

8
korektury/templates/korektury/help.html

@ -1,10 +1,4 @@
{% extends "korektury/base.html" %} {% extends "base.html" %}
{% block submenu %}
{% with "help" as selected %}
{% include "korektury/submenu.html" %}
{% endwith %}
{% endblock %}
{% load staticfiles %} {% load staticfiles %}

4
korektury/templates/korektury/opraf.html

@ -36,12 +36,12 @@
id="neni_chyba_checkbox" id="neni_chyba_checkbox"
name="neni_chyba_checkbox" name="neni_chyba_checkbox"
onchange="toggle_corrections('neni_chyba')" checked> 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" <input type="checkbox"
id="k_zaneseni_checkbox" id="k_zaneseni_checkbox"
name="k_zaneseni_checkbox" name="k_zaneseni_checkbox"
onchange="toggle_corrections('k_zaneseni')" checked> 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/> <hr/>

6
korektury/templates/korektury/seznam.html

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

13
korektury/templates/korektury/submenu.html

@ -1,13 +0,0 @@
{% with "/korektury" as cesta %}
<div id='submenu'>
<ul>
<li class="{% if selected == "aktualni" %}selected{% endif %}"><a href="{{cesta}}/">Aktuální</a>
<li class="{% if selected == "zastarale" %}selected{% endif %}"><a href="{{cesta}}/zastarale/">Zastaralé</a>
<li class="{% if selected == "help" %}selected{% endif %}"><a href="{{cesta}}/help/">Nápověda</a>
</ul>
</div>
{% endwith %}

BIN
korektury/testpdfs/A.pdf

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

12
korektury/urls.py

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

4
mamweb/admin.py

@ -7,7 +7,8 @@ from django.contrib.flatpages.admin import FlatpageForm as FlatpageFormOld
from django import forms from django import forms
from ckeditor_uploader.widgets import CKEditorUploadingWidget from ckeditor_uploader.widgets import CKEditorUploadingWidget
class FlatpageForm(FlatpageFormOld): class FlatpageForm(FlatpageFormOld):
content = forms.CharField(widget=CKEditorUploadingWidget()) content = forms.CharField(widget=CKEditorUploadingWidget())
class Meta: class Meta:
@ -22,3 +23,4 @@ class FlatPageAdmin(FlatPageAdminOld):
# We have to unregister the normal admin, and then reregister ours # We have to unregister the normal admin, and then reregister ours
admin.site.unregister(FlatPage) admin.site.unregister(FlatPage)
admin.site.register(FlatPage, FlatPageAdmin) admin.site.register(FlatPage, FlatPageAdmin)

12
mamweb/context_processors.py

@ -1,12 +0,0 @@
from datetime import datetime, date
def vzhled(request):
''' Podle casu prida do templatu, zdali je nebo neni noc '''
hodin = datetime.now().hour
if (hodin <= 6) or (hodin >= 20):
noc = True
else:
noc = False
return {'noc' : noc}

3
mamweb/settings_common.py

@ -77,7 +77,7 @@ TEMPLATES = [
'django.template.context_processors.request', 'django.template.context_processors.request',
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
'sekizai.context_processors.sekizai', 'sekizai.context_processors.sekizai',
'mamweb.context_processors.vzhled', 'header_fotky.context_processors.vzhled',
) )
}, },
}, },
@ -127,6 +127,7 @@ INSTALLED_APPS = (
'galerie', 'galerie',
'korektury', 'korektury',
'prednasky', 'prednasky',
'header_fotky',
# Admin upravy: # Admin upravy:

315
mamweb/static/css/mamweb.css

@ -101,6 +101,26 @@ h6 {
color: black; color: black;
} }
.button {
margin: 10px 0px 10px 0px;
padding: 4px 0; /*vertikální centování textu*/
text-align: center;
background-color: #e84e10;
color: #fffbf6;
font-size: 150%;
font-weight: bold;
font-variant: small-caps;
filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.4));
}
.button:hover {
position: relative;
top: 2px;
left:2px;
background-color: #df490e;
;
}
.org-logged-in .mam-text-plugin { .org-logged-in .mam-text-plugin {
border: dashed 1px #6a0043; border: dashed 1px #6a0043;
@ -193,38 +213,6 @@ h1 {
top: 58px; top: 58px;
} }
/*
fotky:
todo url
kryptografie
baliky
beh
mam_cernobile -pro archiv? asi ne
vylet
spolecna -spíš ne, moc lidí
snih
ohen
noc
stiny
vikendovka
*/
#header.cojemam { background-image: url("../images/header/vikendovka.jpg");}
#header.soustredeni { background-image: url("../images/header/beh.jpg");}
#header.zadani { background-image: url("../images/header/baliky.jpg");}
#header.clanky { background-image: url("../images/header/kryptografie.jpg");}
#header.archiv { background-image: url("../images/header/stiny.jpg");}
#header.NOC {background-image: url("../images/header/noc.jpg");}
#header.NOCcojemam { background-image: url("../images/header/noc.jpg");}
#header.NOCsoustredeni { background-image: url("../images/header/vylet.jpg");}
#header.NOCzadani { background-image: url("../images/header/stiny.jpg");}
#header.NOCclanky { background-image: url("../images/header/ohen.jpg");}
#header.NOCarchiv { background-image: url("../images/header/stiny.jpg");}
#header img.logo { #header img.logo {
position: absolute center; position: absolute center;
width: 100%; width: 100%;
@ -318,6 +306,14 @@ ul.submenu li>a:hover {
color: black; color: black;
} }
ul.menu li.active>a {
color: #f9d59e;
}
ul.submenu li.active>a {
color: black;
}
/* konec nového menu */ /* konec nového menu */
div.novinky_name { div.novinky_name {
@ -395,13 +391,82 @@ input[type="file"] {
} }
.field-with-comment:hover span.field-comment{ .field-with-comment:hover span.field-comment{
display:block; display: block;
} }
input { input {
margin: 5px; margin: 5px;
} }
/* titulni stranka */
.titulnistrana {
display: flex;
text-align: justify;
}
.titulnistrana h1 {
text-align: center;
}
.zjistit_vic{
text-align: center;
margin-bottom: 30px;
}
.zjistit_vic hr {
display: none;
}
.graf-svg {
display: flex;
}
#svg-graf {
width: 100%;
height: auto;
margin: 30px;
}
.titulnistrana_obsah {
width: 66%;
}
.vitej_titulka, .temata_titulka {
width: 49%;
padding: 10px;
display: table-cell;
}
.titulnistrana_novinky {
width: 33%;
padding: 10px;
}
.novinka_obrazek {
margin: 10px 0px 10px 0px;
width: 100%;
}
.novinka_datum {
font-weight: bold;
}
.novinka_autor {
text-align: right;
font-style: italic;
}
div.org-text {
font-style: italic;
}
div.odpocet {
margin: 20px;
text-align: center;
}
/********************** /**********************
* Zmenšování displeje * Zmenšování displeje
***********************/ ***********************/
@ -431,42 +496,22 @@ input {
width: 100%; width: 100%;
} }
div.novinky{ ul.menu {
max-width: 100%; font-size: 90%;
margin-left: auto; margin-top: -7px;
margin-right: auto;
float: none;
}
div.graf{
width: 70%;
float: none;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
}
#svg-graf{
width: 100%;
height: auto;;
} }
ul.menu { ul.menu li {
font-size: 90%; margin-top: 10px; /* posunutí textu hlavního menu níže */
margin-top: -7px; }
}
ul.menu li {
margin-top: 10px; /* posunutí textu hlavního menu níže */
}
ul.submenu li {
margin-top: 0px; /* aby se spolu s textem hlavního menu neposunoval níže i text submenu */
}
ul.submenu { ul.submenu li {
margin-top: 8px; /* mezera mezi hlavním menu a submenu */ margin-top: 0px; /* aby se spolu s textem hlavního menu neposunoval níže i text submenu */
} }
ul.submenu {
margin-top: 8px; /* mezera mezi hlavním menu a submenu */
}
} }
@ -498,11 +543,53 @@ ul.submenu {
display: inline-grid; display: inline-grid;
max-width: 300px; max-width: 300px;
} }
/* titulni stranka */
.titulnistrana {
display: block;
}
.graf {
padding-top: 40px;
}
.titulnistrana_obsah {
width: 100%;
}
.vitej_titulka, .temata_titulka {
width: 49%;
padding: 10px;
display: table-cell;
}
.titulnistrana_novinky {
width: 100%;
max-width: 500px;
padding: 10px;
margin: auto;
}
#svg-graf {
width: 100%;
max-width: 500px;
padding: 10px;
margin: auto;
}
.zjistit_vic hr {
display: flex;
}
} }
/* malý tablet, mobil */ /* malý tablet, mobil */
@media (max-width: 650px) { @media (max-width: 650px) {
.no-mobile{
display: none;
}
#hide-if-small.login-bar-flatpage { #hide-if-small.login-bar-flatpage {
display: none; display: none;
} }
@ -639,18 +726,34 @@ ul.submenu {
text-align: justify; text-align: justify;
} }
div.novinky { table.form td, table.form tr {
max-width: 100%; display: inherit;
float: none; }
}
/* titulni stranka */
.titulnistrana {
display: block;
}
div.graf { .graf {
padding-top: 40px;
}
.titulnistrana_obsah {
width: 100%; width: 100%;
} }
table.form td, table.form tr { .vitej_titulka, .temata_titulka {
display: inherit; width: 100%;
} padding: 10px;
display: block;
}
.titulnistrana_novinky {
width: 100%;
padding: 10px;
}
} }
@ -732,11 +835,6 @@ div.org_email {
backface-visibility: hidden; backface-visibility: hidden;
} }
/* Style the front side (fallback if image is missing) */
.flip-card-front {
background-color: #bbb;
}
div.flip-card-foto img { div.flip-card-foto img {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -752,6 +850,10 @@ div.flip-card-foto img {
padding-top: 20px; padding-top: 20px;
} }
#archiv.flip-card-back {
background-color: white;
}
/* karty archiv */ /* karty archiv */
div.popis_rocniku { div.popis_rocniku {
@ -948,46 +1050,8 @@ div.cislo_odkazy ul {
} }
/* titulni stranka */ /**/
.zjistit_vic{
text-align: center;
}
.graf{
float: left;
}
.novinky{
float: right;
max-width: 42%;
}
.novinka_obrazek img {
margin-bottom: 15px;
}
div.novinka_obrazek {
width: 100%;
max-width: 400px; /*FIXME*/
}
div.org-text {
font-style: italic;
}
div.nahledy_cisel {
float: right;
height: 297px;
width: 420px;
position: relative;
margin-right: 10%;
margin-bottom: 50px;
}
div.nahledy_cisel div, div.nahledy_cisel img {
position: absolute;
}
ul.form { ul.form {
list-style-type: none; list-style-type: none;
padding-left: 0px; padding-left: 0px;
@ -1012,3 +1076,20 @@ p.gdpr {
div.gdpr { div.gdpr {
font-size: 6pt; font-size: 6pt;
} }
/* Jak řešit */
.jakresit img {
width: 33%;
padding: 10px;
filter: none;
}
@media(max-width: 860px) {
.jakresit img {
margin: auto;
display: grid;
width: 100%;
max-width: 360px;
}
}

26847
mamweb/static/images/jakresit_1.svg

File diff suppressed because it is too large

After

Width:  |  Height:  |  Size: 1.8 MiB

26847
mamweb/static/images/jakresit_2.svg

File diff suppressed because it is too large

After

Width:  |  Height:  |  Size: 1.8 MiB

26847
mamweb/static/images/jakresit_3.svg

File diff suppressed because it is too large

After

Width:  |  Height:  |  Size: 1.8 MiB

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

22
mamweb/templates/base.html

@ -12,7 +12,7 @@
<link href="{% static 'css/mamweb.css' %}" rel="stylesheet"> <link href="{% static 'css/mamweb.css' %}" rel="stylesheet">
<link href="{% static 'css/prettyPhoto.css' %}" rel="stylesheet" type="text/css" media="screen" charset="utf-8" /> <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 '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' %}" /> <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> <script type="text/javascript" src="{% static 'fluent_comments/js/ajaxcomments.js' %}"></script>
@ -56,13 +56,17 @@
<div class='col-md-12'> <div class='col-md-12'>
<a href='/'> <a href='/'>
<div id="title" >M&M - korespondenční seminář a časopis MFF&nbspUK</div> <div id="title" >M&M - korespondenční seminář a časopis MFF&nbspUK</div>
<div id="header" class="{% if noc %}NOC{% endif %}{% block header %}{% endblock %}"> <div id="header">
<img class="logo" src="{% static 'images/logo.svg' %}" /> <div class="no-mobile" style="background-image: url('{{ fotka }}')">
{# TODO style=… není fancy řešení, ale u <img> se bojím, že mi to rozbije vzhled #}
{% sitetree_menu from "main_menu" include "trunk" template "logo.html" %}
</div>
<img class="logo-mobile" src="{% static 'images/logo-mobile.svg' %}" /> <img class="logo-mobile" src="{% static 'images/logo-mobile.svg' %}" />
</div> </div>
</a> </a>
</div> </div>
</div> </div>
<div class='row'> <div class='row'>
<div class='col-md-12'> <div class='col-md-12'>
@ -72,6 +76,9 @@
{# ========= MENU MOBILE ========== #} {# ========= MENU MOBILE ========== #}
</div>
</div>
<!--Navbar--> <!--Navbar-->
<nav class="nav-button"> <nav class="nav-button">
@ -94,21 +101,24 @@
{# ========= END MENU ========== #} {# ========= END MENU ========== #}
<div class='row'>
<div class='row content'> <div class='row content'>
<div class='col-md-12'> <div class='col-md-12'>
{% block content %} {% block content %}
{% endblock content %} {% endblock content %}
</div> </div>
</div>
</div> </div>
<div class='row'> <div class='row'>
<div class='col-md-12'> <div class='col-md-12'>
<div id="footer"> <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> <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> </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> </div>
</div> </div>
<script src="{% static 'js/bootstrap.js' %}"></script> <script src="{% static 'js/bootstrap.js' %}"></script>

104
mamweb/templates/flatpages/default.html

@ -8,106 +8,4 @@
<div> <div>
{{ flatpage.content }} {{ flatpage.content }}
</div> </div>
{% endblock content %} {% endblock content %}
{# nahraj spravne submenu #}
{% block submenu %}
{# co-je-MaM #}
{% if "/co-je-MaM/" in flatpage.url %}
{% if "/uvod/" in flatpage.url %}
{% with "uvod" as selected %}
{% include "seminar/cojemam/submenu.html" %}
{% endwith %}
{% elif "jak-resit" in flatpage.url %}
{% with "jak-resit" as selected %}
{% include "seminar/cojemam/submenu.html" %}
{% endwith %}
{% elif "odmeny" in flatpage.url %}
{% with "odmeny" as selected %}
{% include "seminar/cojemam/submenu.html" %}
{% endwith %}
{% elif "FAQ" in flatpage.url %}
{% with "FAQ" as selected %}
{% include "seminar/cojemam/submenu.html" %}
{% endwith %}
{% elif "kontakt" in flatpage.url %}
{% else %}
{% include "seminar/cojemam/submenu.html" %}
{% endif %}
{% endif %}
{# soustredeni #}
{% if "/soustredeni/" in flatpage.url %}
{% if "/pripravujeme/" in flatpage.url %}
{% with "pripravujeme" as selected %}
{% include "seminar/soustredeni/submenu.html" %}
{% endwith %}
{% else %}
{% with "uvod" as selected %}
{% include "seminar/soustredeni/submenu.html" %}
{% endwith %}
{% endif %}
{% endif %}
{# zadani #}
{% if "/zadani/" in flatpage.url %}
{% if "/aktualni-cislo/" in flatpage.url %}
{% with "aktualni-cislo" as selected %}
{% include "seminar/zadani/submenu.html" %}
{% endwith %}
{% elif "/vysledkova-listina/" in flatpage.url %}
{% with "vysledkova-listina" as selected %}
{% include "seminar/zadani/submenu.html" %}
{% endwith %}
{% else %}
{% include "seminar/zadani/submenu.html" %}
{% endif %}
{% endif %}
{# clanky #}
{% if "/clanky/" in flatpage.url %}
{% if "/uvod/" in flatpage.url %}
{% with "uvod" as selected %}
{% include "seminar/clanky/submenu.html" %}
{% endwith %}
{% elif "/org/" in flatpage.url %}
{% with "org" as selected %}
{% include "seminar/clanky/submenu.html" %}
{% endwith %}
{% elif "/resitel/" in flatpage.url %}
{% with "resitel" as selected %}
{% include "seminar/clanky/submenu.html" %}
{% endwith %}
{% elif "/jak-psat-vedecky-clanek/" in flatpage.url %}
{% with "jak-psat-vedecky-clanek" as selected %}
{% include "seminar/clanky/submenu.html" %}
{% endwith %}
{% else %}
{% include "seminar/clanky/submenu.html" %}
{% endif %}
{% endif %}
{# archiv #}
{% if "/archiv/" in flatpage.url %}
{% if "/ulohy/" in flatpage.url %}
{% with "ulohy" as selected %}
{% include "seminar/archiv/submenu.html" %}
{% endwith %}
{% elif "/vysledky/" in flatpage.url %}
{% with "vysledky" as selected %}
{% include "seminar/archiv/submenu.html" %}
{% endwith %}
{% else %}
{% include "seminar/archiv/submenu.html" %}
{% endif %}
{% endif %}
{% endblock %}
{# zvirazneni menu #}
{% block menu_uvod %}{% if not "/kontakt/" in flatpage.url %}{% if "/co-je-MaM/" in flatpage.url %}selected{% endif %}{% endif %}{% endblock %}
{% block menu_soustredeni %}{% if "/soustredeni/" in flatpage.url %}selected{% endif %}{% endblock %}
{% block menu_zadani %}{% if "/zadani/" in flatpage.url %}selected{% endif %}{% endblock %}
{% block menu_clanky %}{% if "/clanky/" in flatpage.url %}selected{% endif %}{% endblock %}
{% block menu_archiv %}{% if "/archiv/" in flatpage.url %}selected{% endif %}{% endblock %}
{% block menu_odevzdat %}{% if "/kontakt/" in flatpage.url %}selected{% endif %}{% endblock %}
{# zmena titulniho obrazku #}
{% block header %}{% if "/co-je-MaM/" in flatpage.url %}cojemam{% elif "/soustredeni/" in flatpage.url %}soustredeni{% elif "/zadani/" in flatpage.url %}zadani{% elif "/clanky/" in flatpage.url %}clanky{% elif "/archiv/" in flatpage.url %}archiv{% else %}odeslat{% endif %}{% endblock header %}
{# TODO zvirazneni submenu #}

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 %} {% autoescape off %}
<ul class="menu"> <ul class="menu">
{% for item in sitetree_items %} {% 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 %}" > <a href="{% sitetree_url for item %}" >
{{ item.title_resolved }} {{ item.title_resolved }}
</a> </a>

4
mamweb/templates/menu_mobile.html

@ -3,7 +3,9 @@
{% autoescape off %} {% autoescape off %}
<ul class="menu_mobile"> <ul class="menu_mobile">
{% for item in sitetree_items %} {% 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 %}> <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 }} {{ item.title_resolved }}
</a> </a>

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"> <form enctype="multipart/form-data" action="." method="post">
{% csrf_token %} {% csrf_token %}
<table>{{form.as_table}}
</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><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><p><i>{{p.anotace}}</i></p></td></tr>
<tr><td><label>Obor: </label> {{p.obor}}</td></tr> <tr><td><label>Obor: </label> {{p.obor}}</td></tr>
<tr><td><label>Obtížnost: </label> {{p.obtiznost}}</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%} {% if p.klicova %}<tr><td><label>Klíčová slova: </label> {{p.klicova}}</td></tr>{% endif%}
<tr><td>Hodnocení: <tr><td>Hodnocení:
<INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="-1"> rozhodně nechci <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" checked> je mi to jedno <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"> rozhodně chci <INPUT TYPE="radio" NAME="q{{p.pk}}" VALUE="1" {% if h == 1 %} CHECKED="checked" {% endif %}> rozhodně chci
</td></tr> </td></tr>
<tr><td>&nbsp;</td></tr> <tr><td>&nbsp;</td></tr>
{% endfor %} {% endfor %}

6
prednasky/templates/prednasky/metaseznam_prednasek.html

@ -1,9 +1,5 @@
{% extends "prednasky/base.html" %} {% extends "prednasky/base.html" %}
{% block header %}hlasovani{% endblock %}
{% block content %} {% block content %}
<h1>{% block nadpis1a %}{% block nadpis1b %}Hlasování o přednáškách{% endblock %}{% endblock %}</h1> <h1>{% block nadpis1a %}{% block nadpis1b %}Hlasování o přednáškách{% endblock %}{% endblock %}</h1>
{# Projdi vsechny seznamy #} {# Projdi vsechny seznamy #}
@ -19,6 +15,8 @@
<a href="/prednasky/seznam_prednasek/{{seznam.id}}/export">Export</a> <a href="/prednasky/seznam_prednasek/{{seznam.id}}/export">Export</a>
</li> </li>
{% endfor %} {% endfor %}
</ul>
</div>
{% endblock %} {% endblock %}

6
prednasky/templates/prednasky/seznam_prednasek.html

@ -1,9 +1,5 @@
{% extends "prednasky/base.html" %} {% extends "prednasky/base.html" %}
{% block header %}seznam_prednasek{% endblock %}
{% block content %} {% block content %}
<h1>{% block nadpis1a %}Průběžné výsledky hlasování{% endblock %}</h1> <h1>{% block nadpis1a %}Průběžné výsledky hlasování{% endblock %}</h1>
<div class="mam-org-only"> <div class="mam-org-only">
@ -15,5 +11,7 @@
{{ prednaska.body }} b</i>) &ndash; {{ prednaska.org }} {{ prednaska.body }} b</i>) &ndash; {{ prednaska.org }}
</li> </li>
{% endfor %} {% endfor %}
</ul>
</div>
{% endblock %} {% endblock %}

27
prednasky/urls.py

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

37
prednasky/views.py

@ -4,41 +4,52 @@ from django.views import generic
from django.shortcuts import HttpResponseRedirect from django.shortcuts import HttpResponseRedirect
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Sum from django.db.models import Sum
from django.forms import Form
from prednasky.models import Prednaska, Hlasovani, Seznam, STAV_NAVRH from prednasky.models import Prednaska, Hlasovani, Seznam, STAV_NAVRH
from seminar.models import Soustredeni from seminar.models import Soustredeni, Osoba
from prednasky.forms import NewPrednaskyForm
def newPrednaska(request): def newPrednaska(request):
# hlasovani se vztahuje k nejnovejsimu soustredeni # hlasovani se vztahuje k nejnovejsimu soustredeni
sous = Soustredeni.objects.first() sous = Soustredeni.objects.first()
seznam = Seznam.objects.filter(soustredeni = sous, stav = STAV_NAVRH).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 # obsluha formulare
if request.method == 'POST': if request.method == 'POST':
form = NewPrednaskyForm(request.POST, request.FILES) form = Form(request.POST, request.FILES)
if form.is_valid(): 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: for i in request.POST:
if i[0] == 'q': if i[0] == 'q':
hlasovani = Hlasovani() prednaska = Prednaska.objects.filter(pk=int(i[1:]))[0]
print("q:"+i[1:]) hlasovani = Hlasovani.objects.filter(ucastnik=ucastnik, prednaska=prednaska).first()
hlasovani.prednaska = Prednaska.objects.filter(pk = int(i[1:]))[0] if not hlasovani:
hlasovani = Hlasovani()
hlasovani.prednaska = prednaska
hlasovani.ucastnik = ucastnik
hlasovani.seznam = seznam
hlasovani.body = int(request.POST[i]) hlasovani.body = int(request.POST[i])
hlasovani.ucastnik = jmeno
hlasovani.seznam = seznam
hlasovani.save() hlasovani.save()
# presmerovani na prave vzniklou galerii # presmerovani na prave vzniklou galerii
return HttpResponseRedirect('./hotovo') return HttpResponseRedirect('./hotovo')
else: def prednaska_hodnoceni(prednaska):
form = NewPrednaskyForm() h = Hlasovani.objects.filter(ucastnik=ucastnik, prednaska=prednaska).first()
if h:
return prednaska, h.body
else:
return prednaska, 0
return render( return render(
request, request,
'prednasky/base.html', 'prednasky/base.html',
{'form': form, 'prednasky': seznam} {'prednasky': map(prednaska_hodnoceni, seznam.prednaska_set.all())}
) )

13
seminar/migrations/0001_squashed_0067_auto_20190814_0805.py

@ -877,6 +877,7 @@ class Migration(migrations.Migration):
), ),
migrations.RunSQL( 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( migrations.RemoveField(
model_name='rocnik', model_name='rocnik',
@ -1733,15 +1734,19 @@ class Migration(migrations.Migration):
# migr 0052 # migr 0052
migrations.RunPython( migrations.RunPython(
spoj_k_organizatorum_osoby, spoj_k_organizatorum_osoby,
reverse_code=migrations.RunPython.noop,
), ),
migrations.RunPython( migrations.RunPython(
fix_problem, fix_problem,
reverse_code=migrations.RunPython.noop,
), ),
migrations.RunPython( migrations.RunPython(
fix_pohadka, fix_pohadka,
reverse_code=migrations.RunPython.noop,
), ),
migrations.RunPython( migrations.RunPython(
fix_novinka, fix_novinka,
reverse_code=migrations.RunPython.noop,
), ),
# migr 0053 # migr 0053
@ -1795,25 +1800,31 @@ class Migration(migrations.Migration):
# migr 0056 # migr 0056
migrations.RunPython( migrations.RunPython(
generuj_RocnikNody_a_CisloNody, generuj_RocnikNody_a_CisloNody,
reverse_code=migrations.RunPython.noop,
), ),
# migr 0057 # migr 0057
migrations.RunPython( migrations.RunPython(
reseni_to_Reseni, reseni_to_Reseni,
reverse_code=migrations.RunPython.noop,
), ),
# migr 0058 # migr 0058
migrations.RunPython( migrations.RunPython(
uloha_to_Uloha, uloha_to_Uloha,
reverse_code=migrations.RunPython.noop,
), ),
migrations.RunPython( migrations.RunPython(
tema_to_Tema, tema_to_Tema,
reverse_code=migrations.RunPython.noop,
), ),
migrations.RunPython( migrations.RunPython(
clanek_to_Clanek, clanek_to_Clanek,
reverse_code=migrations.RunPython.noop,
), ),
migrations.RunPython( migrations.RunPython(
konfery_rucne, konfery_rucne,
reverse_code=migrations.RunPython.noop,
), ),
# migr "fix 0058" # migr "fix 0058"
@ -1825,11 +1836,13 @@ class Migration(migrations.Migration):
# migr 0059 # migr 0059
migrations.RunPython( migrations.RunPython(
vytvor_pohadkanode, vytvor_pohadkanode,
reverse_code=migrations.RunPython.noop,
), ),
# migr 0060 # migr 0060
migrations.RunPython( migrations.RunPython(
pokacej_les, pokacej_les,
reverse_code=migrations.RunPython.noop,
), ),
migrations.RemoveField( migrations.RemoveField(

3
seminar/migrations/0019_rocnik_ciselne.py

@ -18,7 +18,8 @@ class Migration(migrations.Migration):
preserve_default=False, preserve_default=False,
), ),
migrations.RunSQL( 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( migrations.RemoveField(
model_name='rocnik', model_name='rocnik',

8
seminar/migrations/0052_user_to_organizator.py

@ -75,8 +75,8 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.RunPython(spoj_k_organizatorum_osoby), migrations.RunPython(spoj_k_organizatorum_osoby, migrations.RunPython.noop),
migrations.RunPython(fix_problem), migrations.RunPython(fix_problem, migrations.RunPython.noop),
migrations.RunPython(fix_pohadka), migrations.RunPython(fix_pohadka, migrations.RunPython.noop),
migrations.RunPython(fix_novinka), 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 = [ 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 = [ 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 = [ operations = [
# ashes to Ashes, dust to Dust.... # ashes to Ashes, dust to Dust....
migrations.RunPython(uloha_to_Uloha), migrations.RunPython(uloha_to_Uloha, migrations.RunPython.noop),
migrations.RunPython(tema_to_Tema), migrations.RunPython(tema_to_Tema, migrations.RunPython.noop),
migrations.RunPython(clanek_to_Clanek), migrations.RunPython(clanek_to_Clanek, migrations.RunPython.noop),
migrations.RunPython(konfery_rucne), migrations.RunPython(konfery_rucne, migrations.RunPython.noop),
] ]

2
seminar/migrations/0059_vytvorit_pohadkanode.py

@ -25,5 +25,5 @@ class Migration(migrations.Migration):
] ]
operations = [ 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 = [ operations = [
migrations.RunPython(pokacej_les), migrations.RunPython(pokacej_les, migrations.RunPython.noop),
] ]

2
seminar/migrations/0068_treenode_nazev.py

@ -103,5 +103,5 @@ class Migration(migrations.Migration):
name='nazev', 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'), 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', model_name='reseni',
name='text_zkraceny', 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( migrations.AddField(
model_name='konfera', model_name='konfera',
name='problem_ptr', name='problem_ptr',
@ -95,9 +98,6 @@ class Migration(migrations.Migration):
migrations.DeleteModel( migrations.DeleteModel(
name='ClanekNode', name='ClanekNode',
), ),
migrations.DeleteModel(
name='KonferaNode',
),
migrations.CreateModel( migrations.CreateModel(
name='Konfery_Ucastnici', name='Konfery_Ucastnici',
fields=[ fields=[

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),
]

18
seminar/migrations/0089_cislo_datum_preddeadline.py

@ -0,0 +1,18 @@
# Generated by Django 2.2.16 on 2020-10-13 19:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('seminar', '0088_perm_org_a_ucastnik'),
]
operations = [
migrations.AddField(
model_name='cislo',
name='datum_preddeadline',
field=models.DateField(blank=True, help_text='Datum pro příjem řešení, která se otisknou v dalším čísle', null=True, verbose_name='datum předdeadline'),
),
]

4
seminar/models.py

@ -443,6 +443,9 @@ class Cislo(SeminarModelBase):
datum_deadline = models.DateField('datum deadline', blank=True, null=True, datum_deadline = models.DateField('datum deadline', blank=True, null=True,
help_text='Datum pro příjem řešení úloh zadaných v tomto čísle') help_text='Datum pro příjem řešení úloh zadaných v tomto čísle')
datum_preddeadline = models.DateField('datum předdeadline', blank=True, null=True,
help_text='Datum pro příjem řešení, která se otisknou v dalším čísle')
datum_deadline_soustredeni = models.DateField( datum_deadline_soustredeni = models.DateField(
'datum deadline soustředění', 'datum deadline soustředění',
blank=True, null=True, blank=True, null=True,
@ -703,6 +706,7 @@ class Problem(SeminarModelBase,PolymorphicModel):
(STAV_SMAZANY, 'Smazaný'), (STAV_SMAZANY, 'Smazaný'),
] ]
stav = models.CharField('stav problému', max_length=32, choices=STAV_CHOICES, blank=False, default=STAV_NAVRH) stav = models.CharField('stav problému', max_length=32, choices=STAV_CHOICES, blank=False, default=STAV_NAVRH)
# Téma je taky Problém, takže má stavy, "zadané" témátko je aktuálně otevřené a dá se k němu něco poslat (řešení nebo článek)
zamereni = TaggableManager(verbose_name='zaměření', zamereni = TaggableManager(verbose_name='zaměření',
help_text='Zaměření M/F/I/O problému, příp. další tagy', blank=True) help_text='Zaměření M/F/I/O problému, příp. další tagy', blank=True)

6
seminar/templates/seminar/archiv/base.html

@ -1,6 +0,0 @@
{% extends "base.html" %}
{% block menu_archiv %}selected{% endblock %}
{# zmena fotky #}{% block header %}archiv{% endblock %}

8
seminar/templates/seminar/archiv/cisla.html

@ -1,4 +1,4 @@
{% extends "seminar/archiv/base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<div> <div>
@ -8,10 +8,6 @@
{% endblock %}{% endblock %} {% endblock %}{% endblock %}
</h2> </h2>
<!-- <div class='nahledy_cisel'>
{% autoescape off %}{{ nahledy }}{% endautoescape %}
</div>-->
{% for rocnik, url_png in object_list.items %} {% for rocnik, url_png in object_list.items %}
<div class="rocnik_pole"> <div class="rocnik_pole">
@ -33,7 +29,7 @@
</div> </div>
</div> </div>
<div class="flip-card-back"> <div class="flip-card-back" id="archiv">
<div class="popis_rocniku"> <div class="popis_rocniku">
Jednotlivá čísla: Jednotlivá čísla:
<ul> <ul>

24
seminar/templates/seminar/archiv/cislo.html

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

2
seminar/templates/seminar/archiv/cislo_obalkovani.html

@ -1,4 +1,4 @@
{% extends "seminar/archiv/base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<h1> <h1>

2
seminar/templates/seminar/archiv/prispevek.html

@ -1,4 +1,4 @@
{% extends "seminar/archiv/base.html" %} {% extends "base.html" %}
{% block title %} {% block title %}
{{prispevek.nazev}} {{prispevek.nazev}}

6
seminar/templates/seminar/archiv/problem.html

@ -1,13 +1,13 @@
{% extends "seminar/archiv/base.html" %} {% extends "base.html" %}
{% load comments %} {% load comments %}
{% block content %} {% 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 %} {% block problem %}
{% endblock %} {% endblock %}
{% if user.is_staff %} {% if user.je_org %}
<div class='mam-org-only'> <div class='mam-org-only'>
<h2>Text - org</h2> <h2>Text - org</h2>

6
seminar/templates/seminar/archiv/rocnik.html

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

2
seminar/templates/seminar/archiv/temata.html

@ -1,4 +1,4 @@
{% extends "seminar/archiv/base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<h1> <h1>

10
seminar/templates/seminar/clanky/base.html

@ -1,10 +0,0 @@
{% extends "base.html" %}
{% block menu_clanky %}selected{% endblock %}
{# zmena fotky #}{% block header %}clanky{% endblock %}
{% block submenu %}
{% include "seminar/clanky/submenu.html" %}
{% endblock %}

6
seminar/templates/seminar/clanky/organizatorske_clanky.html

@ -1,11 +1,5 @@
{% extends 'seminar/clanky/resitelske_clanky.html' %} {% extends 'seminar/clanky/resitelske_clanky.html' %}
{% block submenu %}
{% with "org" as selected %}
{% include "seminar/clanky/submenu.html" %}
{% endwith %}
{% endblock submenu %}
{% block nadpis1a %}{% block nadpis1b %} {% block nadpis1a %}{% block nadpis1b %}
Organizátorské články Organizátorské články
{% endblock %}{% endblock %} {% endblock %}{% endblock %}

8
seminar/templates/seminar/clanky/resitelske_clanky.html

@ -1,13 +1,5 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block menu_clanky %}selected{% endblock %}
{% block submenu %}
{% with "resitel" as selected %}
{% include "seminar/clanky/submenu.html" %}
{% endwith %}
{% endblock submenu %}
{% block content %} {% block content %}
<h1> <h1>

6
seminar/templates/seminar/cojemam/base.html

@ -1,6 +0,0 @@
{% extends "base.html" %}
{% block submenu %}
{% include "seminar/cojemam/submenu.html" %}
{% endblock %}

11
seminar/templates/seminar/cojemam/organizatori.html

@ -1,4 +1,4 @@
{% extends "seminar/cojemam/base.html" %} {% extends "base.html" %}
{% block nadpis1a %}{% block nadpis1b %} {% block nadpis1a %}{% block nadpis1b %}
{% if aktivni %} {% if aktivni %}
Organizátoři Organizátoři
@ -7,15 +7,6 @@
{% endif %} {% endif %}
{% endblock%}{% endblock%} {% endblock%}{% endblock%}
{# podbarveni menu a submenu #}
{% block menu_uvod %}selected{% endblock %}
{% block submenu %}
{% with "org" as selected %}
{% include "seminar/cojemam/submenu.html" %}
{% endwith %}
{% endblock %}
{# zmena fotky #}{% block header %}cojemam{% endblock %}
{% block content %} {% block content %}

16
seminar/templates/seminar/jak-resit.html

@ -0,0 +1,16 @@
{% extends 'base.html' %}
{% load humanize %}
{% load staticfiles %}
{% block content %}
<div class=jakresit>
<img class="jakresit_obrazek" alt="" src="{% static 'images/jakresit_1.svg' %}" />
<img class="jakresit_obrazek" alt="" src="{% static 'images/jakresit_2.svg' %}" />
<img class="jakresit_obrazek" alt="" src="{% static 'images/jakresit_3.svg' %}" />
</div>
{% endblock %}

18
seminar/templates/seminar/novinky.html

@ -1,15 +1,15 @@
{% for novinka in object_list %} {% for novinka in object_list %}
{# pripravene div-y na stylovani#} {# pripravene div-y na stylovani#}
<div> <div>
{% if not novinka.zverejneno and user.is_staff %} {% if not novinka.zverejneno and user.je_org %}
<div class="mam-org-only"> <div class="mam-org-only">
<ul> <ul>
<li><a href="/admin/seminar/novinky/{{novinka.pk}}">Upravit novinku</a> <li><a href="/admin/seminar/novinky/{{novinka.pk}}">Upravit novinku</a>
</ul> </ul>
{% endif %} {% endif %}
{% if novinka.zverejneno or user.is_staff %} {% if novinka.zverejneno or user.je_org %}
{# datum #} {# datum #}
<div><b>{{novinka.datum}}</b></div> <div class=novinka_datum>{{novinka.datum}}</div>
{# text #} {# text #}
{{ novinka.text | safe }} {{ novinka.text | safe }}
{# obrazek #} {# obrazek #}
@ -25,15 +25,15 @@
</div> </div>
{% endif %} {% endif %}
{# autor #} {# autor #}
<div class=novinky_name><p>{{novinka.autor.first_name}} <div class=novinka_autor>
{% if novinka.autor.organizator.prezdivka%} {{novinka.autor.osoba.jmeno}}
&bdquo;{{novinka.autor.organizator.prezdivka}}&ldquo; {% if novinka.autor.osoba.prezdivka%}
&bdquo;{{novinka.autor.osoba.prezdivka}}&ldquo;
{% endif %} {% endif %}
{{novinka.autor.last_name}} {{novinka.autor.osoba.prijmeni}}
</p>
</div> </div>
{% endif %} {% endif %}
{% if not novinka.zverejneno and user.is_staff %} {% if not novinka.zverejneno and user.je_org %}
</div> </div>
{% endif %} {% endif %}
</div> </div>

2
seminar/templates/seminar/profil/edit.html

@ -1,4 +1,4 @@
{% extends "seminar/zadani/base.html" %} {% extends "base.html" %}
{% load staticfiles %} {% load staticfiles %}
{% block script %} {% block script %}

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>
<p class="gdpr"> <p class="gdpr">
Dále máte právo: Dále máte právo:
</p>
<ul> <ul>
<li>požádat o informaci, jaké osobní údaje jsou o vás zpracovávány, <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 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 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>požadovat, aby byly vaše osobní údaje předány jinému správci,
<li>podat stížnost u dozorového úřadu. <li>podat stížnost u dozorového úřadu.
</p> </ul>
<p class="gdpr"> <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. 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> </p>

2
seminar/templates/seminar/profil/login.html

@ -1,4 +1,4 @@
{% extends "seminar/zadani/base.html" %} {% extends "base.html" %}
{% load staticfiles %} {% load staticfiles %}

2
seminar/templates/seminar/profil/logout.html

@ -1,4 +1,4 @@
{% extends "seminar/zadani/base.html" %} {% extends "base.html" %}
{% load staticfiles %} {% load staticfiles %}

8
seminar/templates/seminar/profil/nahraj_reseni.html

@ -1,4 +1,4 @@
{% extends "seminar/zadani/base.html" %} {% extends "base.html" %}
{% load staticfiles %} {% load staticfiles %}
{% block script %} {% block script %}
<!--script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script!--> <!--script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script!-->
@ -53,7 +53,7 @@
</td> </td>
<td {% if field.help_text %} class="field-with-comment"{% endif %}> <td {% if field.help_text %} class="field-with-comment"{% endif %}>
{{ field }} {{ field }}
<span class="field-comment">{{ field.help_text|safe }} <span class="field-comment">{{ field.help_text|safe }}</span>>
</td> </td>
<td><span class="field-error">{{ field.errors }}</span></td> <td><span class="field-error">{{ field.errors }}</span></td>
@ -74,7 +74,7 @@
<div id="empty_form" style="display:none"> <div id="empty_form" style="display:none">
<div class="attachment"> <div class="attachment">
<table class='form' id="reseni" class='no_error'> <table class='form no_error' id="reseni">
<tr> <tr>
{% for field in prilohy.empty_form.visible_fields %} {% for field in prilohy.empty_form.visible_fields %}
@ -86,7 +86,7 @@
</td> </td>
<td {% if field.help_text %} class="field-with-comment"{% endif %}> <td {% if field.help_text %} class="field-with-comment"{% endif %}>
{{ field }} {{ field }}
<span class="field-comment">{{ field.help_text|safe }} <span class="field-comment">{{ field.help_text|safe }}</span>
</td> </td>
<td><span class="field-error">{{ field.errors }}</span></td> <td><span class="field-error">{{ field.errors }}</span></td>

2
seminar/templates/seminar/profil/prihlaska.html

@ -1,4 +1,4 @@
{% extends "seminar/zadani/base.html" %} {% extends "base.html" %}
{% load staticfiles %} {% load staticfiles %}
{% block script %} {% block script %}

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

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

2
seminar/templates/seminar/profil/resitel.html

@ -1,4 +1,4 @@
{% extends "seminar/zadani/base.html" %} {% extends "base.html" %}
{% load staticfiles %} {% load staticfiles %}

6
seminar/templates/seminar/soustredeni/base.html

@ -1,6 +0,0 @@
{% extends "base.html" %}
{% block submenu %}
{% include "seminar/soustredeni/submenu.html" %}
{% endblock %}

23
seminar/templates/seminar/soustredeni/seznam_soustredeni.html

@ -1,11 +1,4 @@
{% extends "seminar/soustredeni/base.html" %} {% extends "base.html" %}
{% block menu_soustredeni %}selected{% endblock %}
{% block submenu %}
{% with "probehlo" as selected %}
{% include "seminar/soustredeni/submenu.html" %}
{% endwith %}
{% endblock submenu %}
{# zmena fotky #}{% block header %}soustredeni{% endblock %} {# zmena fotky #}{% block header %}soustredeni{% endblock %}
@ -17,8 +10,8 @@
{# Projdi vsechna soustredeni #} {# Projdi vsechna soustredeni #}
{% for soustredeni in object_list %} {% for soustredeni in object_list %}
{# Kdyz je verejne -> zobraz #} {# Kdyz je verejne -> zobraz #}
{% if soustredeni.verejne_db or user.is_staff %} {% if soustredeni.verejne_db or user.je_org %}
{% if not soustredeni.verejne_db and user.is_staff %} {% if not soustredeni.verejne_db and user.je_org %}
<div class="mam-org-only"> <div class="mam-org-only">
<!--Groups of user: {{user.groups.all}} <br>--> <!--Groups of user: {{user.groups.all}} <br>-->
{% endif %} {% endif %}
@ -34,8 +27,8 @@
{# Zobrazeni odkazu na galerie #} {# Zobrazeni odkazu na galerie #}
{% if soustredeni.galerie_set.all %} {% if soustredeni.galerie_set.all %}
{% for galerie in soustredeni.galerie_set.all %} {% for galerie in soustredeni.galerie_set.all %}
{% if galerie.zobrazit == 0 or user.is_staff %} {% if galerie.zobrazit == 0 or user.je_org %}
<li {% if galerie.zobrazit > 0 and user.is_staff %}class="mam-org-only"{% endif %}> <li {% if galerie.zobrazit > 0 and user.je_org %}class="mam-org-only"{% endif %}>
<a href="../{{soustredeni.pk}}/fotogalerie/{{galerie.pk}}">Fotogalerie</a> <a href="../{{soustredeni.pk}}/fotogalerie/{{galerie.pk}}">Fotogalerie</a>
{# TODO kdyz je titulni obrazek, tak asi i titulni obrazek #} {# TODO kdyz je titulni obrazek, tak asi i titulni obrazek #}
</li> </li>
@ -43,7 +36,7 @@
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</ul> </ul>
{% if user.is_staff %} {% if user.je_org %}
<div class="mam-org-only"> <div class="mam-org-only">
<a href="../{{soustredeni.pk}}/fotogalerie/0/new/">Vytvořit novou fotogalerii</a><br> <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> <a href="../{{soustredeni.pk}}/obalky.pdf">Vygenerovat obálky pro účastníky</a><br>
@ -60,7 +53,7 @@
{% if soustredeni.text %} {% if soustredeni.text %}
{% autoescape off %}{{soustredeni.text}}{% endautoescape %} {% autoescape off %}{{soustredeni.text}}{% endautoescape %}
{% endif %} {% endif %}
{% if user.is_staff %} {% if user.je_org %}
<div class="mam-org-only"> <div class="mam-org-only">
{# Účastníci #} {# Účastníci #}
<h2>Soustředění se zúčastnili tito účastníci:</h2> <h2>Soustředění se zúčastnili tito účastníci:</h2>
@ -82,7 +75,7 @@
</div> </div>
{% endif %} {% endif %}
{% if not soustredeni.verejne_db and user.is_staff %} {% if not soustredeni.verejne_db and user.je_org %}
</div> {# class="mam-org-only" #} </div> {# class="mam-org-only" #}
{% endif %} {% endif %}
{% endif %} {% endif %}

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

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

77
seminar/templates/seminar/titulnistrana.html

@ -5,32 +5,53 @@
{% block content %} {% block content %}
{# Uvitaci text #}
{% if nejblizsi_deadline %}
<div class="odpocet">
<p><b><big>Do konce <a href="/zadani/aktualni/">odeslání řešení</a> {% if typ_deadline == 'soustredeni' %}(pro účast na soustředění) {% elif typ_deadline == 'preddeadline' %}(pro otištění došlých řešení) {% endif %}zbývá:
{{nejblizsi_deadline|timeuntil}}</big></b></p>
</div>
{% endif %}
<div class=titulnistrana>
<div class="titulnistrana_obsah">
<div class="vitej_titulka">
<h1> <h1>
{% block nadpis1a %}{% block nadpis1b %} {% block nadpis1a %}
Vítej! Vítej
{% endblock %}{% endblock %} {% endblock %}
mezi námi
</h1> </h1>
<p>
M&amp;M je korespondenční seminář. Několikrát do roka zdarma vydáváme časopis a v něm zajímavé podněty k přemýšlení. Ty na ně můžeš reagovat.<br>
M&amp;M je taky soutěž. Můžeš vyhrát knížky, deskovky nebo dokonce dort. Můžeš se dostat na matfyz bez přijímaček. A především s námi můžeš jet na skvělé soustředění. <div>
</p> M&amp;M je korespondenční seminář. Vydáváme časopis a v něm zajímavé podněty k přemýšlení. Ty na ně můžeš reagovat,
experimentovat a objevovat s námi fascinující zákoutí matiky, fyziky a informatiky.
<div class="novinky"> <a href="auth/registrace"> <div class="button"> Zaregistruj se! </div> </a> {# FIXME odkaz #}
{% if dead %} M&amp;M je taky soutěž. Za svá řešení dostaneš body a můžeš vyhrát zajímavé ceny, dostat se
<div class="odpocet"> na Matfyz bez přijímaček a především, můžeš s námi jet na skvělé soustředění.
<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> <a href="cojemam/odmeny"> <div class="button"> Co můžeš vyhrát? </div> </a> {# FIXME odkaz #}
<big>{{ted|timesince:dead}}</big></b></p>
</div> </div>
{% endif %}
</div>
{# Novinky #} <div class="temata_titulka">
<h1>Novinky</h1>
{% include 'seminar/novinky.html' %}
<a href='/stare-novinky/'>Archiv novinek</a> <h1>
Řeš témata!
</h1>
<div>
Přidej se k nám! Pusť se do řešení témát.
{% for tema in aktualni_temata %}
<a href="{{ tema.url }}"> <div class="button"> {{ tema.nazev }} </div> </a>
{% endfor %}
</div>
</div> </div>
<div class="graf"> <div class="graf">
<div class="graf-svg"> <div class="graf-svg">
@ -38,8 +59,24 @@ M&amp;M je korespondenční seminář. Několikrát do roka zdarma vydáváme č
</div> </div>
<span class="zjistit_vic"> <span class="zjistit_vic">
<h2><a href="/co-je-MaM/uvod/">Zjistit víc!</a></h2> <h2><a href="/co-je-MaM/uvod/">Zjisti víc!</a></h2>
<hr>
</span> </span>
</div> </div>
</div>
<div class="titulnistrana_novinky">
{# Novinky #}
<h1>Co je nového?</h1>
{% include 'seminar/novinky.html' %}
<a href='/stare-novinky/'>Archiv novinek</a>
</div>
</div>
{% endblock %} {% endblock %}

2
seminar/templates/seminar/treenode.html

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

11
seminar/templates/seminar/zadani/AktualniVysledkovka.html

@ -1,11 +1,4 @@
{% extends "seminar/zadani/base.html" %} {% extends "base.html" %}
{% block submenu %}
{% with "vysledkova-listina" as selected %}
{% include 'seminar/zadani/submenu.html' %}
{% endwith %}
{% endblock submenu %}
{% block content %} {% block content %}
{% with nastaveni.aktualni_rocnik as rocnik %} {% with nastaveni.aktualni_rocnik as rocnik %}
@ -27,7 +20,7 @@
v&nbsp;<a href="/archiv/cisla/">archivu</a>. v&nbsp;<a href="/archiv/cisla/">archivu</a>.
</p> </p>
{% if user.is_staff and vysledkovka_s_neverejnymi %} {% if user.je_org and vysledkovka_s_neverejnymi %}
<div class='mam-org-only'> <div class='mam-org-only'>
<h1>Výsledky včetně neveřejných</h1> <h1>Výsledky včetně neveřejných</h1>
{% with vysledkovka_s_neverejnymi as vysledkovka %} {% with vysledkovka_s_neverejnymi as vysledkovka %}

14
seminar/templates/seminar/zadani/AktualniZadani.html

@ -1,10 +1,4 @@
{% extends "seminar/zadani/base.html" %} {% extends "base.html" %}
{% block submenu %}
{% with "aktualni" as selected %}
{% include 'seminar/zadani/submenu.html' %}
{% endwith %}
{% endblock submenu %}
{% block nadpis1a %}{% block nadpis1b %} {% block nadpis1a %}{% block nadpis1b %}
Aktuální zadání Aktuální zadání
@ -16,8 +10,8 @@
{% with nastaveni.aktualni_cislo as ac %} {% with nastaveni.aktualni_cislo as ac %}
{# Zobrazovani neverejnych zadani jen organizatorum #} {# Zobrazovani neverejnych zadani jen organizatorum #}
{% if user.is_staff or verejne %} {% if user.je_org or verejne %}
{% if user.is_staff and not verejne %}<div class="mam-org-only">{% endif %} {% if user.je_org and not verejne %}<div class="mam-org-only">{% endif %}
{% if ac.zadane_problemy.all %} {% if ac.zadane_problemy.all %}
{% if ac.datum_deadline_soustredeni %} {% if ac.datum_deadline_soustredeni %}
@ -60,7 +54,7 @@
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% if user.is_staff and not verejne%}</div>{% endif %} {% if user.je_org and not verejne%}</div>{% endif %}
{% else %} {% else %}
<h2>Aktuálně nejsou zveřejněny žádné úlohy</h2> <h2>Aktuálně nejsou zveřejněny žádné úlohy</h2>
{% endif %} {% endif %}

9
seminar/templates/seminar/zadani/Temata.html

@ -1,11 +1,4 @@
{% extends "seminar/zadani/base.html" %} {% extends "base.html" %}
{% block submenu %}
{% with "temata" as selected %}
{% include 'seminar/zadani/submenu.html' %}
{% endwith %}
{% endblock submenu %}
{% block content %} {% block content %}
{% with nastaveni.aktualni_rocnik as ar %} {% with nastaveni.aktualni_rocnik as ar %}

10
seminar/templates/seminar/zadani/base.html

@ -1,10 +0,0 @@
{% extends "base.html" %}
{% block menu_zadani %}selected{% endblock %}
{# zmena fotky #}{% block header %}zadani{% endblock %}
{% block submenu %}
{% include 'seminar/zadani/submenu.html' %}
{% endblock submenu %}

55
seminar/testutils.py

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime import datetime
from django.contrib.auth.models import Permission
from pytz import timezone from pytz import timezone
import random import random
import lorem import lorem
@ -9,6 +11,7 @@ from django.db import transaction
import unidecode import unidecode
import logging 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 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 import seminar.models as m
@ -70,7 +73,7 @@ def gen_osoby(rnd, size):
if pokusy >= max_pokusy: if pokusy >= max_pokusy:
print("Chyba, na danou velikost testovacích dat příliš málo možných" print("Chyba, na danou velikost testovacích dat příliš málo možných"
" jmen a příjmení") " jmen a příjmení")
exit exit()
prezdivka = rnd.choice(prezdivky) prezdivka = rnd.choice(prezdivky)
email = "@".join([unidecode.unidecode(jmeno), rnd.choice(domain)]) email = "@".join([unidecode.unidecode(jmeno), rnd.choice(domain)])
telefon = "".join([str(rnd.choice([k for k in range(10)])) for i in range(9)]) 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...') logger.info('Generuji řešitele...')
resitele = [] resitele = []
x = 0
resitel_perm = Permission.objects.filter(codename__exact='resitel').first()
for os in osoby: for os in osoby:
rand = rnd.randint(0, 8) rand = rnd.randint(0, 8)
if not (rand % 8 == 0): 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), resitele.append(Resitel.objects.create(osoba=os, skola=rnd.choice(skoly),
rok_maturity=rnd.randint(2019, 2029), rok_maturity=rnd.randint(2019, 2029),
zasilat=rnd.choice(Resitel.ZASILAT_CHOICES)[0])) 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)) prijemci.append(Prijemce.objects.create(osoba=i))
return prijemci return prijemci
def gen_organizatori(rnd, osoby, last_rocnik, users): def gen_organizatori(rnd, osoby, last_rocnik):
logger.info('Generuji organizátory...') logger.info('Generuji organizátory...')
organizatori = [] organizatori = []
@ -149,6 +163,8 @@ def gen_organizatori(rnd, osoby, last_rocnik, users):
seznam_oboru = ["matematiku", "matematiku", "matematiku", "fyziku", "literaturu", seznam_oboru = ["matematiku", "matematiku", "matematiku", "fyziku", "literaturu",
"informatiku", "informatiku", "běhání dokolečka"] "informatiku", "informatiku", "běhání dokolečka"]
x = 0
org_perm = Permission.objects.filter(codename__exact='org').first()
for os in osoby: for os in osoby:
rand = rnd.randint(0, 8) rand = rnd.randint(0, 8)
if (rand % 8 == 0): if (rand % 8 == 0):
@ -175,6 +191,15 @@ def gen_organizatori(rnd, osoby, last_rocnik, users):
if do.year > datetime.datetime.now().year: if do.year > datetime.datetime.now().year:
do = None 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, organizatori.append(Organizator.objects.create(osoba=os,
organizuje_od=od, organizuje_do=do, strucny_popis_organizatora = popis_orga)) organizuje_od=od, organizuje_do=do, strucny_popis_organizatora = popis_orga))
return organizatori return organizatori
@ -681,14 +706,14 @@ def otec_syn(otec, syn):
syn.save() syn.save()
otec.save() otec.save()
def gen_clanek(rnd): def gen_clanek(rnd, organizatori, resitele):
logger.info("Generuji článek do čísla 22.2") logger.info("Generuji článek do čísla 22.2")
clanek = m.Clanek.objects.create( clanek = m.Clanek.objects.create(
nazev="Článek o Lorem ipsum", nazev="Článek o Lorem ipsum",
nadproblem=None, nadproblem=None,
stav='vyreseny', stav='vyreseny',
zamereni=['I'], zamereni=['I'],
garant=rnd.choice(m.Organizator.objects.all()), garant=rnd.choice(organizatori),
kod='cl', kod='cl',
) )
clanek.save() clanek.save()
@ -696,7 +721,7 @@ def gen_clanek(rnd):
reseni = m.Reseni.objects.create( reseni = m.Reseni.objects.create(
zverejneno=True, zverejneno=True,
) )
reseni.resitele.add(rnd.choice(m.Resitel.objects.all())) reseni.resitele.add(rnd.choice(resitele))
reseni.save() reseni.save()
cislo = m.Cislo.objects.get(rocnik__rocnik=22, poradi=2) cislo = m.Cislo.objects.get(rocnik__rocnik=22, poradi=2)
@ -771,11 +796,22 @@ def create_test_data(size = 6, rnd = None):
# users # users
admin = User.objects.create_superuser(username='admin', email='', password='admin') 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'] usernames = ['anet', 'bara', 'cyril', 'david', 'eva', 'filip']
users = [] users = []
for usr in usernames[:size]: 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.first_name = usr.capitalize()
u.save() u.save()
users.append(u) users.append(u)
@ -789,8 +825,8 @@ def create_test_data(size = 6, rnd = None):
# resitele a organizatori # resitele a organizatori
last_rocnik = 25 last_rocnik = 25
organizatori = gen_organizatori(rnd, osoby, last_rocnik)
resitele = gen_resitele(rnd, osoby, skoly) resitele = gen_resitele(rnd, osoby, skoly)
organizatori = gen_organizatori(rnd, osoby, last_rocnik, users)
#generování novinek #generování novinek
novinky = gen_novinky(rnd, organizatori) novinky = gen_novinky(rnd, organizatori)
@ -830,6 +866,9 @@ def create_test_data(size = 6, rnd = None):
#generování konfer #generování konfer
konfery = gen_konfery(size, rnd, organizatori, resitele, soustredeni) 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 # 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) # 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 # 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 # TODO: přidat ke konferám řešení a dát je do čísel
# Dohackované vytvoření jednoho článku # 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ě # obecné nastavení semináře, musí být už přidané ročníky a čísla, jinak se nastaví divně

115
seminar/urls.py

@ -1,11 +1,8 @@
from django.urls import path, include 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 . 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.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 = [ urlpatterns = [
# path('aktualni/temata/', views.TemataRozcestnikView), # path('aktualni/temata/', views.TemataRozcestnikView),
@ -20,7 +17,7 @@ urlpatterns = [
path('archiv/temata/', views.ArchivTemataView.as_view()), path('archiv/temata/', views.ArchivTemataView.as_view()),
path('rocnik/<int:rocnik>/', views.RocnikView.as_view(), name='seminar_rocnik'), path('rocnik/<int:rocnik>/', views.RocnikView.as_view(), name='seminar_rocnik'),
path('cislo/<int:rocnik>.<int:cislo>/', views.CisloView.as_view(), name='seminar_cislo'), # odkomentované jenom kvůli testování archivu path('cislo/<int:rocnik>.<str:cislo>/', views.CisloView.as_view(), name='seminar_cislo'),
path('problem/<int:pk>/', views.ProblemView.as_view(), name='seminar_problem'), path('problem/<int:pk>/', views.ProblemView.as_view(), name='seminar_problem'),
path('treenode/<int:pk>/', views.TreeNodeView.as_view(), name='seminar_treenode'), path('treenode/<int:pk>/', views.TreeNodeView.as_view(), name='seminar_treenode'),
#path('problem/(?P<pk>\d+)/(?P<prispevek>\d+)/', views.PrispevekView.as_view(), name='seminar_problem_prispevek'), #path('problem/(?P<pk>\d+)/(?P<prispevek>\d+)/', views.PrispevekView.as_view(), name='seminar_problem_prispevek'),
@ -33,17 +30,17 @@ urlpatterns = [
), ),
path( path(
'soustredeni/<int:soustredeni>/seznam_ucastniku', 'soustredeni/<int:soustredeni>/seznam_ucastniku',
staff_member_required(views.SoustredeniUcastniciView.as_view()), org_required(views.SoustredeniUcastniciView.as_view()),
name='soustredeni_ucastnici' name='soustredeni_ucastnici'
), ),
path( path(
'soustredeni/<int:soustredeni>/maily_ucastniku', 'soustredeni/<int:soustredeni>/maily_ucastniku',
staff_member_required(views.SoustredeniMailyUcastnikuView.as_view()), org_required(views.SoustredeniMailyUcastnikuView.as_view()),
name='maily_ucastniku' name='maily_ucastniku'
), ),
path( path(
'soustredeni/<int:soustredeni>/export_ucastniku', 'soustredeni/<int:soustredeni>/export_ucastniku',
staff_member_required(views.soustredeniUcastniciExportView), org_required(views.soustredeniUcastniciExportView),
name='soustredeni_ucastnici_export' name='soustredeni_ucastnici_export'
), ),
path( path(
@ -62,64 +59,102 @@ urlpatterns = [
#path('clanky/org/', views.ClankyOrganizatorView.as_view(), name='clanky_organizator'), #path('clanky/org/', views.ClankyOrganizatorView.as_view(), name='clanky_organizator'),
# Aesop # Aesop
path('aesop-export/mam-rocnik-<int:prvni_rok>.csv', export.ExportRocnikView.as_view(), name='seminar_export_rocnik'), path(
path('aesop-export/mam-sous-<str:datum_zacatku>.csv', export.ExportSousView.as_view(), name='seminar_export_sous'), 'aesop-export/mam-rocnik-<int:prvni_rok>.csv',
path('aesop-export/index.csv', export.ExportIndexView.as_view(), name='seminar_export_index'), 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: # Stranky viditelne pouze pro orgy:
path( path(
'rocnik/<int:rocnik>/vysledkovka.tex', 'rocnik/<int:rocnik>/vysledkovka.tex',
staff_member_required(views.RocnikVysledkovkaView.as_view()), org_required(views.RocnikVysledkovkaView.as_view()),
name='seminar_rocnik_vysledkovka' name='seminar_rocnik_vysledkovka'
), ),
path('cislo/<int:rocnik>.<int:cislo>/vysledkovka.tex', path(
staff_member_required(views.CisloVysledkovkaView.as_view()), 'cislo/<int:rocnik>.<int:cislo>/vysledkovka.tex',
name='seminar_cislo_vysledkovka' 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'
), ),
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'),
# příprava na nestatický orgorozcestník # příprava na nestatický orgorozcestník
path('org/rozcestnik/', path(
staff_member_required(views.OrgoRozcestnikView.as_view()),name='seminar_org_rozcestnik'), 'org/rozcestnik/',
org_required(views.OrgoRozcestnikView.as_view()),
name='seminar_org_rozcestnik'
),
path('prihlaska/',views.prihlaskaView, name='seminar_prihlaska'), path('prihlaska/',views.prihlaskaView, name='seminar_prihlaska'),
path('login/', views.LoginView.as_view(), name='login'), path('login/', views.LoginView.as_view(), name='login'),
path('logout/', views.LogoutView.as_view(), name='logout'), 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('reset_password/', views.PasswordResetView.as_view(), name='reset_password'),
path('change_password/', views.PasswordChangeView.as_view(), name='change_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_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_confirm/<uidb64>/<token>/', views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('reset_password_complete/', views.PasswordResetCompleteView.as_view(), name='reset_password_complete'), 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 # Obecný view na profil -- orgům dá rozcestník, řešitelům jejich stránku
path('profil/', views.profilView, name='profil'), path('profil/', views.profilView, name='profil'),
# Autocomplete # Autocomplete
path('autocomplete/skola/',views.SkolaAutocomplete.as_view(), name='autocomplete_skola'), 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('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/add_solution', org_required(views.AddSolutionView.as_view()), name='seminar_vloz_reseni'),
path('temp/nahraj_reseni', views.NahrajReseniView.as_view(),name='seminar_nahraj_reseni'), path('temp/nahraj_reseni', resitel_required(views.NahrajReseniView.as_view()), name='seminar_nahraj_reseni'),
path('', views.TitulniStranaView.as_view(), name='titulni_strana'), path('', views.TitulniStranaView.as_view(), name='titulni_strana'),
path('jak-resit/', views.JakResitView.as_view(), name='jak-resit'),
# Ceka na autocomplete v3 # Ceka na autocomplete v3
# path('autocomplete/organizatori/', # path('autocomplete/organizatori/',
# staff_member_required(views.OrganizatorAutocomplete.as_view()), # org_member_required(views.OrganizatorAutocomplete.as_view()),
# name='seminar_autocomplete_organizator') # name='seminar_autocomplete_organizator')

14
seminar/utils.py

@ -1,15 +1,25 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime 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 html.parser import HTMLParser
from django.contrib.auth.models import AnonymousUser
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
import seminar.models as m import seminar.models as m
import seminar.treelib as t 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): class FirstTagParser(HTMLParser):

2
seminar/views/utils.py

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

113
seminar/views/views_all.py

@ -1,6 +1,6 @@
# coding:utf-8 # 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.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, JsonResponse
from django.urls import reverse,reverse_lazy from django.urls import reverse,reverse_lazy
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
@ -13,7 +13,7 @@ from django.views.generic.edit import FormView, CreateView
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.contrib.auth import authenticate, login, get_user_model, logout from django.contrib.auth import authenticate, login, get_user_model, logout
from django.contrib.auth import views as auth_views 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.contrib.auth.mixins import LoginRequiredMixin
from django.db import transaction from django.db import transaction
@ -24,7 +24,7 @@ from seminar import utils, treelib
from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm from seminar.forms import PrihlaskaForm, LoginForm, ProfileEditForm
import seminar.forms as f import seminar.forms as f
from datetime import timedelta, date, datetime from datetime import timedelta, date, datetime, MAXYEAR
from django.utils import timezone from django.utils import timezone
from itertools import groupby from itertools import groupby
from collections import OrderedDict from collections import OrderedDict
@ -44,14 +44,15 @@ import time
from seminar.utils import aktivniResitele, resi_v_rocniku from seminar.utils import aktivniResitele, resi_v_rocniku
# ze starého modelu
def verejna_temata(rocnik): #def verejna_temata(rocnik):
"""Vrací queryset zveřejněných témat v daném ročníku. # """
""" # Vrací queryset zveřejněných témat v daném ročníku.
return Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=rocnik, cislo_zadani__verejne_db=True).order_by('kod') # """
# return Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=rocnik, cislo_zadani__verejne_db=True).order_by('kod')
def temata_v_rocniku(rocnik): #
return Problem.objects.filter(typ=Problem.TYP_TEMA, rocnik=rocnik) #def temata_v_rocniku(rocnik):
# return Problem.objects.filter(typ=Problem.TYP_TEMA, rocnik=rocnik)
def get_problemy_k_tematu(tema): def get_problemy_k_tematu(tema):
return Problem.objects.filter(nadproblem = tema) return Problem.objects.filter(nadproblem = tema)
@ -238,50 +239,55 @@ def spravne_novinky(request):
user = request.user user = request.user
# Využíváme líné vyhodnocování QuerySetů # Využíváme líné vyhodnocování QuerySetů
qs = Novinky.objects.all() 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.je_org:
if not user.is_staff:
qs = qs.filter(zverejneno=True) qs = qs.filter(zverejneno=True)
return qs.order_by('-datum') return qs.order_by('-datum')
def aktualni_temata(rocnik):
"""
Vrací PolymorphicQuerySet témat v daném ročníku, ke kterým se aktuálně něco odevzdat.
"""
return Tema.objects.filter(rocnik=rocnik, stav='zadany').order_by('kod')
class TitulniStranaView(generic.ListView): class TitulniStranaView(generic.ListView):
template_name='seminar/titulnistrana.html' template_name='seminar/titulnistrana.html'
def get_queryset(self): def get_queryset(self):
return spravne_novinky(self.request)[:5] return spravne_novinky(self.request)[:3]
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(TitulniStranaView, self).get_context_data(**kwargs) context = super(TitulniStranaView, self).get_context_data(**kwargs)
nastaveni = get_object_or_404(Nastaveni) nastaveni = get_object_or_404(Nastaveni)
deadline_soustredeni = (nastaveni.aktualni_cislo.datum_deadline_soustredeni, "soustredeni")
preddeadline = (nastaveni.aktualni_cislo.datum_preddeadline, "preddeadline")
deadline = (nastaveni.aktualni_cislo.datum_deadline, "deadline")
# zjisteni spravneho terminu try:
if nastaveni.aktualni_cislo.datum_deadline_soustredeni: nejblizsi_deadline = sorted(filter(lambda dl: dl[0] is not None and dl[0] >= date.today(), [deadline_soustredeni, preddeadline, deadline]))[0]
cas_deadline_soustredeni = nastaveni.aktualni_cislo.\ except IndexError:
datum_deadline_soustredeni nejblizsi_deadline = (None, None) # neni zadna aktualni deadline
if (datetime.now().date() <= cas_deadline_soustredeni):
cas_deadline = cas_deadline_soustredeni if nejblizsi_deadline[0] is not None:
deadline_soustredeni = True context['nejblizsi_deadline'] = datetime.combine(nejblizsi_deadline[0], datetime.max.time())
else:
cas_deadline = nastaveni.aktualni_cislo.datum_deadline
deadline_soustredeni = False
else:
cas_deadline = nastaveni.aktualni_cislo.datum_deadline
deadline_soustredeni = False
# Pokud neni zverejnene cislo nezverejnuj odpocet
if nastaveni.aktualni_cislo.verejne():
# pokus se zjistit termin odeslani a pokud neni zadany,
# nezverejnuj odpocet
context['deadline_soustredeni'] = deadline_soustredeni
try:
context['dead'] = datetime.combine(cas_deadline,
datetime.max.time())
context['ted'] = datetime.now()
except:
context['dead'] = None
else: else:
context['dead'] = None context['nejblizsi_deadline'] = None
context['deadline_soustredeni'] = deadline_soustredeni
context['typ_deadline'] = nejblizsi_deadline[1]
# Aktuální témata
nazvy_a_odkazy_na_aktualni_temata = []
akt_temata = aktualni_temata(nastaveni.aktualni_rocnik)
for tema in akt_temata:
# FIXME: netuším, jestli funguje tema.verejne_url(), nemáme testdata na témátka - je to asi url vzhledem k ročníku
nazvy_a_odkazy_na_aktualni_temata.append({'nazev':tema.nazev,'url':tema.verejne_url()})
context['aktualni_temata'] = nazvy_a_odkazy_na_aktualni_temata
print(context)
return context return context
class StareNovinkyView(generic.ListView): class StareNovinkyView(generic.ListView):
@ -344,7 +350,8 @@ class ArchivView(generic.ListView):
### Výsledky ### Výsledky
def sloupec_s_poradim(setrizene_body): def sloupec_s_poradim(setrizene_body):
""" Ze seznamu obsahujícího sestupně setřízené body řešitelů za daný ročník """
Ze seznamu obsahujícího sestupně setřízené body řešitelů za daný ročník
vytvoří seznam s pořadími (včetně 3.-5. a pak 2 volná místa atp.), vytvoří seznam s pořadími (včetně 3.-5. a pak 2 volná místa atp.),
podle toho, jak jdou za sebou ve výsledkovce. podle toho, jak jdou za sebou ve výsledkovce.
Parametr: Parametr:
@ -384,7 +391,8 @@ def sloupec_s_poradim(setrizene_body):
return sloupec_s_poradim return sloupec_s_poradim
def cisla_rocniku(rocnik, jen_verejne=True): def cisla_rocniku(rocnik, jen_verejne=True):
""" Vrátí všechna čísla daného ročníku. """
Vrátí všechna čísla daného ročníku.
Parametry: Parametry:
rocnik (Rocnik): ročník semináře rocnik (Rocnik): ročník semináře
jen_verejne (bool): zda se mají vrátit jen veřejná, nebo všechna čísla jen_verejne (bool): zda se mají vrátit jen veřejná, nebo všechna čísla
@ -539,7 +547,7 @@ def vysledkovka_rocniku(rocnik, jen_verejne=True):
# získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně # získáme body za ročník, seznam obsahuje dvojice (řešitel_id, body) setřízené sestupně
resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele) resitel_rocnikbody_sezn = secti_body_za_rocnik(rocnik, aktivni_resitele)
# setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší # setřídíme řešitele podle počtu bodů a získáme seznam s body od nejvyšších po nenižší
setrizeni_resitele_id, setrizeni_resitele, setrizene_body = setrid_resitele_a_body(resitel_rocnikbody_sezn) setrizeni_resitele_id, setrizeni_resitele, setrizene_body = setrid_resitele_a_body(resitel_rocnikbody_sezn)
poradi = sloupec_s_poradim(setrizene_body) poradi = sloupec_s_poradim(setrizene_body)
@ -623,7 +631,7 @@ class ProblemView(generic.DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**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. # 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() raise PermissionDenied()
if isinstance(context['object'], Clanek): if isinstance(context['object'], Clanek):
context['reseni'] = Reseni.objects.filter(problem=context['object']).select_related('resitel').order_by('resitel__prijmeni') context['reseni'] = Reseni.objects.filter(problem=context['object']).select_related('resitel').order_by('resitel__prijmeni')
@ -774,6 +782,7 @@ def vysledkovka_cisla(cislo, context=None):
return context return context
class CisloView(generic.DetailView): class CisloView(generic.DetailView):
# FIXME zobrazování témátek a vůbec, teď je tam jen odkaz na číslo v pdf
model = Cislo model = Cislo
template_name = 'seminar/archiv/cislo.html' template_name = 'seminar/archiv/cislo.html'
@ -1212,6 +1221,8 @@ def prihlaskaView(request):
password=fcd['password'], password=fcd['password'],
email = fcd['email']) email = fcd['email'])
u.save() u.save()
resitel_perm = Permission.objects.filter(codename__exact='resitel').first()
u.user_permissions.add(resitel_perm)
o = Osoba( o = Osoba(
jmeno = fcd['jmeno'], jmeno = fcd['jmeno'],
@ -1311,10 +1322,9 @@ class PasswordChangeView(auth_views.PasswordChangeView):
# Jen hloupé rozhazovátko # Jen hloupé rozhazovátko
def profilView(request): def profilView(request):
user = request.user user = request.user
# FIXME: správná oprávnění if user.has_perm('auth.org'):
if user.has_perm('org'):
return OrgoRozcestnikView.as_view()(request) return OrgoRozcestnikView.as_view()(request)
if user.has_perm('ucastnik'): if user.has_perm('auth.resitel'):
return ResitelView.as_view()(request) return ResitelView.as_view()(request)
else: else:
return LoginView.as_view()(request) return LoginView.as_view()(request)
@ -1332,3 +1342,10 @@ def formularOKView(request):
} }
return render(request, template_name, context) return render(request, template_name, context)
#------------------ Jak řešit - možná má být udělané úplně jinak
class JakResitView(generic.ListView):
template_name = 'seminar/jak-resit.html'
def get_queryset(self):
return None

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save