diff --git a/seminar/models.py b/seminar/models.py
index 4070e1d0..d706db0d 100644
--- a/seminar/models.py
+++ b/seminar/models.py
@@ -582,7 +582,7 @@ class Organizator(SeminarModelBase):
"školu, ale jen obor, možnost zobrazit zvlášť")
def clean(self):
- if self.organizuje_od > self.organizuje_do:
+ if self.organizuje_od and self.organizuje_do and (self.organizuje_od > self.organizuje_do):
raise ValidationError("Organizátor nemůže skončit s organizováním dříve než začal!")
super().clean()
diff --git a/seminar/templates/seminar/clanky/resitelske_clanky.html b/seminar/templates/seminar/clanky/resitelske_clanky.html
index 1e15fcbc..84089753 100644
--- a/seminar/templates/seminar/clanky/resitelske_clanky.html
+++ b/seminar/templates/seminar/clanky/resitelske_clanky.html
@@ -17,7 +17,7 @@
{% for clanek in object_list %}
-{% with clanek.cislo_zadani.rocnik.rocnik as rocnik %}
+{% with clanek.cislo.rocnik.rocnik as rocnik %}
{% ifchanged rocnik %}
{% if not forloop.first %}{% endif %}
{{ rocnik }}. ročník
diff --git a/seminar/templates/seminar/orgorozcestnik.html b/seminar/templates/seminar/orgorozcestnik.html
new file mode 100644
index 00000000..5bd75403
--- /dev/null
+++ b/seminar/templates/seminar/orgorozcestnik.html
@@ -0,0 +1,86 @@
+{% extends "base.html" %}
+
+{% block content %}
+Informace, komunikace
+
+
+ - wiki obsahuje různé návody a know-how
+ - Riot chatování s dalšími orgy
+ - Kanboard správa TODO
+
+
+ - přidat novinku na web
+
+
+
+Tvorba čísla
+
+
+
+
+Moje problémy
+
+ Témata
+
+{% for t in temata %}
+- {{ t }}
+{% endfor %}
+
+
+ Úlohy
+
+{% for u in ulohy %}
+- {{ u }}
+{% endfor %}
+
+
+ Články
+
+{% for c in clanky %}
+- {{ c }}
+{% endfor %}
+
+
+
+Soustředění
+
+
+ - přednášky
+
+
+
+ - proběhlá soustředění
+
+ - vytvoření galerie
+ - stažení seznamu účastníků
+ - obálky
+
+
+
+
+
+Můj profil
+
+
+
+
+Nemůžeš najít, co hledáš? Může to být v administračním rozhraní webu.
+{% endblock content %}
+
diff --git a/seminar/urls.py b/seminar/urls.py
index df2e1435..ed42a7f8 100644
--- a/seminar/urls.py
+++ b/seminar/urls.py
@@ -90,6 +90,9 @@ urlpatterns = [
path('org/vloz_body//',
staff_member_required(views.VlozBodyView.as_view()),name='seminar_org_vlozbody'),
+ # příprava na nestatický orgorozcestník
+ path('org/rozcestnik/',
+ staff_member_required(views.OrgoRozcestnikView.as_view()),name='seminar_org_rozcestnik'),
path('prihlaska/',views.prihlaskaView, name='seminar_prihlaska'),
path('login/', views.LoginView.as_view(), name='login'),
path('logout/', views.LogoutView.as_view(), name='logout'),
diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py
index 87c7dbe5..0144854a 100644
--- a/seminar/views/views_all.py
+++ b/seminar/views/views_all.py
@@ -10,6 +10,7 @@ from django.http import Http404,HttpResponseBadRequest,HttpResponseRedirect
from django.db.models import Q, Sum, Count
from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.generic.edit import FormView, CreateView
+from django.views.generic.base import TemplateView
from django.contrib.auth import authenticate, login, get_user_model, logout
from django.contrib.auth import views as auth_views
from django.contrib.auth.models import User
@@ -200,7 +201,7 @@ class AktualniZadaniView(TreeNodeView):
# "cisla" : cisla
# })
# return render(request, 'seminar/tematka/rozcestnik.html', {"tematka": tematka, "rocnik" : nastaveni.aktualni_rocnik().rocnik})
-#
+#
#def ZadaniAktualniVysledkovkaView(request):
# nastaveni = get_object_or_404(Nastaveni)
@@ -873,6 +874,43 @@ def oldObalkovaniView(request, rocnik, cislo):
{'cislo': cislo, 'problemy': problemy, 'reseni': reseni}
)
+### Orgostránky
+
+class OrgoRozcestnikView(TemplateView):
+ ''' Zobrazí organizátorský rozcestník.'''
+
+ template_name = 'seminar/orgorozcestnik.html'
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context['posledni_soustredeni'] = Soustredeni.objects.order_by('-datum_konce').first()
+ nastaveni = Nastaveni.objects.first()
+ aktualni_rocnik = nastaveni.aktualni_rocnik
+ context['posledni_cislo_url'] = nastaveni.aktualni_cislo.verejne_url()
+ # TODO možná chceme odkazovat na právě rozpracované číslo, a ne to poslední vydané
+ # pokud nechceme haluzit kód (= poradi) dalšího čísla, bude asi potřeba jít
+ # přes treenody (a dát si přitom pozor na MezicisloNode)
+
+ u = self.request.user
+ os = s.Osoba.objects.get(user=u)
+ organizator = s.Organizator.objects.get(osoba=os)
+ temata_garant = s.Tema.objects.filter(garant=organizator,
+ rocnik=aktualni_rocnik)
+ #FIXME: přidat opravovatel, stav='STAV_ZADANY'
+ ulohy_garant = s.Uloha.objects.filter(garant=organizator,
+ cislo_zadani__rocnik=aktualni_rocnik)
+ clanky_garant = s.Clanek.objects.filter(garant=organizator,
+ cislo__rocnik=aktualni_rocnik)
+
+ context['temata'] = temata_garant
+ context['ulohy'] = ulohy_garant
+ context['clanky'] = clanky_garant
+ context['organizator'] = organizator
+ return context
+
+ #content_type = 'text/plain; charset=UTF8'
+ #XXX
+
### Tituly
def TitulyView(request, rocnik, cislo):
@@ -951,12 +989,42 @@ def soustredeniUcastniciExportView(request,soustredeni):
### Články
+def group_by_rocnik(clanky):
+ ''' Vezme zadaný seznam článků a seskupí je podle ročníku.
+ Vrátí seznam seznamů článků ze stejného ročníku.'''
+ if len(clanky) == 0:
+ return clanky
+ clanky.order_by('cislo__rocnik__rocnik')
+ skupiny_clanku = []
+ skupina = []
+
+ rocnik = clanky.first().cislo.rocnik.rocnik # první ročník
+ for clanek in clanky:
+ if clanek.cislo.rocnik.rocnik == rocnik:
+ skupina.append(clanek)
+ else:
+ skupiny_clanku.append(skupina)
+ skupina = []
+ skupina.append(clanek)
+ rocnik = clanek.cislo.rocnik.rocnik
+ skupiny_clanku.append(skupina)
+ return skupiny_clanku
+
# FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi
class ClankyResitelView(generic.ListView):
model = Problem
template_name = 'seminar/clanky/resitelske_clanky.html'
- queryset = Clanek.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')
+ #queryset
+ clanky = Clanek.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo__rocnik').order_by('-cislo__rocnik__rocnik')
+ queryset = []
+ skupiny_clanku = group_by_rocnik(clanky)
+ for skupina in skupiny_clanku:
+ skupina.sort(key=lambda clanek: clanek.kod_v_rocniku())
+ for clanek in skupina:
+ queryset.append(clanek)
+
+ #zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')
# FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit
#class ClankyOrganizatorView(generic.ListView):
@@ -1065,63 +1133,63 @@ def logoutView(request):
def prihlaska_log_gdpr_safe(logger, gdpr_logger, msg, form_data):
- msg = "{}, form_hash:{}".format(msg,hash(form_data))
+ msg = "{}, form_hash:{}".format(msg,hash(frozenset(form_data.items)))
logger.warn(msg)
gdpr_logger.warn(msg+", form:{}".format(form_data))
from django.forms.models import model_to_dict
def resitelEditView(request):
- err_logger = logging.getLogger('seminar.prihlaska.problem')
- ## Načtení objektu Osoba a Resitel, patrici k aktuálně přihlášenému uživately
- u = request.user
- osoba_edit = Osoba.objects.get(user=u)
- resitel_edit = osoba_edit.resitel
- user_edit = osoba_edit.user
- ## Vytvoření slovníku, kterým předvyplním formulář
- prefill_1=model_to_dict(user_edit)
- prefill_2=model_to_dict(resitel_edit)
- prefill_3=model_to_dict(osoba_edit)
- prefill_1.update(prefill_2)
- prefill_1.update(prefill_3)
- form = ProfileEditForm(initial=prefill_1)
- ## Změna údajů a jejich uložení
- if request.method == 'POST':
- form = ProfileEditForm(request.POST)
- if form.is_valid():
- ## Změny v osobě
- fcd = form.cleaned_data
- osoba_edit.jmeno = fcd['jmeno']
- osoba_edit.prijmeni = fcd['prijmeni']
- osoba_edit.pohlavi_muz = fcd['pohlavi_muz']
- osoba_edit.email = fcd['email']
- osoba_edit.telefon = fcd['telefon']
- osoba_edit.ulice = fcd['ulice']
- osoba_edit.mesto = fcd['mesto']
- osoba_edit.psc = fcd['psc']
- ## Změny v osobě s podmínkami
- if fcd.get('spam',False):
- osoba_edit.datum_souhlasu_zasilani = date.today()
- if fcd.get('stat','') in ('CZ','SK'):
- osoba_edit.stat = fcd['stat']
- else:
- ## Neznámá země
- msg = "Unknown country {}".format(fcd['stat_text'])
-
- ## Změny v řešiteli
- resitel_edit.skola = fcd['skola']
- resitel_edit.rok_maturity = fcd['rok_maturity']
- resitel_edit.zasilat = fcd['zasilat']
- if fcd.get('skola'):
- resitel_edit.skola = fcd['skola']
- else:
- # Unknown school - log it
- msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa'])
- resitel_edit.save()
- osoba_edit.save()
- return HttpResponseRedirect('/thanks/')
- else:
- ## Stránka před odeslaním formuláře = předvyplněný formulář
- return render(request, 'seminar/profil/edit.html', {'form': form})
+ err_logger = logging.getLogger('seminar.prihlaska.problem')
+ ## Načtení objektu Osoba a Resitel, patrici k aktuálně přihlášenému uživately
+ u = request.user
+ osoba_edit = Osoba.objects.get(user=u)
+ resitel_edit = osoba_edit.resitel
+ user_edit = osoba_edit.user
+ ## Vytvoření slovníku, kterým předvyplním formulář
+ prefill_1=model_to_dict(user_edit)
+ prefill_2=model_to_dict(resitel_edit)
+ prefill_3=model_to_dict(osoba_edit)
+ prefill_1.update(prefill_2)
+ prefill_1.update(prefill_3)
+ form = ProfileEditForm(initial=prefill_1)
+ ## Změna údajů a jejich uložení
+ if request.method == 'POST':
+ form = ProfileEditForm(request.POST)
+ if form.is_valid():
+ ## Změny v osobě
+ fcd = form.cleaned_data
+ osoba_edit.jmeno = fcd['jmeno']
+ osoba_edit.prijmeni = fcd['prijmeni']
+ osoba_edit.pohlavi_muz = fcd['pohlavi_muz']
+ osoba_edit.email = fcd['email']
+ osoba_edit.telefon = fcd['telefon']
+ osoba_edit.ulice = fcd['ulice']
+ osoba_edit.mesto = fcd['mesto']
+ osoba_edit.psc = fcd['psc']
+ ## Změny v osobě s podmínkami
+ if fcd.get('spam',False):
+ osoba_edit.datum_souhlasu_zasilani = date.today()
+ if fcd.get('stat','') in ('CZ','SK'):
+ osoba_edit.stat = fcd['stat']
+ else:
+ ## Neznámá země
+ msg = "Unknown country {}".format(fcd['stat_text'])
+
+ ## Změny v řešiteli
+ resitel_edit.skola = fcd['skola']
+ resitel_edit.rok_maturity = fcd['rok_maturity']
+ resitel_edit.zasilat = fcd['zasilat']
+ if fcd.get('skola'):
+ resitel_edit.skola = fcd['skola']
+ else:
+ # Unknown school - log it
+ msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa'])
+ resitel_edit.save()
+ osoba_edit.save()
+ return HttpResponseRedirect('/thanks/')
+ else:
+ ## Stránka před odeslaním formuláře = předvyplněný formulář
+ return render(request, 'seminar/profil/edit.html', {'form': form})
def prihlaskaView(request):
generic_logger = logging.getLogger('seminar.prihlaska')
@@ -1133,8 +1201,8 @@ def prihlaskaView(request):
if form.is_valid():
generic_logger.info("Form valid")
fcd = form.cleaned_data
- form_hash = hash(fcd)
- form_logger.info(fcd,form_hash=form_hash)
+ form_hash = hash(frozenset(fcd.items()))
+ form_logger.info(fcd,form_hash) # TODO takhle log nefunguje, ale ta předchozí varianta dokonce padala
with transaction.atomic():
u = User.objects.create_user(
@@ -1164,7 +1232,7 @@ def prihlaskaView(request):
else:
# Unknown country - log it
msg = "Unknown country {}".format(fcd['stat_text'])
- err_logger.warn(msg,form_hash=form_hash)
+ err_logger.warn(msg,form_hash) # TODO viz výše
o.save()
o.user = u
@@ -1182,7 +1250,7 @@ def prihlaskaView(request):
else:
# Unknown school - log it
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa'])
- err_logger.warn(msg,form_hash=form_hash)
+ err_logger.warn(msg,form_hash) # TODO viz výše
r.save()