From b744e844dd22d2ebdb875777183a9e2a0205df27 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 23 Apr 2025 21:07:38 +0200 Subject: [PATCH 01/16] =?UTF-8?q?Pr=C3=A1va=20ke=20galeri=C3=ADm=20funk?= =?UTF-8?q?=C4=8Dn=C3=AD,=20UI=20zat=C3=ADm=20ne?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0014_alter_galerie_zobrazit.py | 18 ++++++++ galerie/models.py | 2 + galerie/templates/galerie/Galerie.html | 2 +- galerie/utils.py | 6 +++ galerie/views.py | 44 +++++++++++++------ personalni/utils.py | 22 +++++++++- 6 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 galerie/migrations/0014_alter_galerie_zobrazit.py create mode 100644 galerie/utils.py diff --git a/galerie/migrations/0014_alter_galerie_zobrazit.py b/galerie/migrations/0014_alter_galerie_zobrazit.py new file mode 100644 index 00000000..c53393f3 --- /dev/null +++ b/galerie/migrations/0014_alter_galerie_zobrazit.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.20 on 2025-04-23 18:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('galerie', '0013_post_split_soustredeni'), + ] + + operations = [ + migrations.AlterField( + model_name='galerie', + name='zobrazit', + field=models.IntegerField(choices=[(0, 'Vždy'), (1, 'Organizátorům'), (3, 'Účastníkům a orgům'), (2, 'Nikdy')], default=1, verbose_name='Zobrazit?'), + ), + ] diff --git a/galerie/models.py b/galerie/models.py index 074b0d26..bca860a9 100644 --- a/galerie/models.py +++ b/galerie/models.py @@ -10,9 +10,11 @@ from soustredeni.models import Soustredeni VZDY=0 ORG=1 NIKDY=2 +UCASTNIK=3 VIDITELNOST = ( (VZDY, 'Vždy'), (ORG, 'Organizátorům'), + (UCASTNIK, 'Účastníkům a orgům'), (NIKDY, 'Nikdy'), ) diff --git a/galerie/templates/galerie/Galerie.html b/galerie/templates/galerie/Galerie.html index ff8ebfe3..9aa4b40b 100644 --- a/galerie/templates/galerie/Galerie.html +++ b/galerie/templates/galerie/Galerie.html @@ -83,7 +83,7 @@ {# Popisek fotky #}
- {% if preview %} + {% if upravy_popisku %}
{% csrf_token %} 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..0e20055d 100644 --- a/galerie/views.py +++ b/galerie/views.py @@ -5,18 +5,32 @@ 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; - else: - raise Http404 - return preview + soustredeni = top_galerie(galerie).soustredeni + # Superuživatelům úplně všechny galerie. + if request.user.is_superuser: return True + + if galerie.zobrazit == VZDY: return True + if galerie.zobrazit == NIKDY: return False + if galerie.zobrazit == ORG and request.user.je_org: return True + if galerie.zobrazit == UCASTNIK: + if request.user.je_org: + return True + resitel = resitel_uzivatele(request.user) + if resitel is not None and resitel.soustredeni_set.contains(soustredeni): + return True + return False + +def dovolit_upravy_popisku(galerie, request): + # 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): @@ -37,7 +51,8 @@ def nahled(request, pk, soustredeni): podgalerie = podgalerie.filter(zobrazit__lt=1) obrazky = Obrazek.objects.filter(galerie = galerie).order_by('poradi', 'nazev') - preview = zobrazit(galerie, request) + 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: @@ -62,7 +77,7 @@ def nahled(request, pk, soustredeni): {'galerie' : galerie, 'podgalerie' : podgalerie, 'obrazky' : obrazky, - 'preview' : preview, + 'upravy_popisku' : dovolit_upravy_popisku(galerie, request), 'cesta': cesta, 'sourozenci': sourozenci, 'predchozi': predchozi, @@ -78,7 +93,8 @@ def detail(request, pk, fotka, soustredeni): NAHLEDU = 1 galerie = get_object_or_404(Galerie, pk=pk) - preview = zobrazit(galerie, request) + 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) obrazky = galerie.obrazek_set.all().order_by('poradi', 'nazev') @@ -98,7 +114,7 @@ def detail(request, pk, fotka, soustredeni): break else: # Obrazek neni v galerii/stitku. - raise Http404 + raise Http404("„Obrázek není v galerii/štítku“, ať už to znamená cokoliv…") # Nacteni okolnich obrazku a galerii @@ -153,7 +169,7 @@ def detail(request, pk, fotka, soustredeni): 'sirka' : sirka, 'obrazky_predchozi' : obrazky_predchozi, 'obrazky_dalsi' : obrazky_dalsi, - 'preview' : preview, + 'upravy_popisku' : dovolit_upravy_popisku(galerie, request), 'form' : form, 'cesta': cesta_od_korene(galerie), }) @@ -179,7 +195,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/personalni/utils.py b/personalni/utils.py index 02e541da..f3c796e6 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,23 @@ 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) + +# TODO: organizator_osoby, organizator_uzivatele From 787a570117e3c8373487cb7bf32aeb7adcb57b8d Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Wed, 23 Apr 2025 23:02:35 +0200 Subject: [PATCH 02/16] =?UTF-8?q?Logika=20pro=20=C3=BA=C4=8Dastnick=C3=A9?= =?UTF-8?q?=20galerie=20ve=20views?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/views.py | 126 ++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 68 deletions(-) diff --git a/galerie/views.py b/galerie/views.py index 0e20055d..b1e720ca 100644 --- a/galerie/views.py +++ b/galerie/views.py @@ -1,6 +1,6 @@ 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 @@ -12,23 +12,27 @@ 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): +import logging +logger = logging.getLogger(__name__) + +def galerie_ke_zobrazeni(soustredeni: Soustredeni, 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 (resitel := resitel_uzivatele(request.user)) is not None: + if resitel.soustredeni_set.contains(soustredeni): + return (VZDY, UCASTNIK) + else: + 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 - # Superuživatelům úplně všechny galerie. - if request.user.is_superuser: return True + return galerie.zobrazit in galerie_ke_zobrazeni(soustredeni, request) - if galerie.zobrazit == VZDY: return True - if galerie.zobrazit == NIKDY: return False - if galerie.zobrazit == ORG and request.user.je_org: return True - if galerie.zobrazit == UCASTNIK: - if request.user.je_org: - return True - resitel = resitel_uzivatele(request.user) - if resitel is not None and resitel.soustredeni_set.contains(soustredeni): - return True - return False - -def dovolit_upravy_popisku(galerie, 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) @@ -45,20 +49,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') + 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 @@ -77,7 +80,6 @@ def nahled(request, pk, soustredeni): {'galerie' : galerie, 'podgalerie' : podgalerie, 'obrazky' : obrazky, - 'upravy_popisku' : dovolit_upravy_popisku(galerie, request), 'cesta': cesta, 'sourozenci': sourozenci, 'predchozi': predchozi, @@ -93,10 +95,41 @@ def detail(request, pk, fotka, soustredeni): NAHLEDU = 1 galerie = get_object_or_404(Galerie, pk=pk) + 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': @@ -106,49 +139,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("„Obrázek není v galerii/štítku“, ať už to znamená cokoliv…") - - - # 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 @@ -167,8 +157,8 @@ def detail(request, pk, fotka, soustredeni): 'obrazek' : obrazek, 'vyska' : vyska, 'sirka' : sirka, - 'obrazky_predchozi' : obrazky_predchozi, - 'obrazky_dalsi' : obrazky_dalsi, + 'obrazky_predchozi' : predchozi_obrazky, + 'obrazky_dalsi' : nasledujici_obrazky, 'upravy_popisku' : dovolit_upravy_popisku(galerie, request), 'form' : form, 'cesta': cesta_od_korene(galerie), From fa866170eed220de847c9c96dd4e262d33db2cc6 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 24 Apr 2025 00:15:31 +0200 Subject: [PATCH 03/16] =?UTF-8?q?Snad=20ne=C5=A1kodn=C3=A9=20=C3=BApravy?= =?UTF-8?q?=20templat=C5=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/templates/galerie/GalerieNahled.html | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/galerie/templates/galerie/GalerieNahled.html b/galerie/templates/galerie/GalerieNahled.html index 87794680..bd1f8d93 100644 --- a/galerie/templates/galerie/GalerieNahled.html +++ b/galerie/templates/galerie/GalerieNahled.html @@ -6,8 +6,11 @@ Galerie {{galerie.nazev}} {% block content %} - {% if galerie.zobrazit > 0 %} + {# FIXME: použít konstanty… #} + {% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %}
+ {% elif galerie.zobrazit == 3 %} +
{% endif %}

@@ -73,9 +76,13 @@ Galerie {{galerie.nazev}} {% endwith %} {% endif %} {% endif %} - {% if user.je_org and galerie.zobrazit > 0 %} + {% if user.je_org %}
- Vytvořit novou podgalerii + {% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %} + Vytvořit novou podgalerii, upravit galerii v adminu + {% else %} + Jestli chceš změnit pořadí podgalerií nebo přidat novou, nastav zobrazení jen pro orgy v adminu. + {% endif %}
{% endif %} @@ -120,8 +127,10 @@ Galerie {{galerie.nazev}} {% endif %} {% endif %} - {% if galerie.zobrazit > 0 %} + {% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %}

{# mam-org-only #} + {% elif galerie.zobrazit == 2 %} +
{# mam-resitel-only #} {% endif %} {% endblock content %} From 819b22511ae60f69a91389e61d6f9a870c48f82e Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 24 Apr 2025 00:39:58 +0200 Subject: [PATCH 04/16] =?UTF-8?q?Lehk=C3=A1=20=C3=BAprava=20chov=C3=A1n?= =?UTF-8?q?=C3=AD=20po=C5=99ad=C3=AD=20v=20podgaleri=C3=ADch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/templates/galerie/GalerieNahled.html | 44 ++++++++++---------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/galerie/templates/galerie/GalerieNahled.html b/galerie/templates/galerie/GalerieNahled.html index bd1f8d93..7c04f991 100644 --- a/galerie/templates/galerie/GalerieNahled.html +++ b/galerie/templates/galerie/GalerieNahled.html @@ -48,29 +48,31 @@ Galerie {{galerie.nazev}} {% if podgalerie %} {% with 22 as max_delka_nazvu %}
- {% for galerie in podgalerie %} - max_delka_nazvu %} - title="{{ galerie.nazev }}" - {% endif %} - class="podgalerie_nahled"> - {% if galerie.titulni_obrazek %} - {% with galerie.titulni_obrazek.obrazek_maly as obrazek %} - - {% endwith %} + {% for pgalerie in podgalerie %} + max_delka_nazvu %} + title="{{ pgalerie.nazev }}" {% endif %} -
- {{ galerie|truncatechars:max_delka_nazvu }} + class="podgalerie_nahled"> + {% if pgalerie.titulni_obrazek %} + {% with pgalerie.titulni_obrazek.obrazek_maly as obrazek %} + + {% endwith %} + {% endif %} +
+ {{ pgalerie|truncatechars:max_delka_nazvu }} +
+
+ {% if galerie.zobrazit == 1 or galerie.zobrazit == 2 %} + {% if user.je_org %} +
+ ({{pgalerie.poradi}}) + + + -
- - {% if user.je_org and galerie.zobrazit > 0 %} -
- ({{galerie.poradi}}) - + - - -
- {% endif %} + {% endif %} + {% endif %} {% endfor %}
{% endwith %} From 7f9318abca188cd296eeaed2dd807dd17cf70fa9 Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 24 Apr 2025 01:29:21 +0200 Subject: [PATCH 05/16] =?UTF-8?q?Admin=20akce=20u=C5=BE=20ned=C4=9Blaj?= =?UTF-8?q?=C3=AD=20=C3=BApln=C3=A9=20blbosti?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/admin.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/galerie/admin.py b/galerie/admin.py index 2b270163..c663287e 100644 --- a/galerie/admin.py +++ b/galerie/admin.py @@ -1,4 +1,4 @@ -from galerie.models import Obrazek, Galerie +from galerie.models import Obrazek, Galerie, VZDY, ORG, NIKDY, UCASTNIK from django.contrib import admin from django.http import HttpResponseRedirect from django import forms @@ -8,8 +8,9 @@ from django.db import models def zverejnit_fotogalerii(modeladmin, request, queryset): '''zverejni vybranou fotogalerii i jeji vsechny podgalerie''' + queryset = queryset.filter(zobrazit=ORG) for galerie in queryset: - galerie.zobrazit = 0 + galerie.zobrazit = VZDY galerie.save() zverejnit_fotogalerii(modeladmin, request, Galerie.objects.filter(galerie_up = galerie)) @@ -18,8 +19,9 @@ def zverejnit_fotogalerii(modeladmin, request, queryset): def prepnout_fotogalerii_do_org_rezimu(modeladmin, request, queryset): '''zneverjni vybranou fotogalerii i jeji vsechny podgalerie''' + queryset = queryset.filter(zobrazit=VZDY) for galerie in queryset: - galerie.zobrazit = 1 + galerie.zobrazit = ORG galerie.save() prepnout_fotogalerii_do_org_rezimu(modeladmin, request, Galerie.objects.filter(galerie_up = galerie)) From e1acc5affe3bb5ac7b38093b0714776478f6091f Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Thu, 24 Apr 2025 01:31:56 +0200 Subject: [PATCH 06/16] =?UTF-8?q?Smaz=C3=A1n=20nikdy=20nepou=C5=BEit=C3=BD?= =?UTF-8?q?=20k=C3=B3d=20model=C5=AF=20galerie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/models.py | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/galerie/models.py b/galerie/models.py index bca860a9..8122b477 100644 --- a/galerie/models.py +++ b/galerie/models.py @@ -100,25 +100,3 @@ class Galerie(models.Model): class Meta: verbose_name = 'Galerie' verbose_name_plural = 'Galerie' - - #def link_na_preview(self): - #"""Odkaz na galerii, používá se v admin rozhranní. """ - #return 'Preview' % self.id - #link_na_preview.allow_tags = True - #link_na_preview.short_description = 'Zobrazit galerii' -# - #def je_publikovano(self): - #"""Vraci True, pokud je tato galerie publikovana. """ - #if self.zobrazit == VZDY: - #return True - #if self.zobrazit == PODLE_CLANKU: - #for clanek in self.clanek_set.all(): - #if clanek.je_publikovano(): - #return True - #return False -# - #@staticmethod - #def publikovane_galerie(): - #"""Vraci galerie, ktere uz maji byt publikovane.""" - #clanky = Blog.models.Clanek.publikovane_clanky() - #return Galerie.objects.filter(Q(zobrazit=VZDY) | (Q(clanek__in=clanky) & Q(zobrazit=PODLE_CLANKU))).distinct() From e5a61d69fec91defa4e5e0f56a39c1ba52d9568d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Wed, 30 Apr 2025 20:06:22 +0200 Subject: [PATCH 07/16] =?UTF-8?q?R=C3=A1me=C4=8Dky=20kolem=20neve=C5=99ejn?= =?UTF-8?q?=C3=BDch=20obr=C3=A1zk=C5=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/templates/galerie/Galerie.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/galerie/templates/galerie/Galerie.html b/galerie/templates/galerie/Galerie.html index 9aa4b40b..e3d00865 100644 --- a/galerie/templates/galerie/Galerie.html +++ b/galerie/templates/galerie/Galerie.html @@ -46,6 +46,7 @@ {% block content %} +

{% for g in cesta %} @@ -133,4 +134,6 @@ {% endif %}

+ + {% endblock %} From 4334ad03238a41f3c1314ae8d295459e96e348e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Wed, 30 Apr 2025 20:09:15 +0200 Subject: [PATCH 08/16] =?UTF-8?q?R=C3=A1me=C4=8Dky=20kolem=20neve=C5=99ejn?= =?UTF-8?q?=C3=BDch=20obr=C3=A1zk=C5=AF=20(je=C5=A1t=C4=9B=20=C3=BApln?= =?UTF-8?q?=C4=9B=20neve=C5=99ejn=C3=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/templates/galerie/Galerie.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galerie/templates/galerie/Galerie.html b/galerie/templates/galerie/Galerie.html index e3d00865..1dcefeda 100644 --- a/galerie/templates/galerie/Galerie.html +++ b/galerie/templates/galerie/Galerie.html @@ -46,7 +46,7 @@ {% block content %} -
+

{% for g in cesta %} From fc83152169737995fd798358d15c0f312d18075d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Wed, 30 Apr 2025 20:10:55 +0200 Subject: [PATCH 09/16] =?UTF-8?q?R=C3=A1me=C4=8Dky=20kolem=20neve=C5=99ejn?= =?UTF-8?q?=C3=BDch=20obr=C3=A1zk=C5=AF=20(je=C5=A1t=C4=9B=20=C3=BApln?= =?UTF-8?q?=C4=9B=20neve=C5=99ejn=C3=A9,=20https://github.com/nvbn/thefuck?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/templates/galerie/Galerie.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galerie/templates/galerie/Galerie.html b/galerie/templates/galerie/Galerie.html index 1dcefeda..364d0b51 100644 --- a/galerie/templates/galerie/Galerie.html +++ b/galerie/templates/galerie/Galerie.html @@ -46,7 +46,7 @@ {% block content %} -
+

{% for g in cesta %} From b49ab06219ae529437861739bc5a7546a31df946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Wed, 30 Apr 2025 20:31:16 +0200 Subject: [PATCH 10/16] =?UTF-8?q?R=C3=A1me=C4=8Dky=20kolem=20neve=C5=99ejn?= =?UTF-8?q?=C3=BDch=20podgaleri=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/static/css/galerie.css | 5 +++++ galerie/templates/galerie/GalerieNahled.html | 2 +- galerie/templates/galerie/base.html | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/galerie/static/css/galerie.css b/galerie/static/css/galerie.css index 46df8552..46e02367 100644 --- a/galerie/static/css/galerie.css +++ b/galerie/static/css/galerie.css @@ -136,6 +136,11 @@ top: 160px; } +.podgalerie_nahled.mam-org-only, .podgalerie_nahled.mam-resitel-only { + margin: 10px; + padding: 0; +} + /* Odkazy na předchozí a následující podgalerii */ .galerie_predchozi_nasledujici { diff --git a/galerie/templates/galerie/GalerieNahled.html b/galerie/templates/galerie/GalerieNahled.html index 7c04f991..548d70ea 100644 --- a/galerie/templates/galerie/GalerieNahled.html +++ b/galerie/templates/galerie/GalerieNahled.html @@ -53,7 +53,7 @@ Galerie {{galerie.nazev}} {% if pgalerie.nazev|length > max_delka_nazvu %} title="{{ pgalerie.nazev }}" {% endif %} - class="podgalerie_nahled"> + class="podgalerie_nahled {% if pgalerie.zobrazit == 1 or pgalerie.zobrazit == 2 %}mam-org-only{% endif %}{% if pgalerie.zobrazit == 3 %}mam-resitel-only{% endif %}"> {% if pgalerie.titulni_obrazek %} {% with pgalerie.titulni_obrazek.obrazek_maly as obrazek %} + {% endblock %} From 138acfd430f25048c5b473b245b0cc76f9a45e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Wed, 30 Apr 2025 20:55:57 +0200 Subject: [PATCH 11/16] =?UTF-8?q?Mazan=C3=A1=20galerie=20by=20nem=C4=9Bla?= =?UTF-8?q?=20m=C3=ADt=20=C5=BE=C3=A1dn=C3=A9=20podgalerie=20(jinak=20moho?= =?UTF-8?q?u=20p=C5=99estat=20b=C3=BDt=20doklikateln=C3=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0015_alter_galerie_galerie_up.py | 19 +++++++++++++++++++ galerie/models.py | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 galerie/migrations/0015_alter_galerie_galerie_up.py diff --git a/galerie/migrations/0015_alter_galerie_galerie_up.py b/galerie/migrations/0015_alter_galerie_galerie_up.py new file mode 100644 index 00000000..2033c9af --- /dev/null +++ b/galerie/migrations/0015_alter_galerie_galerie_up.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.16 on 2025-04-30 18:53 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('galerie', '0014_alter_galerie_zobrazit'), + ] + + operations = [ + migrations.AlterField( + model_name='galerie', + name='galerie_up', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='galerie.galerie'), + ), + ] diff --git a/galerie/models.py b/galerie/models.py index 8122b477..692f7953 100644 --- a/galerie/models.py +++ b/galerie/models.py @@ -90,7 +90,7 @@ class Galerie(models.Model): titulni_obrazek = models.ForeignKey(Obrazek, blank = True, null = True, related_name = "+", on_delete = models.SET_NULL) zobrazit = models.IntegerField('Zobrazit?', default = ORG, choices = VIDITELNOST) galerie_up = models.ForeignKey('Galerie', blank = True, null = True, - on_delete=models.SET_NULL) + on_delete=models.PROTECT) soustredeni = models.ForeignKey(Soustredeni, blank = True, null = True, on_delete=models.PROTECT) poradi = models.IntegerField('Pořadí', blank = True, null = False, default = 0) From 506fb3015a8abbc5549c1203ce6fedd058af4fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Wed, 30 Apr 2025 21:00:29 +0200 Subject: [PATCH 12/16] =?UTF-8?q?Galerie=20nad=20sebou=20nemus=C3=AD=20m?= =?UTF-8?q?=C3=ADt=20soust=C5=99ed=C4=9Bn=C3=AD=20(mohou=20b=C3=BDt=20nap?= =?UTF-8?q?=C5=99.=20k=20t=C3=A9m=C3=A1tku),=20tak=C5=BEe=20umo=C5=BEn?= =?UTF-8?q?=C3=ADme=20i=20soustredeni=3DNone?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- galerie/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/galerie/views.py b/galerie/views.py index b1e720ca..fa2a15e9 100644 --- a/galerie/views.py +++ b/galerie/views.py @@ -15,10 +15,11 @@ from galerie.forms import KomentarForm, NewGalerieForm import logging logger = logging.getLogger(__name__) -def galerie_ke_zobrazeni(soustredeni: Soustredeni, request: HttpRequest) -> tuple[int]: +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) From 5787e1f1d86acf7bb9b6385ca2824921180dbf61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= Date: Wed, 30 Apr 2025 21:02:45 +0200 Subject: [PATCH 13/16] =?UTF-8?q?S=20galeri=C3=AD=20sma=C5=BE=20i=20obr?= =?UTF-8?q?=C3=A1zky?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0016_alter_obrazek_galerie.py | 19 +++++++++++++++++++ galerie/models.py | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 galerie/migrations/0016_alter_obrazek_galerie.py diff --git a/galerie/migrations/0016_alter_obrazek_galerie.py b/galerie/migrations/0016_alter_obrazek_galerie.py new file mode 100644 index 00000000..8c8e57af --- /dev/null +++ b/galerie/migrations/0016_alter_obrazek_galerie.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.16 on 2025-04-30 19:02 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('galerie', '0015_alter_galerie_galerie_up'), + ] + + operations = [ + migrations.AlterField( + model_name='obrazek', + name='galerie', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='galerie.galerie'), + ), + ] diff --git a/galerie/models.py b/galerie/models.py index 692f7953..44c1120e 100644 --- a/galerie/models.py +++ b/galerie/models.py @@ -56,7 +56,7 @@ class Obrazek(models.Model): nazev = models.CharField('Název', max_length=50, blank=True, null=True) popis = models.TextField('Popis', blank=True, null=True) datum_vlozeni = models.DateTimeField('Datum vložení', auto_now_add=True) - galerie = models.ForeignKey('Galerie', blank=True, null=True, on_delete=models.SET_NULL) + galerie = models.ForeignKey('Galerie', blank=True, null=True, on_delete=models.CASCADE) poradi = models.IntegerField('Pořadí', blank=True, null=True) def __str__(self): From 768d79654993cd61e27d955eb8687aaef2c403be Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 4 May 2025 13:57:26 +0200 Subject: [PATCH 14/16] =?UTF-8?q?Opravov=C3=A1tko:=20probl=C3=A9my=20ukazu?= =?UTF-8?q?j=C3=AD=20role?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- odevzdavatko/templates/odevzdavatko/tabulka.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odevzdavatko/templates/odevzdavatko/tabulka.html b/odevzdavatko/templates/odevzdavatko/tabulka.html index 41f91b14..dfe35bfc 100644 --- a/odevzdavatko/templates/odevzdavatko/tabulka.html +++ b/odevzdavatko/templates/odevzdavatko/tabulka.html @@ -27,7 +27,7 @@ Do data (včetně): {{ filtr.reseni_do }} {% for p in problemy %}

