+ {% elif galerie.zobrazit == 3 %}
+
{# mam-resitel-only #}
{% endif %}
{% endblock content %}
diff --git a/galerie/templates/galerie/base.html b/galerie/templates/galerie/base.html
index 032f16b2..0c449914 100644
--- a/galerie/templates/galerie/base.html
+++ b/galerie/templates/galerie/base.html
@@ -2,5 +2,5 @@
{% load static %}
{% block custom_css %}
-
+
{% endblock %}
diff --git a/galerie/utils.py b/galerie/utils.py
new file mode 100644
index 00000000..352e197b
--- /dev/null
+++ b/galerie/utils.py
@@ -0,0 +1,6 @@
+from galerie.models import Galerie
+
+def top_galerie(g: Galerie) -> Galerie:
+ while g.galerie_up is not None:
+ g = g.galerie_up
+ return g
diff --git a/galerie/views.py b/galerie/views.py
index cf9ade8b..fa2a15e9 100644
--- a/galerie/views.py
+++ b/galerie/views.py
@@ -1,22 +1,41 @@
import random
-from django.http import HttpResponse, Http404
+from django.http import HttpResponse, Http404, HttpRequest
from django.shortcuts import render, HttpResponseRedirect, get_object_or_404
from django.template import RequestContext
from datetime import datetime
-from galerie.models import Obrazek, Galerie
+from galerie.utils import top_galerie
+from personalni.utils import resitel_uzivatele
+
+from galerie.models import Obrazek, Galerie, VZDY, ORG, UCASTNIK, NIKDY
from soustredeni.models import Soustredeni
from galerie.forms import KomentarForm, NewGalerieForm
-def zobrazit(galerie, request):
- preview = False
- if galerie.zobrazit >= 1:
- if request.user.je_org:
- preview = True;
+import logging
+logger = logging.getLogger(__name__)
+
+def galerie_ke_zobrazeni(soustredeni: Soustredeni | None, request: HttpRequest) -> tuple[int]:
+ if request.user.is_superuser: return (VZDY, ORG, UCASTNIK, NIKDY)
+ if request.user.je_org: return (VZDY, ORG, UCASTNIK)
+ if request.user.is_anonymous: return (VZDY,)
+ if soustredeni is None: return (VZDY,)
+ if (resitel := resitel_uzivatele(request.user)) is not None:
+ if resitel.soustredeni_set.contains(soustredeni):
+ return (VZDY, UCASTNIK)
else:
- raise Http404
- return preview
+ return (VZDY,)
+ logger.warning("Nepodařilo se zjistit, jaké galerie se mají zobrazit!")
+ return (VZDY,)
+
+
+def zobrazit(galerie: Galerie, request: HttpRequest) -> bool:
+ soustredeni = top_galerie(galerie).soustredeni
+ return galerie.zobrazit in galerie_ke_zobrazeni(soustredeni, request)
+
+def dovolit_upravy_popisku(galerie: Galerie, request: HttpRequest) -> bool:
+ # FIXME: Dočasné: úpravy jen když je to v org-only stavu. (Odpovídá předchozímu chování)
+ return request.user.je_org and galerie.zobrazit in (ORG, NIKDY)
def cesta_od_korene(g):
@@ -31,19 +50,19 @@ def cesta_od_korene(g):
def nahled(request, pk, soustredeni):
"""Zobrazeni nahledu vsech fotek ve skupine."""
galerie = get_object_or_404(Galerie, pk=pk)
+ soustredeni = top_galerie(galerie).soustredeni
+ # FIXME: přepsat model a použít přímo dolů…
podgalerie = Galerie.objects.filter(galerie_up = galerie).order_by('poradi')
- if not request.user.je_org:
- podgalerie = podgalerie.filter(zobrazit__lt=1)
+ podgalerie = podgalerie.filter(zobrazit__in=galerie_ke_zobrazeni(soustredeni, request))
- obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev')
- preview = zobrazit(galerie, request)
+ obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev')
+ ma_se_zobrazit = zobrazit(galerie, request)
+ if not ma_se_zobrazit: raise Http404("Galerie sice existuje, ale my se tváříme, že ne :-D")
sourozenci = []
if galerie.galerie_up:
- sourozenci = galerie.galerie_up.galerie_set.all().order_by('poradi')
- if not request.user.je_org:
- sourozenci = sourozenci.filter(zobrazit__lt=1)
+ sourozenci = galerie.galerie_up.galerie_set.filter(zobrazit__in=galerie_ke_zobrazeni(soustredeni, request)).order_by('poradi')
predchozi = None
nasledujici = None
@@ -62,7 +81,6 @@ def nahled(request, pk, soustredeni):
{'galerie' : galerie,
'podgalerie' : podgalerie,
'obrazky' : obrazky,
- 'preview' : preview,
'cesta': cesta,
'sourozenci': sourozenci,
'predchozi': predchozi,
@@ -78,9 +96,41 @@ def detail(request, pk, fotka, soustredeni):
NAHLEDU = 1
galerie = get_object_or_404(Galerie, pk=pk)
- preview = zobrazit(galerie, request)
+ soustredeni = top_galerie(galerie).soustredeni
+ ma_se_zobrazit = zobrazit(galerie, request)
+ if not ma_se_zobrazit: raise Http404("Obrázek neukážu!")
obrazek = get_object_or_404(Obrazek, pk=fotka)
+
+ # Pořadí není povinné. FIXME: `nazev` je zavádějící… Ale tohle je kanonické pořadí obrázků v galerii…
obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev')
+ obrazky = list(obrazky)
+ index_obrazku = obrazky.index(obrazek)
+ # Podle mě se nemůže stát, že by volání výš selhalo, kdyžtak shodí web. (původně to byl explicitně ošetřený stav dávající 404)
+ predchozi_obrazky = list(reversed(obrazky[:index_obrazku]))
+ nasledujici_obrazky = obrazky[index_obrazku+1:]
+ # Může jich být hodně…
+ predchozi_obrazky = predchozi_obrazky[:NAHLEDU]
+ nasledujici_obrazky = nasledujici_obrazky[:NAHLEDU]
+ # Předchozí obrázky chceme v normálním pořadí
+ predchozi_obrazky = list(reversed(predchozi_obrazky))
+
+ if galerie.galerie_up is not None:
+ sousedni_galerie = Galerie.objects.filter(galerie_up=galerie.galerie_up, zobrazit__in=galerie_ke_zobrazeni(soustredeni, request)).order_by('poradi')
+ sousedni_galerie = list(sousedni_galerie)
+ # Teoreticky se můžeme dívat na galerie.poradi, ale jednak už tenhle pattern stejně je výš a druhak je galerií málo, takže pomalost nevadí.
+ index_galerie = sousedni_galerie.index(galerie)
+ predchozi_galerie = sousedni_galerie[index_galerie-1] if index_galerie > 0 else None
+ nasledujici_galerie = sousedni_galerie[index_galerie+1] if index_galerie < len(sousedni_galerie) - 1 else None
+ else:
+ predchozi_galerie = None
+ nasledujici_galerie = None
+
+ # Pokud je obrázků dost, tak další galerii nepotřebujeme
+ # (jo, mohli jsme si ušetřit práci, ale takhle je kód imho přehlednější a za pár ušetřených dotazů do DB to nestojí)
+ if len(predchozi_obrazky) >= NAHLEDU:
+ predchozi_galerie = None
+ if len(nasledujici_obrazky) >= NAHLEDU:
+ nasledujici_galerie = None
# vytvoreni a obslouzeni formulare
if request.method == 'POST':
@@ -90,49 +140,6 @@ def detail(request, pk, fotka, soustredeni):
obrazek.save()
else:
form = KomentarForm({'komentar': obrazek.popis})
-
- # Poradi aktualniho obrazku v galerii/stitku.
- for i in range(len(obrazky)):
- if obrazky[i] == obrazek:
- poradi = i
- break
- else:
- # Obrazek neni v galerii/stitku.
- raise Http404
-
-
- # Nacteni okolnich obrazku a galerii
- # TODO vyjmout zjisteni predchozich a nasledujicich galerii
- # a udelat z toho funkci, ktera se pouzije u nahledu
- predchozi_galerie = None
- nasledujici_galerie = None
- obrazky_dalsi = obrazky[poradi+1:poradi+NAHLEDU+1]
- if (poradi+1) > NAHLEDU:
- obrazky_predchozi = obrazky[poradi-NAHLEDU:poradi]
- else:
- obrazky_predchozi = obrazky[0:poradi]
- if galerie.poradi > 1:
- predchozi_galerie = Galerie.objects.\
- filter(galerie_up=galerie.galerie_up).\
- filter(poradi=(galerie.poradi-1))
- if predchozi_galerie:
- predchozi_galerie = predchozi_galerie[0]
- else:
- predchozi_galerie = None
- if (poradi+1) == len(obrazky): # Tohle je poslední obrázek
- if (galerie.poradi is not None
- and galerie.galerie_up is not None):
- nasledujici_galerie = Galerie.objects.\
- filter(galerie_up=galerie.galerie_up).\
- filter(poradi=(galerie.poradi+1))
- else:
- nasledujici_galerie = None
- if nasledujici_galerie:
- nasledujici_galerie = nasledujici_galerie[0]
- else:
- nasledujici_galerie = None
-
-
# Preskalovani obrazku do vybraneho prostoru.
vyska = obrazek.obrazek_stredni.height
@@ -151,9 +158,9 @@ def detail(request, pk, fotka, soustredeni):
'obrazek' : obrazek,
'vyska' : vyska,
'sirka' : sirka,
- 'obrazky_predchozi' : obrazky_predchozi,
- 'obrazky_dalsi' : obrazky_dalsi,
- 'preview' : preview,
+ 'obrazky_predchozi' : predchozi_obrazky,
+ 'obrazky_dalsi' : nasledujici_obrazky,
+ 'upravy_popisku' : dovolit_upravy_popisku(galerie, request),
'form' : form,
'cesta': cesta_od_korene(galerie),
})
@@ -179,7 +186,7 @@ def new_galerie(request, galerie, soustredeni):
gal = Galerie()
gal.nazev = form.cleaned_data['nazev']
#gal.popis = form.cleaned_data['popis'] # popis nepouzivame
- gal.zobrazit = 1 # galerie je v procesu vytvareni
+ gal.zobrazit = ORG # galerie je v procesu vytvareni
''' pokud je to podgalerie pridej nadrazenou galerii
a nadrazene soustredeni nechej volne,
pokud je to hlavni galerie, tak nadrazena galerie neexistuje,
diff --git a/odevzdavatko/static/css/odevzdavatko.css b/odevzdavatko/static/css/odevzdavatko.css
new file mode 100644
index 00000000..9a61b259
--- /dev/null
+++ b/odevzdavatko/static/css/odevzdavatko.css
@@ -0,0 +1,10 @@
+.odevzdavatko-role {
+ font-size: 0.8em;
+
+ .vyrazne {
+ color: var(--hlavni-oranzova);
+ }
+ .nevyrazne {
+ color: #aaa;
+ }
+}
diff --git a/odevzdavatko/templates/odevzdavatko/base.html b/odevzdavatko/templates/odevzdavatko/base.html
new file mode 100644
index 00000000..e304e253
--- /dev/null
+++ b/odevzdavatko/templates/odevzdavatko/base.html
@@ -0,0 +1,6 @@
+{% extends "base.html" %}
+{% load static %}
+
+{% block custom_css %}
+
+{% endblock %}
diff --git a/odevzdavatko/templates/odevzdavatko/tabulka.html b/odevzdavatko/templates/odevzdavatko/tabulka.html
index 41f91b14..4167c4b5 100644
--- a/odevzdavatko/templates/odevzdavatko/tabulka.html
+++ b/odevzdavatko/templates/odevzdavatko/tabulka.html
@@ -1,6 +1,7 @@
-{% extends "base.html" %}
+{% extends "odevzdavatko/base.html" %}
{% load barvy_reseni %}
+{% load orgove %}
{% block content %}
@@ -27,7 +28,15 @@ Do data (včetně): {{ filtr.reseni_do }}
{% for p in problemy %}
{# TODO: Přehled řešení k problému, odkázaný odsud? #}
- {{ p }}
+ {{ p }}
+
+ {% spaceless %}
+ A
+ G
+ O
+ {% endspaceless %}
+
+
|
{% endfor %}
diff --git a/odevzdavatko/templatetags/orgove.py b/odevzdavatko/templatetags/orgove.py
new file mode 100644
index 00000000..c5380067
--- /dev/null
+++ b/odevzdavatko/templatetags/orgove.py
@@ -0,0 +1,27 @@
+from django import template
+register = template.Library()
+
+from personalni.utils import organizator_cehokoliv
+
+# Jen typová anotace
+from tvorba.models import Problem
+from personalni.models import Osoba, Organizator, Resitel, Prijemce
+from django.contrib.auth.models import AnonymousUser, User
+
+@register.filter
+def ma_autora(p: Problem, o: Osoba | Organizator | User | AnonymousUser | Resitel | Prijemce) -> bool | None:
+ o = organizator_cehokoliv(o)
+ if o is None: return None
+ return p.autor == o
+
+@register.filter
+def ma_garanta(p: Problem, o: Osoba | Organizator | User | AnonymousUser | Resitel | Prijemce) -> bool | None:
+ o = organizator_cehokoliv(o)
+ if o is None: return None
+ return p.garant == o
+
+@register.filter
+def ma_opravovatele(p: Problem, o: Osoba | Organizator | User | AnonymousUser | Resitel | Prijemce) -> bool | None:
+ o = organizator_cehokoliv(o)
+ if o is None: return None
+ return p.opravovatele.contains(o)
diff --git a/personalni/utils.py b/personalni/utils.py
index 02e541da..4a8b9a38 100644
--- a/personalni/utils.py
+++ b/personalni/utils.py
@@ -3,7 +3,7 @@ import re
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import permission_required, user_passes_test
-from django.contrib.auth.models import AnonymousUser
+from django.contrib.auth.models import AnonymousUser, User
from django.db import transaction
import soustredeni.models
@@ -182,3 +182,46 @@ def merge_osoby(cilova, zdrojova):
cilova.save()
input("Potvrdit transakci osob (^C pro zrušení) ")
+
+def osoba_uzivatele(u: User | AnonymousUser) -> Osoba | None:
+ if u.is_anonymous: return None
+ try:
+ return u.osoba
+ except User.osoba.RelatedObjectDoesNotExist:
+ return None
+
+def resitel_osoby(o: Osoba) -> Resitel | None:
+ try:
+ return o.resitel
+ except Osoba.resitel.RelatedObjectDoesNotExist:
+ return None
+
+def resitel_uzivatele(u: User | AnonymousUser) -> Resitel | None:
+ o = osoba_uzivatele(u)
+ if o is None: return None
+ return resitel_osoby(o)
+
+def resitel_cehokoliv(r: User | AnonymousUser | Osoba | Organizator | Resitel | Prijemce) -> Organizator | None:
+ if isinstance(r, User): r = resitel_uzivatele(r)
+ if isinstance(r, Osoba): r = resitel_osoby(r)
+ if isinstance(r, Resitel) or isinstance(r, Prijemce): r = resitel_osoby(r.osoba)
+ assert isinstance(r, Resitel) or r is None
+ return r
+
+def organizator_osoby(o: Osoba) -> Organizator | None:
+ try:
+ return o.org
+ except Osoba.org.RelatedObjectDoesNotExist:
+ return None
+
+def organizator_uzivatele(u: User | AnonymousUser) -> Organizator | None:
+ o = osoba_uzivatele(u)
+ if o is None: return None
+ return organizator_osoby(o)
+
+def organizator_cehokoliv(o: User | AnonymousUser | Osoba | Organizator | Resitel | Prijemce) -> Organizator | None:
+ if isinstance(o, User): o = organizator_uzivatele(o)
+ if isinstance(o, Osoba): o = organizator_osoby(o)
+ if isinstance(o, Resitel) or isinstance(o, Prijemce): o = organizator_osoby(o.osoba)
+ assert isinstance(o, Organizator) or o is None
+ return o