{% endfor %} From af298af58dbc76e312c1c28aa6adafcaf880909b Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 4 May 2025 18:03:22 +0200 Subject: [PATCH 15/16] =?UTF-8?q?Odevzd=C3=A1v=C3=A1tko:=20zobrazen=C3=AD?= =?UTF-8?q?=20rol=C3=AD=20u=20probl=C3=A9m=C5=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- odevzdavatko/static/css/odevzdavatko.css | 10 +++++++ odevzdavatko/templates/odevzdavatko/base.html | 6 +++++ .../templates/odevzdavatko/tabulka.html | 13 +++++++-- odevzdavatko/templatetags/orgove.py | 27 +++++++++++++++++++ personalni/utils.py | 25 ++++++++++++++++- 5 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 odevzdavatko/static/css/odevzdavatko.css create mode 100644 odevzdavatko/templates/odevzdavatko/base.html create mode 100644 odevzdavatko/templatetags/orgove.py diff --git a/odevzdavatko/static/css/odevzdavatko.css b/odevzdavatko/static/css/odevzdavatko.css new file mode 100644 index 00000000..f38833d8 --- /dev/null +++ b/odevzdavatko/static/css/odevzdavatko.css @@ -0,0 +1,10 @@ +.odevzdavatko-role { + font-size: 0.8em; + + .true { + color: var(--hlavni-oranzova); + } + .false { + 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 dfe35bfc..87670466 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 %} {% 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 f3c796e6..4a8b9a38 100644 --- a/personalni/utils.py +++ b/personalni/utils.py @@ -201,4 +201,27 @@ def resitel_uzivatele(u: User | AnonymousUser) -> Resitel | None: if o is None: return None return resitel_osoby(o) -# TODO: organizator_osoby, organizator_uzivatele +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 From c274c8110c6b5f49949e346951058799ac4c0b7f Mon Sep 17 00:00:00 2001 From: "Pavel \"LEdoian\" Turinsky" Date: Sun, 4 May 2025 18:27:38 +0200 Subject: [PATCH 16/16] =?UTF-8?q?Role=20v=20odevzd=C3=A1v=C3=A1tku:=20P?= =?UTF-8?q?=C5=99ejmenov=C3=A1n=C3=AD=20t=C5=99=C3=ADd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- odevzdavatko/static/css/odevzdavatko.css | 4 ++-- odevzdavatko/templates/odevzdavatko/tabulka.html | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/odevzdavatko/static/css/odevzdavatko.css b/odevzdavatko/static/css/odevzdavatko.css index f38833d8..9a61b259 100644 --- a/odevzdavatko/static/css/odevzdavatko.css +++ b/odevzdavatko/static/css/odevzdavatko.css @@ -1,10 +1,10 @@ .odevzdavatko-role { font-size: 0.8em; - .true { + .vyrazne { color: var(--hlavni-oranzova); } - .false { + .nevyrazne { color: #aaa; } } diff --git a/odevzdavatko/templates/odevzdavatko/tabulka.html b/odevzdavatko/templates/odevzdavatko/tabulka.html index 87670466..4167c4b5 100644 --- a/odevzdavatko/templates/odevzdavatko/tabulka.html +++ b/odevzdavatko/templates/odevzdavatko/tabulka.html @@ -31,9 +31,9 @@ Do data (včetně): {{ filtr.reseni_do }} {{ p }} {% spaceless %} - A - G - O + A + G + O {% endspaceless %}
{# TODO: Přehled řešení k problému, odkázaný odsud? #} - {{ p }} + {{ p }}{# TODO: role? e.g. Úloha 3.3 (role: AG) jakože autor a garant #}
{# TODO: Přehled řešení k problému, odkázaný odsud? #} - {{ p }}{# TODO: role? e.g. Úloha 3.3 (role: AG) jakože autor a garant #} + {{ p }} + + {% spaceless %} + A + G + O + {% endspaceless %} + +