From 291d4e2d568721645ec2c676159d732a671bf343 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 22 Jan 2025 13:12:09 +0100 Subject: [PATCH 01/30] grey na opacity - a zarovnani do stran --- personalni/static/personalni/jak_se_dozvedeli.css | 3 ++- personalni/templates/personalni/jak_se_dozvedeli.html | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/personalni/static/personalni/jak_se_dozvedeli.css b/personalni/static/personalni/jak_se_dozvedeli.css index 15a47b80..07a10997 100644 --- a/personalni/static/personalni/jak_se_dozvedeli.css +++ b/personalni/static/personalni/jak_se_dozvedeli.css @@ -26,9 +26,10 @@ .tres { flex: 1; + text-align: end; } - .grey { + .half-opacity { opacity: 0.5; } } diff --git a/personalni/templates/personalni/jak_se_dozvedeli.html b/personalni/templates/personalni/jak_se_dozvedeli.html index 6695f94c..4f667353 100644 --- a/personalni/templates/personalni/jak_se_dozvedeli.html +++ b/personalni/templates/personalni/jak_se_dozvedeli.html @@ -18,7 +18,7 @@ {% for osoba in object_list %} <div class="osoba"> <div class="uno">{{ osoba.jmeno }} {{ osoba.prijmeni }}</div> - <div class="dos {% if not osoba.jak_se_dozvedeli %}grey{% endif %}">{% if osoba.jak_se_dozvedeli %} {{osoba.jak_se_dozvedeli}} {% else %} NEZADÁNO {% endif %}</div> + <div class="dos {% if not osoba.jak_se_dozvedeli %}half-opacity{% endif %}">{% if osoba.jak_se_dozvedeli %} {{osoba.jak_se_dozvedeli}} {% else %} NEZADÁNO {% endif %}</div> <div class="tres">{{ osoba.datum_registrace }}</div> </div> {% endfor %} From 5a1eedb7b192ab15371e2bfcd9fcb430815170b9 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 29 Jan 2025 18:17:00 +0100 Subject: [PATCH 02/30] ruzne exporty resitelu --- .../personalni/profil/export_lidi.html | 88 +++++++++++++ .../personalni/profil/orgorozcestnik.html | 7 ++ personalni/urls.py | 22 ++++ personalni/views.py | 118 +++++++++++++++++- tvorba/utils.py | 22 ++++ 5 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 personalni/templates/personalni/profil/export_lidi.html diff --git a/personalni/templates/personalni/profil/export_lidi.html b/personalni/templates/personalni/profil/export_lidi.html new file mode 100644 index 00000000..96778449 --- /dev/null +++ b/personalni/templates/personalni/profil/export_lidi.html @@ -0,0 +1,88 @@ +{% extends "base.html" %} + + +{% block content %} + +<h2><strong>Export lidí</strong></h2> + +<select name="select-one" id="select-one"> + <option value="0">---</option> + <option value="1">Řešitelé čísla</option> + <option value="2">Řešitelé ročníku</option> + <option value="3">Všichni řešitelé, kteří ještě neodmaturovali</option> + <option value="4">Organizátoři soustředění</option> +</select> + +<select name="select-two" id="select-two"> +<!-- will be filled with ajax --> +</select> + +<button id="download-button">Stáhnout</button> + +<script defer> + const select_one = document.getElementById("select-one") + const select_two = document.getElementById("select-two") + const download_button = document.getElementById("download-button") + + download_button.style.display = 'none' + select_two.style.display = 'none' + + const fetch_dict_string = '{{ typy_exportu|safe }}' + const fetch_dict = JSON.parse(fetch_dict_string) + + + select_one.addEventListener('change', (e) => { + value = e.target.value + select_two.style.display = 'none' + select_two.innerHTML = '' + // puvodni stav + if (value == 0) { + download_button.style.display = 'none' + select_two.style.display = 'none' + return + } + // v tomto pripade muzeme rovnou stahnout + if (!(value in fetch_dict)) { + download_button.style.display = 'block' + select_two.style.display = 'none' + return + } + download_button.style.display = 'none' + fetch("/profil/exporty_lidi/get/" + value) + .then(response => response.json()) + .then(data => { + const option = document.createElement('option') + option.value = 0 + option.text = '---' + select_two.appendChild(option) + for (const [key, value] of Object.entries(data)) { + const option = document.createElement('option') + option.value = value["id"] + option.text = value["display"] + select_two.appendChild(option) + } + select_two.style.display = 'block' + }) + + }) + + select_two.addEventListener('change', (e) => { + value = e.target.value + if (value == 0) { + download_button.style.display = 'none' + return + } + download_button.style.display = 'block' + }) + + download_button.addEventListener('click', (e) => { + if (select_two.innerHTML == '') { + window.location.href = "/profil/exporty_lidi/get_csv_only_one_step/" + select_one.value + } else { + window.location.href = "/profil/exporty_lidi/get_csv/" + select_one.value + "/" + select_two.value + } + + }) +</script> + +{% endblock %} diff --git a/personalni/templates/personalni/profil/orgorozcestnik.html b/personalni/templates/personalni/profil/orgorozcestnik.html index 2dbc853b..bd73fa6e 100644 --- a/personalni/templates/personalni/profil/orgorozcestnik.html +++ b/personalni/templates/personalni/profil/orgorozcestnik.html @@ -107,6 +107,13 @@ </li> </ul> +<hr /> +<h2><strong>Exporty dat lidí v semináří</strong></h2> + +<ul> + <li><a href="exporty_lidi">dostupné exporty</a></li> +</ul> + <hr /> <p>Nemůžeš najít, co hledáš? Může to být v <a href="{% url 'admin:index' %}">administračním rozhraní webu</a>.</p> {% endblock content %} diff --git a/personalni/urls.py b/personalni/urls.py index 1805bbfe..9e173aae 100644 --- a/personalni/urls.py +++ b/personalni/urls.py @@ -38,6 +38,28 @@ urlpatterns = [ 'org/propagace/jak-se-dozvedeli/', org_required(views.JakSeDozvedeliView.as_view()), name='jak_se_dozvedeli' + ), + + # export dat o řešitelích + path( + 'profil/exporty_lidi', + org_required(views.ExportLidiView.as_view()), + name='exporty_lidi', + ), + path( + 'profil/exporty_lidi/get/<int:type>', + org_required(views.get_export_options), + name='exporty_lidi_options', + ), + path( + 'profil/exporty_lidi/get_csv_only_one_step/<int:type>', + org_required(views.download_export_csv_only_first_step), + name='exporty_lidi_data', + ), + path( + 'profil/exporty_lidi/get_csv/<int:type>/<int:id>', + org_required(views.download_export_csv), + name='exporty_lidi_download', ) ] diff --git a/personalni/views.py b/personalni/views.py index 49442c2d..5ae97e24 100644 --- a/personalni/views.py +++ b/personalni/views.py @@ -20,13 +20,16 @@ from django.utils import timezone import personalni.models as m from soustredeni.models import Soustredeni from odevzdavatko.models import Hodnoceni -from tvorba.models import Clanek, Uloha, Tema +from tvorba.models import Clanek, Uloha, Tema, Cislo, Rocnik +import tvorba.utils as tvorba_utils from various.models import Nastaveni from .forms import PrihlaskaForm, ProfileEditForm, PoMaturiteProfileEditForm from datetime import date import logging import csv +from enum import Enum +import json from various.views.pomocne import formularOKView from various.autentizace.views import LoginView @@ -140,7 +143,54 @@ class OrgoRozcestnikView(TemplateView): #content_type = 'text/plain; charset=UTF8' #XXX + +class PrvniTypExportu(Enum): + CISLA = 1 + ROCNIKU = 2 + SOUSTREDENI = 4 +class ExportLidiView(TemplateView): + template_name = 'personalni/profil/export_lidi.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['typy_exportu'] = json.dumps({member.value: member.name.lower().capitalize() for member in PrvniTypExportu}) + return context + + +def get_export_options(request, type): + if type == PrvniTypExportu.CISLA.value: + data = [{"id": c.id, "display": str(c)} for c in Cislo.objects.all()] + if type == PrvniTypExportu.ROCNIKU.value: + data = [{"id": r.id, "display": str(r)} for r in Rocnik.objects.all()] + if type == PrvniTypExportu.SOUSTREDENI.value: + data = [{"id": s.id, "display": str(s)} for s in Soustredeni.objects.all()] + return HttpResponse(json.dumps(data), content_type='application/json') + +def download_export_csv_only_first_step(request, type): + if type == 3: + response = dataResiteluCsvResponse(tvorba_utils.resitele_co_neodmaturovali()) + response['Content-Disposition'] = 'attachment; filename="resitele_co_neodmaturovali.csv"' + return response + +def download_export_csv(request, type, id): + if type == PrvniTypExportu.CISLA.value: + response = dataResiteluCsvResponse(tvorba_utils.resi_cislo(Cislo.objects.get(id=id))) + name = str(Cislo.objects.get(id=id)).replace(" ", "_") + "_resitele_cisla.csv" + response['Content-Disposition'] = 'attachment; filename="' + name + '"' + return response + if type == PrvniTypExportu.ROCNIKU.value: + response = dataResiteluCsvResponse(tvorba_utils.resi_v_rocniku(Rocnik.objects.get(id=id))) + name = str(Rocnik.objects.get(id=id)).replace(" ", "_") + "_resitele_rocniku.csv" + response['Content-Disposition'] = 'attachment; filename="' + name + '"' + return response + if type == PrvniTypExportu.SOUSTREDENI.value: + soustredeni = Soustredeni.objects.get(id=id) + organizatori = soustredeni.organizatori.all() + response = dataOsobCsvResponse(organizatori) + name = str(soustredeni).replace(" ", "_") + "_organizatori_soustredeni.csv" + response['Content-Disposition'] = 'attachment; filename="' + name + '"' + return response class ResitelView(LoginRequiredMixin,generic.DetailView): model = m.Resitel @@ -470,3 +520,69 @@ def dataResiteluCsvResponse(queryset, columns=None, with_header=True): writer.writerows(queryset_list) return response + +def dataOsobCsvResponse(queryset, columns=None, with_header=True): + """Pomocná funkce pro vracení dat osob jako CSV. Musí dostat správný QuerySet, který dává Ososby""" + + default_columns = ( + 'id', + 'osoba__jmeno', + 'osoba__prijmeni', + 'osoba__prezdivka', + 'osoba__email', + 'osoba__telefon', + 'osoba__user__username', + 'osoba__datum_narozeni', + 'osoba__osloveni', + 'osoba__ulice', + 'osoba__mesto', + 'osoba__psc', + 'osoba__stat', + 'osoba__jak_se_dozvedeli', + 'osoba__poznamka', + 'osoba__datum_registrace', + 'osoba__datum_souhlasu_udaje', + 'osoba__datum_souhlasu_zasilani', + ) + if columns is None: columns = default_columns + + field_name_overrides = { + # Zrušení prefixu "osoba__" + 'osoba__jmeno': 'jmeno', + 'osoba__prijmeni': 'prijmeni', + 'osoba__prezdivka': 'prezdivka', + 'osoba__email': 'email', + 'osoba__telefon': 'telefon', + 'osoba__user__username': 'user', + 'osoba__datum_narozeni': 'datum_narozeni', + 'osoba__osloveni': 'osloveni', + 'osoba__ulice': 'ulice', + 'osoba__mesto': 'mesto', + 'osoba__psc': 'psc', + 'osoba__stat': 'stat', + 'osoba__jak_se_dozvedeli': 'jak_se_dozvedeli', + 'osoba__poznamka': 'poznamka', + 'osoba__datum_registrace': 'datum_registrace', + 'osoba__datum_souhlasu_udaje': 'datum_souhlasu_udaje', + 'osoba__datum_souhlasu_zasilani':'datum_souhlasu_zasilani', + } + + def get_field_name(column_name): + if column_name in field_name_overrides: + return field_name_overrides[column_name] + return column_name + + response = HttpResponse(content_type='text/csv') + writer = csv.writer(response) + + # První řádek je záhlaví + if with_header: + writer.writerow(map(get_field_name, columns)) + + # Data: + queryset_list = queryset.values_list(*columns) + writer.writerows(queryset_list) + + return response + + diff --git a/tvorba/utils.py b/tvorba/utils.py index c2feadd9..1c8076c8 100644 --- a/tvorba/utils.py +++ b/tvorba/utils.py @@ -27,6 +27,28 @@ def resi_v_rocniku(rocnik, cislo=None): reseni__hodnoceni__deadline_body__cislo__rocnik=rocnik, reseni__hodnoceni__deadline_body__cislo__poradi__lte=cislo.poradi ).distinct() + +def resi_cislo(cislo): + """ Vrátí seznam řešitelů, co vyřešili nějaký problém v daném čísle. + Parametry: + cislo (typu Cislo) číslo, ve kterém chci řešitele, co něco odevzdali + Výstup: + QuerySet objektů typu Resitel + + Nejsem si moc jistý, jestli to tak funguje... Vašek """ + + return personalni.models.Resitel.objects.filter( + reseni__hodnoceni__deadline_body__cislo=cislo + ).distinct() + +def resitele_co_neodmaturovali(): + """ Vrátí seznam řešitelů, co ještě neodmaturovali. + Výstup: + QuerySet objektů typu Resitel """ + from datetime import datetime + current_year = datetime.now().year + '''Člověk odmaturuje když je jeho rok maturity menší nebo stejný jako aktuální rok? ''' + return personalni.models.Resitel.objects.filter(rok_maturity__gte=current_year) def aktivniResitele(cislo, pouze_letosni=False): From dcba5b6b308aeaafaff880d688f8be57b45488b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Wed, 19 Feb 2025 18:38:38 +0100 Subject: [PATCH 03/30] =?UTF-8?q?Hlasov=C3=A1n=C3=AD=20m=C3=A1=20m=C3=ADt?= =?UTF-8?q?=20i=20osobu,=20nejen=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0023_hlasovani_ucastnik_osoba.py | 20 +++++++++++++++++++ prednasky/models.py | 1 + prednasky/views.py | 1 + 3 files changed, 22 insertions(+) create mode 100644 prednasky/migrations/0023_hlasovani_ucastnik_osoba.py diff --git a/prednasky/migrations/0023_hlasovani_ucastnik_osoba.py b/prednasky/migrations/0023_hlasovani_ucastnik_osoba.py new file mode 100644 index 00000000..970a6c24 --- /dev/null +++ b/prednasky/migrations/0023_hlasovani_ucastnik_osoba.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.16 on 2025-02-19 17:31 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('personalni', '0019_rename_upozorneni_resitel_upozornovat_na_opravy_reseni'), + ('prednasky', '0022_preklep_u_odpovedi_hlasovanioznalostech'), + ] + + operations = [ + migrations.AddField( + model_name='hlasovani', + name='ucastnik_osoba', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='personalni.osoba'), + ), + ] diff --git a/prednasky/models.py b/prednasky/models.py index f508ca7e..b49a3a69 100644 --- a/prednasky/models.py +++ b/prednasky/models.py @@ -88,6 +88,7 @@ class Hlasovani(models.Model): #: že všechna předchozí hlasování zde mají náhodný string…) #: TODO Změnit to na Osobu* ucastnik = models.CharField("Účastník", max_length=100) + ucastnik_osoba = models.ForeignKey(Osoba, on_delete=models.CASCADE, blank=False, null=True) seznam = models.ForeignKey(Seznam, null=True, on_delete=models.SET_NULL) def __str__(self): diff --git a/prednasky/views.py b/prednasky/views.py index 43ac983b..5bb33c14 100644 --- a/prednasky/views.py +++ b/prednasky/views.py @@ -64,6 +64,7 @@ def newPrednaska(request: HttpRequest) -> HttpResponse: prednaska=prednaska, body=form.cleaned_data['body'], ucastnik=ucastnik, + ucastnik_osoba=osoba, seznam=seznam, ) From a8e9f03cc1f33987453b9c23eb18720eea10e3bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Wed, 19 Feb 2025 18:41:13 +0100 Subject: [PATCH 04/30] =?UTF-8?q?<div>y=20kolem=20jednotliv=C3=BDch=20hlas?= =?UTF-8?q?ov=C3=A1n=C3=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/templates/prednasky/base.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prednasky/templates/prednasky/base.html b/prednasky/templates/prednasky/base.html index 326370f1..2a63abd1 100644 --- a/prednasky/templates/prednasky/base.html +++ b/prednasky/templates/prednasky/base.html @@ -14,6 +14,7 @@ <p>Obtížnost 1 je nejlehčí, 3 nejtěžší.</p> {{ form_set_prednasky.management_form }} {% for f, p in formy_a_prednasky %} + <div class="hlasovani-prednaska"> <h4>{{p.nazev}} ({{p.org}})</h4> <p class="textprednasky">{{p.anotace | linebreaksbr}}</p> <label>Obor: </label> {{p.obor}}<br> @@ -22,17 +23,20 @@ <br> {{ f }} <br> + </div> {% empty %} Nejsou žádné přednášky o kterých by šlo hlasovat. {% endfor %} {{ form_set_znalosti.management_form }} {% for f, z in formy_a_znalosti %} + <div class="hlasovani-znalost"> {% if forloop.first %}<hr/><h3>Jak moc znáš následující?</h3>{% endif %} <h4>{{z.nazev}}</h4> <p class="textznalosti">{{z.text | linebreaksbr}}</p> {{ f }} <br> + </div> {% endfor %} <input type="submit" value="Odeslat"/> </form> From 7a70b9dcff1a27205e42e514bda37af22c723cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Wed, 19 Feb 2025 18:45:24 +0100 Subject: [PATCH 05/30] =?UTF-8?q?Pojmenovan=C3=A9=20URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/templates/prednasky/metaseznam_prednasek.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prednasky/templates/prednasky/metaseznam_prednasek.html b/prednasky/templates/prednasky/metaseznam_prednasek.html index dfc13caf..d34b5fa7 100644 --- a/prednasky/templates/prednasky/metaseznam_prednasek.html +++ b/prednasky/templates/prednasky/metaseznam_prednasek.html @@ -14,7 +14,7 @@ {% else %} <a href="/prednasky/seznam_prednasek/{{seznam.id}}">Seznam přednášek na soustředění {{seznam.soustredeni.misto}} </a> {% endif %} - <a href="/prednasky/seznam_prednasek/{{seznam.id}}/hlasovani.csv">Export</a> + <a href='{% url "seznam-export-csv" seznam=seznam.id %}'>Export</a> </li> {% endfor %} </ul> From 4d5800f3b8a363a2b29a9777e15a1ecbde3dc1b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Wed, 19 Feb 2025 18:53:44 +0100 Subject: [PATCH 06/30] =?UTF-8?q?Pouze=20CSV=20export=20p=C5=99edn=C3=A1?= =?UTF-8?q?=C5=A1ek=20(smaz=C3=A1n=C3=AD=20ostatn=C3=ADch)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../prednasky/metaseznam_prednasek.html | 10 ++-- prednasky/urls.py | 10 ---- prednasky/views.py | 58 ------------------- 3 files changed, 5 insertions(+), 73 deletions(-) diff --git a/prednasky/templates/prednasky/metaseznam_prednasek.html b/prednasky/templates/prednasky/metaseznam_prednasek.html index d34b5fa7..1216e2dc 100644 --- a/prednasky/templates/prednasky/metaseznam_prednasek.html +++ b/prednasky/templates/prednasky/metaseznam_prednasek.html @@ -2,19 +2,19 @@ {% block content %} <h1>{% block nadpis1a %} - Hlasování o přednáškách + Výsledky hlasování o přednáškách {% endblock %}</h1> {# Projdi vsechny seznamy #} <div class="mam-org-only"> <ul> {% for seznam in object_list %} <li> - {% if seznam.stav == 1 %} {# STAV_NAHRH = 1 #} - <a href="/prednasky/seznam_prednasek/{{seznam.id}}">Návrh přednášek na soustředění {{seznam.soustredeni.misto}} </a> + {% if seznam.stav == seznam.Stav.NAVRH %} + Návrh přednášek na soustředění {{seznam.soustredeni.misto}} {% else %} - <a href="/prednasky/seznam_prednasek/{{seznam.id}}">Seznam přednášek na soustředění {{seznam.soustredeni.misto}} </a> + Seznam přednášek na soustředění {{seznam.soustredeni.misto}} {% endif %} - <a href='{% url "seznam-export-csv" seznam=seznam.id %}'>Export</a> + <a href='{% url "seznam-export-csv" seznam=seznam.id %}'>(CSV)</a> </li> {% endfor %} </ul> diff --git a/prednasky/urls.py b/prednasky/urls.py index 24d8535a..5c0201d8 100644 --- a/prednasky/urls.py +++ b/prednasky/urls.py @@ -12,19 +12,9 @@ urlpatterns = [ 'prednasky/metaseznam_prednasek', org_required(views.MetaSeznamListView.as_view()), name='metaseznam-list'), - # path( - # 'prednasky/seznam_prednasek/<int:seznam>/export', - # org_required(views.SeznamExportView), - # name='seznam-export' - # ), path( 'prednasky/seznam_prednasek/<int:seznam>/hlasovani.csv', org_required(views.PrednaskyExportView), name='seznam-export-csv' ), - path( - 'prednasky/seznam_prednasek/<int:seznam>/', - org_required(views.SeznamListView.as_view()), - name='seznam-list' - ), ] diff --git a/prednasky/views.py b/prednasky/views.py index 5bb33c14..53ee9b54 100644 --- a/prednasky/views.py +++ b/prednasky/views.py @@ -133,64 +133,6 @@ class MetaSeznamListView(generic.ListView): template_name = 'prednasky/metaseznam_prednasek.html' -class SeznamListView(generic.ListView): - """ - Náhled na to, kolik má která přednáška v :py:class:`Seznamu <prednasky.models.Seznam>` :py:class:`hlasů <prednasky.models.Hlasovani.Body>`. - (Je otázka, zda tento View vůbec chceme. Pokud ano, hodilo by se do něj přidat i znalosti.) - """ - template_name = 'prednasky/seznam_prednasek.html' - - def get_queryset(self): - self.seznam = get_object_or_404(Seznam, id=self.kwargs["seznam"]) - prednasky = Prednaska.objects.filter(seznamy=self.seznam).order_by( - 'org__osoba__user__first_name', 'org__osoba__user__last_name' - ) - return prednasky - - # FIXME nahradit anotaci s filtrem po prechodu na Django 2.2 - def get_context_data(self,**kwargs): - context = super(SeznamListView, self).get_context_data(**kwargs) - - # hlasovani se vztahuje k nejnovejsimu soustredeni - sous = Soustredeni.objects.first() - seznam = Seznam.objects.filter(soustredeni = sous, stav=Seznam.Stav.NAVRH).first() - - for obj in self.object_list: - hlasovani_set = obj.hlasovani_set.filter(seznam=seznam).only('body') - obj.body = sum(map(lambda x: x.body,hlasovani_set)) - - return context - - -# def SeznamExportView(request, seznam): -# """Vypíše výsledky hlasování ve formátu pro prologovský optimalizátor""" -# # TODO zřejmě se nepoužívá, časem vyřadit? nahradit tabulkou vhodnější pro -# # lidi? -# hlasovani = Hlasovani.objects.filter(seznam=seznam) -# prednasky = Prednaska.objects.filter(seznamy=seznam) -# orgove = set(p.org for p in prednasky) -# ucastnici = set(h.ucastnik for h in hlasovani) -# -# for p in prednasky: -# p.body = [] -# for u in ucastnici: -# try: -# p.body.append(hlasovani.get(ucastnik=u, prednaska=p).body) -# except ObjectDoesNotExist: -# # účastník nehlasoval -# p.body.append("?") -# -# for h in hlasovani: -# h.ucastnik = hash(h.ucastnik) -# -# return render( -# request, -# 'prednasky/seznam_prednasek_export.txt', -# {"hlasovani": hlasovani, "prednasky": prednasky, "orgove": orgove}, -# content_type="text/plain" -# ) - - def PrednaskyExportView(request: HttpRequest, seznam: int, **kwargs) -> HttpResponse: """ Vrátí všechna :py:class:`Hlasování <prednasky.models.Hlasovani>` From 52c5d18595c6410cbe412bbc0a25e77f23bbc7e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Fri, 21 Feb 2025 16:42:11 +0100 Subject: [PATCH 07/30] =?UTF-8?q?Nekonzumovateln=C3=BD=20kontext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prednasky/views.py b/prednasky/views.py index 53ee9b54..8bc66e49 100644 --- a/prednasky/views.py +++ b/prednasky/views.py @@ -117,8 +117,8 @@ def newPrednaska(request: HttpRequest) -> HttpResponse: 'prednasky/base.html', { 'form_set_prednasky': form_set_prednasky, 'form_set_znalosti': form_set_znalosti, - 'formy_a_prednasky': zip(form_set_prednasky, prednasky), - 'formy_a_znalosti': zip(form_set_znalosti, znalosti), + 'formy_a_prednasky': list(zip(form_set_prednasky, prednasky)), + 'formy_a_znalosti': list(zip(form_set_znalosti, znalosti)), } ) From a0ee2383340758a704c06f2f9110dc793ef589f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Fri, 21 Feb 2025 16:42:57 +0100 Subject: [PATCH 08/30] =?UTF-8?q?Z=C3=A1vorky=20nechci=20jako=20sou=C4=8D?= =?UTF-8?q?=C3=A1st=20odkazu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/templates/prednasky/metaseznam_prednasek.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prednasky/templates/prednasky/metaseznam_prednasek.html b/prednasky/templates/prednasky/metaseznam_prednasek.html index 1216e2dc..541c7bb2 100644 --- a/prednasky/templates/prednasky/metaseznam_prednasek.html +++ b/prednasky/templates/prednasky/metaseznam_prednasek.html @@ -14,7 +14,7 @@ {% else %} Seznam přednášek na soustředění {{seznam.soustredeni.misto}} {% endif %} - <a href='{% url "seznam-export-csv" seznam=seznam.id %}'>(CSV)</a> + (<a href='{% url "seznam-export-csv" seznam=seznam.id %}'>CSV</a>) </li> {% endfor %} </ul> From 061a699f62978d48c4a6b003f692d000f8ab103e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Fri, 21 Feb 2025 17:00:35 +0100 Subject: [PATCH 09/30] =?UTF-8?q?Chyb=C4=9Bj=C3=ADc=C3=AD=20backticky?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/admin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prednasky/admin.py b/prednasky/admin.py index 07615f43..ff8e9464 100644 --- a/prednasky/admin.py +++ b/prednasky/admin.py @@ -97,7 +97,7 @@ admin.site.register(Seznam, SeznamAdmin) class PrednaskaAdmin(VersionAdmin): - """ Admin pro :py:class:`Přednášku <prednasky.models.Prednaska> """ + """ Admin pro :py:class:`Přednášku <prednasky.models.Prednaska>` """ list_display = ['nazev', 'org', 'obor'] list_filter = ['org', 'obor'] search_fields = ['nazev'] @@ -138,7 +138,7 @@ admin.site.register(Prednaska, PrednaskaAdmin) class ZnalostAdmin(PrednaskaAdmin): # Trochu hack, ať nemusím vypisovat všechno znovu """ - Admin pro :py:class:`Znalost <prednasky.models.Znalost> + Admin pro :py:class:`Znalost <prednasky.models.Znalost>` TODO předělat, aby nedědila z :py:class:`prednasky.admin.PrednaskaAdmin`, ale společné věci byly zvlášť """ list_display = ("__str__",) From 46e2bb6b12197dd882d84dfcadbe2ff6fb3b72fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Fri, 21 Feb 2025 17:17:14 +0100 Subject: [PATCH 10/30] =?UTF-8?q?pro=20nav=C3=ADc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/forms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prednasky/forms.py b/prednasky/forms.py index 7b0e9739..e1543f80 100644 --- a/prednasky/forms.py +++ b/prednasky/forms.py @@ -3,7 +3,7 @@ from django import forms from .models import Hlasovani, HlasovaniOZnalostech class HlasovaniPrednaskaForm(forms.Form): - """ :py:class:`Formulář <django.forms.Form>` pro pro :py:class:`Hlasování <prednasky.models.Hlasovani>` o jedné :py:class:`Přednášce <prednasky.models.Prednaska>` + """ :py:class:`Formulář <django.forms.Form>` pro :py:class:`Hlasování <prednasky.models.Hlasovani>` o jedné :py:class:`Přednášce <prednasky.models.Prednaska>` (neobsahuje téměř nic, většina se musí doplnit jiným způsobem) """ @@ -17,7 +17,7 @@ class HlasovaniPrednaskaForm(forms.Form): HlasovaniPrednaskaFormSet = forms.formset_factory(HlasovaniPrednaskaForm, extra=0) class HlasovaniZnalostiForm(forms.Form): - """ :py:class:`Formulář <django.forms.Form>` pro pro :py:class:`HlasováníOZnalostech <prednasky.models.HlasovaniOZnalostech>` o jedné :py:class:`Znalosti <prednasky.models.Znalost>` + """ :py:class:`Formulář <django.forms.Form>` pro :py:class:`HlasováníOZnalostech <prednasky.models.HlasovaniOZnalostech>` o jedné :py:class:`Znalosti <prednasky.models.Znalost>` (neobsahuje téměř nic, většina se musí doplnit jiným způsobem) """ From 19448ce6c0ba64db3953bbf1acefa785a3c87487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Sat, 22 Feb 2025 16:38:11 +0100 Subject: [PATCH 11/30] =?UTF-8?q?Hlasit=C4=9Bj=C5=A1=C3=AD=20v=C3=BDstup?= =?UTF-8?q?=20p=C5=99i=20odstran=C4=9Bn=C3=A9=20znalosti/p=C5=99edn=C3=A1?= =?UTF-8?q?=C5=A1ce=20v=20exportu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/views.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/prednasky/views.py b/prednasky/views.py index 8bc66e49..e5adeec1 100644 --- a/prednasky/views.py +++ b/prednasky/views.py @@ -157,6 +157,8 @@ def PrednaskyExportView(request: HttpRequest, seznam: int, **kwargs) -> HttpResp # A po inicializaci sloupců vyplníme tabulku table: [str, list[str|Prednaska|Znalost,]] = {} + errors = [] + for h in hlasovani: if h.ucastnik not in table: # Pokud jsme účastníka ještě neviděli, předgenerujeme si jeho řádek table[h.ucastnik] = [h.ucastnik] + ([""] * width) @@ -164,7 +166,7 @@ def PrednaskyExportView(request: HttpRequest, seznam: int, **kwargs) -> HttpResp if h.prednaska.id in prednasky_map: table[h.ucastnik][prednasky_map[h.prednaska.id]] = h.body else: - pass # TODO Padat hlasitě? + errors.append(f"Přednáška {h.prednaska.id} ({h.prednaska}) dostala od Účastníka {h.ucastnik} následující hodnocení: {h.body}") for h in hlasovani_o_znalostech: ucastnik = str(h.ucastnik) + ' ' + str(h.ucastnik.id) # id, kvůli kolizi jmen @@ -174,8 +176,11 @@ def PrednaskyExportView(request: HttpRequest, seznam: int, **kwargs) -> HttpResp if h.znalost.id in znalosti_map: table[ucastnik][znalosti_map[h.znalost.id]] = h.odpoved else: - pass # TODO Padat hlasitě? + errors.append(f"Znalost {h.znalost.id} ({h.znalost}) dostala od Účastníka {h.ucastnik.id} následující odpověď: {h.odpoved}") + if len(errors) > 0: + logger.error("Při exportování hlasování o přednáškách a znalostech se neexportovali hodnocení z následujícího infa (pravděpodobně se od hlasování vyškrtla nějaká znalost/přednáška ze seznamu).") + logger.info("\n".join(errors)) response = HttpResponse(content_type="text/csv", charset="utf-8") response["Content-Disposition"] = 'attachment; filename="hlasovani.csv"' From b53da8c800d2c0f88611370970c11c0c174143a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Wed, 26 Feb 2025 13:36:50 +0100 Subject: [PATCH 12/30] =?UTF-8?q?Okomentov=C3=A1n=C3=AD=20hodnot=20enumu?= =?UTF-8?q?=20Stav?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prednasky/models.py b/prednasky/models.py index b49a3a69..39b012b7 100644 --- a/prednasky/models.py +++ b/prednasky/models.py @@ -19,8 +19,8 @@ class Seznam(models.Model): class Stav(models.IntegerChoices): """ Stav seznamu přednášek (NAVRH se používá k hlasování viz :py:func:`daný view <prednasky.views.newPrednaska>`). """ - NAVRH = 1, "Návrh" - BUDE = 2, "Bude" + NAVRH = 1, "Návrh" #: odpovídá před-soustřeďkové představě o tom, jaké přednášky dělat (dá se o nich třeba hlasovat ap.) + BUDE = 2, "Bude" #: odpovídá definitivní představě o tom, co bude/bylo a dá se porovnávat s novými návrhy id = models.AutoField(primary_key=True) soustredeni = models.ForeignKey(Soustredeni, null=True, default=None, on_delete=models.PROTECT) From ac71922472e7d90cf8499c6464c126f486979434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Wed, 26 Feb 2025 13:43:42 +0100 Subject: [PATCH 13/30] =?UTF-8?q?Dal=C5=A1=C3=AD=20dokumentace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/models.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/prednasky/models.py b/prednasky/models.py index 39b012b7..99c2e6eb 100644 --- a/prednasky/models.py +++ b/prednasky/models.py @@ -6,7 +6,7 @@ from personalni.models import Organizator, Osoba class Seznam(models.Model): """ - Spojuje :py:class:`Přednášky <prednasky.models.Prednaska>` + Spojuje :py:class:`Přednášky <prednasky.models.Prednaska>` a :py:class:`Znalosti <prednasky.models.Znalost> se :py:class:`Soustředěními <soustredeni.models.Soustredeni>`, kde by mohly zaznít, nebo zazní/zazněly. """ @@ -99,6 +99,9 @@ class Znalost(models.Model): """ Reprezentuje znalost, na kterou se můžeme účastníka ptát (nechat je hlasovat). (Viz :py:class:`HlasováníOZnalostech <prednasky.models.HlasovaniOZnalostech>`.) + + (V podstatě :py:class:`Přednáška <prednasky.models.Prednaska>, jen neobsahuje + tolik detailů a v hlasování má jiné odpovědi.) """ class Meta: db_table = "prednasky_znalost" @@ -118,6 +121,9 @@ class HlasovaniOZnalostech(models.Model): Reprezentuje hlasování jednoho účastníka o jedné :py:class:`Znalosti <prednasky.models.Znalost>` v jednom :py:class:`Seznamu <prednasky.models.Seznam>` (účastníkův pohled se totiž mezi sousy změnit) + + (V podstatě totéž, co :py:class:`Hlasování <prednasky.models.Hlasovani>`, jen má jiné komentáře + u odpovědí a místo přednášky odkazuje na znalost.) """ class Odpoved(models.IntegerChoices): """ Na kolik danou znalost účastník ovládá v daném Hlasování (větší číslo = víc zná) """ From 283bb4247e61afe242ed94628348cad41cb00660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Wed, 26 Feb 2025 14:06:14 +0100 Subject: [PATCH 14/30] =?UTF-8?q?Lep=C5=A1=C3=AD=3F=20popis=20inline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/admin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prednasky/admin.py b/prednasky/admin.py index ff8e9464..d0fe603a 100644 --- a/prednasky/admin.py +++ b/prednasky/admin.py @@ -10,7 +10,7 @@ from soustredeni.models import Soustredeni class Seznam_PrednaskaInline(admin.TabularInline): """ - Pomůcka pro :py:class:`prednasky.admin.SeznamAdmin` zobrazující hezky :py:class:`Přednášky <prednasky.models.Prednaska>` + :py:class:`Inline <django.contrib.admin.TabularInline>` pro :py:class:`prednasky.admin.SeznamAdmin` zobrazující :py:class:`Přednášky <prednasky.models.Prednaska>` v adminu :py:class:`Seznamu <prednasky.models.Seznam>`. """ model = Prednaska.seznamy.through @@ -60,7 +60,7 @@ class Seznam_PrednaskaInline(admin.TabularInline): class Seznam_ZnalostInline(admin.TabularInline): """ - Pomůcka pro :py:class:`prednasky.admin.SeznamAdmin` zobrazující hezky :py:class:`Znalosti <prednasky.models.Znalost>` + :py:class:`Inline <django.contrib.admin.TabularInline>` pro :py:class:`prednasky.admin.SeznamAdmin` zobrazující :py:class:`Znalosti <prednasky.models.Znalost>` v adminu :py:class:`Seznamu <prednasky.models.Seznam>`. """ model = Znalost.seznamy.through From 6e6b2deedb8039a9990df95ffb7c45186594dacc Mon Sep 17 00:00:00 2001 From: MaM Web user <mam-web@gimli.ms.mff.cuni.cz> Date: Wed, 26 Feb 2025 14:25:32 +0100 Subject: [PATCH 15/30] =?UTF-8?q?Kdy=C5=BE=20nen=C3=AD=20jin=C3=A9ho=20zby?= =?UTF-8?q?t=C3=AD,=20tak=20budou=20p=C5=99edm=C4=9Bty=20e-mail=C5=AF=20?= =?UTF-8?q?=C5=A1=C3=ADlen=C3=A9=20(by=20Jid=C3=A1=C5=A1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prednasky/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/prednasky/views.py b/prednasky/views.py index e5adeec1..7a01839a 100644 --- a/prednasky/views.py +++ b/prednasky/views.py @@ -179,8 +179,7 @@ def PrednaskyExportView(request: HttpRequest, seznam: int, **kwargs) -> HttpResp errors.append(f"Znalost {h.znalost.id} ({h.znalost}) dostala od Účastníka {h.ucastnik.id} následující odpověď: {h.odpoved}") if len(errors) > 0: - logger.error("Při exportování hlasování o přednáškách a znalostech se neexportovali hodnocení z následujícího infa (pravděpodobně se od hlasování vyškrtla nějaká znalost/přednáška ze seznamu).") - logger.info("\n".join(errors)) + logger.error("Při exportování hlasování o přednáškách a znalostech se neexportovali hodnocení a přednášky (pravděpodobně se od hlasování vyškrtla nějaká znalost/přednáška ze seznamu):\n" + "\n".join(errors)) response = HttpResponse(content_type="text/csv", charset="utf-8") response["Content-Disposition"] = 'attachment; filename="hlasovani.csv"' From 3814d292adc1c4fbdc1be2a1e0eab61ce0d8aa24 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 19:11:50 +0100 Subject: [PATCH 16/30] oprava na query set osob --- personalni/views.py | 60 ++++++++++++++------------------------------- tvorba/utils.py | 2 ++ 2 files changed, 21 insertions(+), 41 deletions(-) diff --git a/personalni/views.py b/personalni/views.py index 5ae97e24..49938f29 100644 --- a/personalni/views.py +++ b/personalni/views.py @@ -187,7 +187,8 @@ def download_export_csv(request, type, id): if type == PrvniTypExportu.SOUSTREDENI.value: soustredeni = Soustredeni.objects.get(id=id) organizatori = soustredeni.organizatori.all() - response = dataOsobCsvResponse(organizatori) + organizatoriOsoby = Osoba.objects.filter(org__in=organizatori) + response = dataOsobCsvResponse(organizatoriOsoby, columns=("jmeno", "prijmeni", "email", "telefon",)) name = str(soustredeni).replace(" ", "_") + "_organizatori_soustredeni.csv" response['Content-Disposition'] = 'attachment; filename="' + name + '"' return response @@ -526,50 +527,27 @@ def dataOsobCsvResponse(queryset, columns=None, with_header=True): default_columns = ( 'id', - 'osoba__jmeno', - 'osoba__prijmeni', - 'osoba__prezdivka', - 'osoba__email', - 'osoba__telefon', - 'osoba__user__username', - 'osoba__datum_narozeni', - 'osoba__osloveni', - 'osoba__ulice', - 'osoba__mesto', - 'osoba__psc', - 'osoba__stat', - 'osoba__jak_se_dozvedeli', - 'osoba__poznamka', - 'osoba__datum_registrace', - 'osoba__datum_souhlasu_udaje', - 'osoba__datum_souhlasu_zasilani', + 'jmeno', + 'prijmeni', + 'prezdivka', + 'email', + 'telefon', + 'datum_narozeni', + 'osloveni', + 'ulice', + 'mesto', + 'psc', + 'stat', + 'jak_se_dozvedeli', + 'poznamka', + 'datum_registrace', + 'datum_souhlasu_udaje', + 'datum_souhlasu_zasilani', ) + if columns is None: columns = default_columns - field_name_overrides = { - # Zrušení prefixu "osoba__" - 'osoba__jmeno': 'jmeno', - 'osoba__prijmeni': 'prijmeni', - 'osoba__prezdivka': 'prezdivka', - 'osoba__email': 'email', - 'osoba__telefon': 'telefon', - 'osoba__user__username': 'user', - 'osoba__datum_narozeni': 'datum_narozeni', - 'osoba__osloveni': 'osloveni', - 'osoba__ulice': 'ulice', - 'osoba__mesto': 'mesto', - 'osoba__psc': 'psc', - 'osoba__stat': 'stat', - 'osoba__jak_se_dozvedeli': 'jak_se_dozvedeli', - 'osoba__poznamka': 'poznamka', - 'osoba__datum_registrace': 'datum_registrace', - 'osoba__datum_souhlasu_udaje': 'datum_souhlasu_udaje', - 'osoba__datum_souhlasu_zasilani':'datum_souhlasu_zasilani', - } - def get_field_name(column_name): - if column_name in field_name_overrides: - return field_name_overrides[column_name] return column_name response = HttpResponse(content_type='text/csv') diff --git a/tvorba/utils.py b/tvorba/utils.py index 1c8076c8..a7b016a9 100644 --- a/tvorba/utils.py +++ b/tvorba/utils.py @@ -48,6 +48,8 @@ def resitele_co_neodmaturovali(): from datetime import datetime current_year = datetime.now().year '''Člověk odmaturuje když je jeho rok maturity menší nebo stejný jako aktuální rok? ''' + if datetime.now().month < 8: + current_year -= 1 return personalni.models.Resitel.objects.filter(rok_maturity__gte=current_year) From be4fda5e7fde77cde2a489a1e7d8a424d2125532 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 19:17:06 +0100 Subject: [PATCH 17/30] oprava url na spravny tvar --- personalni/templates/personalni/profil/orgorozcestnik.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/personalni/templates/personalni/profil/orgorozcestnik.html b/personalni/templates/personalni/profil/orgorozcestnik.html index bd73fa6e..338857ba 100644 --- a/personalni/templates/personalni/profil/orgorozcestnik.html +++ b/personalni/templates/personalni/profil/orgorozcestnik.html @@ -111,7 +111,7 @@ <h2><strong>Exporty dat lidí v semináří</strong></h2> <ul> - <li><a href="exporty_lidi">dostupné exporty</a></li> + <li><a href="{% url 'exporty_lidi' %}">dostupné exporty</a></li> </ul> <hr /> From b7ac8417603f924f1f6968a99024edae16e90ba3 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 19:21:01 +0100 Subject: [PATCH 18/30] komentar maturity --- tvorba/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tvorba/utils.py b/tvorba/utils.py index a7b016a9..41ac578a 100644 --- a/tvorba/utils.py +++ b/tvorba/utils.py @@ -34,8 +34,7 @@ def resi_cislo(cislo): cislo (typu Cislo) číslo, ve kterém chci řešitele, co něco odevzdali Výstup: QuerySet objektů typu Resitel - - Nejsem si moc jistý, jestli to tak funguje... Vašek """ + """ return personalni.models.Resitel.objects.filter( reseni__hodnoceni__deadline_body__cislo=cislo @@ -43,11 +42,12 @@ def resi_cislo(cislo): def resitele_co_neodmaturovali(): """ Vrátí seznam řešitelů, co ještě neodmaturovali. + Pokud ještě není srpen, tak tak zahrnuje i ty, kteří odmaturovali letos. + Výstup: QuerySet objektů typu Resitel """ from datetime import datetime current_year = datetime.now().year - '''Člověk odmaturuje když je jeho rok maturity menší nebo stejný jako aktuální rok? ''' if datetime.now().month < 8: current_year -= 1 return personalni.models.Resitel.objects.filter(rok_maturity__gte=current_year) From d86bdf9218166101ba96352c4f55889ab9e779f1 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 19:35:00 +0100 Subject: [PATCH 19/30] tak odebrano --- tvorba/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tvorba/utils.py b/tvorba/utils.py index 41ac578a..312e83e6 100644 --- a/tvorba/utils.py +++ b/tvorba/utils.py @@ -42,7 +42,7 @@ def resi_cislo(cislo): def resitele_co_neodmaturovali(): """ Vrátí seznam řešitelů, co ještě neodmaturovali. - Pokud ještě není srpen, tak tak zahrnuje i ty, kteří odmaturovali letos. + Pokud ještě není srpen, tak zahrnuje i ty, kteří odmaturovali letos. Výstup: QuerySet objektů typu Resitel """ From b25c04bf42f81c2acf7a2878890d485f2787bc75 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 20:13:25 +0100 Subject: [PATCH 20/30] odmena nastrel --- tvorba/templates/tvorba/archiv/odmeny.html | 6 ++++++ tvorba/views/__init__.py | 10 +++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tvorba/templates/tvorba/archiv/odmeny.html b/tvorba/templates/tvorba/archiv/odmeny.html index 6b2d1eb7..e41ee2b8 100644 --- a/tvorba/templates/tvorba/archiv/odmeny.html +++ b/tvorba/templates/tvorba/archiv/odmeny.html @@ -16,4 +16,10 @@ {% endfor %} </ul> + <ul> + {% for resitel in resitele %} + <li>{{ resitel.jmeno }} {{ resitel.tbody - resitel.fbody }}</li> + {% endfor %} + </ul> + {% endblock content %} diff --git a/tvorba/views/__init__.py b/tvorba/views/__init__.py index 006a4e50..b9c4663e 100644 --- a/tvorba/views/__init__.py +++ b/tvorba/views/__init__.py @@ -375,7 +375,7 @@ class OdmenyView(generic.TemplateView): tocislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('trocnik'), poradi=self.kwargs.get('tcislo')) resitele = utils.aktivniResitele(tocislo) - def get_diff(from_deadline: Deadline, to_deadline: Deadline): + def get_diff(from_deadline: Deadline, to_deadline: Deadline, probody=False): frombody = body_resitelu(resitele=resitele, jen_verejne=False, do=from_deadline) tobody = body_resitelu(resitele=resitele, jen_verejne=False, do=to_deadline) outlist = [] @@ -384,8 +384,11 @@ class OdmenyView(generic.TemplateView): tbody = tobody.get(resitel.id, 0) ftitul = resitel.get_titul(fbody) ttitul = resitel.get_titul(tbody) - if ftitul != ttitul: - outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'ftitul': ftitul, 'ttitul': ttitul}) + if probody: + outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'fbody': fbody, 'tbody': tbody, 'ftitul': ftitul, 'ttitul': ttitul}) + else: + if ftitul != ttitul: + outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'ftitul': ftitul, 'ttitul': ttitul}) return outlist def posledni_deadline_oprava(cislo: Cislo) -> Deadline: @@ -401,6 +404,7 @@ class OdmenyView(generic.TemplateView): context["from_deadline"] = from_deadline context["to_deadline"] = to_deadline context["zmeny"] = get_diff(from_deadline, to_deadline) + context["resitele"] = get_diff(from_deadline, to_deadline, probody=resitele.order_by("osoba__prijmeni")) return context From 8e25a2eb4f0765a91c380b1438142d07c05e962c Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 20:34:59 +0100 Subject: [PATCH 21/30] bodydiff --- tvorba/templates/tvorba/archiv/odmeny.html | 2 +- tvorba/views/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tvorba/templates/tvorba/archiv/odmeny.html b/tvorba/templates/tvorba/archiv/odmeny.html index e41ee2b8..1f0b4a2b 100644 --- a/tvorba/templates/tvorba/archiv/odmeny.html +++ b/tvorba/templates/tvorba/archiv/odmeny.html @@ -18,7 +18,7 @@ <ul> {% for resitel in resitele %} - <li>{{ resitel.jmeno }} {{ resitel.tbody - resitel.fbody }}</li> + <li>{{ resitel.jmeno }}: {{ bodydiff }}</li> {% endfor %} </ul> diff --git a/tvorba/views/__init__.py b/tvorba/views/__init__.py index b9c4663e..0d33a557 100644 --- a/tvorba/views/__init__.py +++ b/tvorba/views/__init__.py @@ -385,7 +385,7 @@ class OdmenyView(generic.TemplateView): ftitul = resitel.get_titul(fbody) ttitul = resitel.get_titul(tbody) if probody: - outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'fbody': fbody, 'tbody': tbody, 'ftitul': ftitul, 'ttitul': ttitul}) + outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'fbody': fbody, 'tbody': tbody, 'ftitul': ftitul, 'ttitul': ttitul, 'bodydiff': tbody - fbody}) else: if ftitul != ttitul: outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'ftitul': ftitul, 'ttitul': ttitul}) From 380a14299d3492da6af47b676a46474553008e94 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 20:38:14 +0100 Subject: [PATCH 22/30] dalsi random test --- tvorba/templates/tvorba/archiv/odmeny.html | 4 ++-- tvorba/views/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tvorba/templates/tvorba/archiv/odmeny.html b/tvorba/templates/tvorba/archiv/odmeny.html index 1f0b4a2b..f7369947 100644 --- a/tvorba/templates/tvorba/archiv/odmeny.html +++ b/tvorba/templates/tvorba/archiv/odmeny.html @@ -17,8 +17,8 @@ </ul> <ul> - {% for resitel in resitele %} - <li>{{ resitel.jmeno }}: {{ bodydiff }}</li> + {% for resitel in resitele %} + <li>{{ resitel.jmeno }}: {{ resitel.bodydiff }} {{resitel.posilat}}</li> {% endfor %} </ul> diff --git a/tvorba/views/__init__.py b/tvorba/views/__init__.py index 0d33a557..3c9979bd 100644 --- a/tvorba/views/__init__.py +++ b/tvorba/views/__init__.py @@ -385,7 +385,7 @@ class OdmenyView(generic.TemplateView): ftitul = resitel.get_titul(fbody) ttitul = resitel.get_titul(tbody) if probody: - outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'fbody': fbody, 'tbody': tbody, 'ftitul': ftitul, 'ttitul': ttitul, 'bodydiff': tbody - fbody}) + outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'fbody': fbody, 'tbody': tbody, 'ftitul': ftitul, 'ttitul': ttitul, 'bodydiff': tbody - fbody, "posilat": resitel.zasilat_cislo_papirove}) else: if ftitul != ttitul: outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'ftitul': ftitul, 'ttitul': ttitul}) From c853e06d7104985e3204e155b1bdfdfded7bd147 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 20:43:47 +0100 Subject: [PATCH 23/30] random bulshit goes... --- tvorba/templates/tvorba/archiv/odmeny.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tvorba/templates/tvorba/archiv/odmeny.html b/tvorba/templates/tvorba/archiv/odmeny.html index f7369947..79229d15 100644 --- a/tvorba/templates/tvorba/archiv/odmeny.html +++ b/tvorba/templates/tvorba/archiv/odmeny.html @@ -18,7 +18,7 @@ <ul> {% for resitel in resitele %} - <li>{{ resitel.jmeno }}: {{ resitel.bodydiff }} {{resitel.posilat}}</li> + <li>{{ resitel.jmeno }}: {% if resitel.bodydiff > 3 %}🧦{% endif %} {% if resitel.posilat %}POSÍLAT DOMŮ{% endif %} {% if resitel.ttitul != resitel.ftitul %} {{z.ftitul}} → {{z.ttitul}} {% endif %}</li> {% endfor %} </ul> From 8e8b446e09de72c93a2c322ff87be1b4c0803b77 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 20:45:57 +0100 Subject: [PATCH 24/30] fixint tyyyypos --- tvorba/templates/tvorba/archiv/odmeny.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tvorba/templates/tvorba/archiv/odmeny.html b/tvorba/templates/tvorba/archiv/odmeny.html index 79229d15..ec79937a 100644 --- a/tvorba/templates/tvorba/archiv/odmeny.html +++ b/tvorba/templates/tvorba/archiv/odmeny.html @@ -18,7 +18,7 @@ <ul> {% for resitel in resitele %} - <li>{{ resitel.jmeno }}: {% if resitel.bodydiff > 3 %}🧦{% endif %} {% if resitel.posilat %}POSÍLAT DOMŮ{% endif %} {% if resitel.ttitul != resitel.ftitul %} {{z.ftitul}} → {{z.ttitul}} {% endif %}</li> + <li>{{ resitel.jmeno }}: {% if resitel.bodydiff > 3 %}🧦{% endif %} {% if resitel.posilat %}POSÍLAT DOMŮ{% endif %} {% if resitel.ttitul != resitel.ftitul %} {{resitel.ftitul}} → {{resitel.ttitul}} {% endif %}</li> {% endfor %} </ul> From 80aa01d76b49eaf13ca4ab895debeedc030d904a Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 20:51:52 +0100 Subject: [PATCH 25/30] random inline css --- tvorba/templates/tvorba/archiv/odmeny.html | 2 +- tvorba/views/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tvorba/templates/tvorba/archiv/odmeny.html b/tvorba/templates/tvorba/archiv/odmeny.html index ec79937a..4dcd4806 100644 --- a/tvorba/templates/tvorba/archiv/odmeny.html +++ b/tvorba/templates/tvorba/archiv/odmeny.html @@ -18,7 +18,7 @@ <ul> {% for resitel in resitele %} - <li>{{ resitel.jmeno }}: {% if resitel.bodydiff > 3 %}🧦{% endif %} {% if resitel.posilat %}POSÍLAT DOMŮ{% endif %} {% if resitel.ttitul != resitel.ftitul %} {{resitel.ftitul}} → {{resitel.ttitul}} {% endif %}</li> + <li {% if resitel.neposilame %}style="color: white; background-color: red;"{% endif %}>{{ resitel.jmeno }}: {% if resitel.bodydiff > 3 %}🧦{% endif %} {% if resitel.ttitul != resitel.ftitul %} {{resitel.ftitul}} → {{resitel.ttitul}} {% endif %}</li> {% endfor %} </ul> diff --git a/tvorba/views/__init__.py b/tvorba/views/__init__.py index 3c9979bd..68f8772d 100644 --- a/tvorba/views/__init__.py +++ b/tvorba/views/__init__.py @@ -385,7 +385,7 @@ class OdmenyView(generic.TemplateView): ftitul = resitel.get_titul(fbody) ttitul = resitel.get_titul(tbody) if probody: - outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'fbody': fbody, 'tbody': tbody, 'ftitul': ftitul, 'ttitul': ttitul, 'bodydiff': tbody - fbody, "posilat": resitel.zasilat_cislo_papirove}) + outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'fbody': fbody, 'tbody': tbody, 'ftitul': ftitul, 'ttitul': ttitul, 'bodydiff': tbody - fbody, "neposilame": not(resitel.zasilat_cislo_papirove)}) else: if ftitul != ttitul: outlist.append({'jmeno': resitel.osoba.plne_jmeno(), 'ftitul': ftitul, 'ttitul': ttitul}) From 95e164650efd1b7f4e05e2d0921215c192831cc1 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 20:58:06 +0100 Subject: [PATCH 26/30] cervena text --- tvorba/templates/tvorba/archiv/odmeny.html | 1 + 1 file changed, 1 insertion(+) diff --git a/tvorba/templates/tvorba/archiv/odmeny.html b/tvorba/templates/tvorba/archiv/odmeny.html index 4dcd4806..a2b35c8c 100644 --- a/tvorba/templates/tvorba/archiv/odmeny.html +++ b/tvorba/templates/tvorba/archiv/odmeny.html @@ -16,6 +16,7 @@ {% endfor %} </ul> + <h2>Seznam účastníků - červená znamená že jim nechodí fyzické číslo</h2> <ul> {% for resitel in resitele %} <li {% if resitel.neposilame %}style="color: white; background-color: red;"{% endif %}>{{ resitel.jmeno }}: {% if resitel.bodydiff > 3 %}🧦{% endif %} {% if resitel.ttitul != resitel.ftitul %} {{resitel.ftitul}} → {{resitel.ttitul}} {% endif %}</li> From c1ae550a781d36233da76a97f948d50d807c9486 Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 21:13:48 +0100 Subject: [PATCH 27/30] dokumentace probody --- tvorba/views/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tvorba/views/__init__.py b/tvorba/views/__init__.py index 68f8772d..2240abf3 100644 --- a/tvorba/views/__init__.py +++ b/tvorba/views/__init__.py @@ -375,6 +375,7 @@ class OdmenyView(generic.TemplateView): tocislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('trocnik'), poradi=self.kwargs.get('tcislo')) resitele = utils.aktivniResitele(tocislo) + """Co je probody? pokud True, funkce vrací všechny rešitele a k nim potřebné informace, pokud False, vrací jen ty, kteří mají změnu v titulu.""" def get_diff(from_deadline: Deadline, to_deadline: Deadline, probody=False): frombody = body_resitelu(resitele=resitele, jen_verejne=False, do=from_deadline) tobody = body_resitelu(resitele=resitele, jen_verejne=False, do=to_deadline) From d34e551b715600ebf7471fd498fcb7a9809775bd Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 21:18:19 +0100 Subject: [PATCH 28/30] – --- tvorba/templates/tvorba/archiv/odmeny.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tvorba/templates/tvorba/archiv/odmeny.html b/tvorba/templates/tvorba/archiv/odmeny.html index a2b35c8c..f91a631a 100644 --- a/tvorba/templates/tvorba/archiv/odmeny.html +++ b/tvorba/templates/tvorba/archiv/odmeny.html @@ -16,7 +16,7 @@ {% endfor %} </ul> - <h2>Seznam účastníků - červená znamená že jim nechodí fyzické číslo</h2> + <h2>Seznam účastníků – červená znamená že jim nechodí fyzické číslo</h2> <ul> {% for resitel in resitele %} <li {% if resitel.neposilame %}style="color: white; background-color: red;"{% endif %}>{{ resitel.jmeno }}: {% if resitel.bodydiff > 3 %}🧦{% endif %} {% if resitel.ttitul != resitel.ftitul %} {{resitel.ftitul}} → {{resitel.ttitul}} {% endif %}</li> From 777a36b1f7b5354d2488e2ed8bc9786c321d0fbf Mon Sep 17 00:00:00 2001 From: ticvac <vaclav.tichy180@gmail.com> Date: Wed, 26 Feb 2025 21:19:39 +0100 Subject: [PATCH 29/30] posunuti dokumneasasasa --- tvorba/views/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tvorba/views/__init__.py b/tvorba/views/__init__.py index 2240abf3..4cb769a6 100644 --- a/tvorba/views/__init__.py +++ b/tvorba/views/__init__.py @@ -375,8 +375,8 @@ class OdmenyView(generic.TemplateView): tocislo = get_object_or_404(Cislo, rocnik=self.kwargs.get('trocnik'), poradi=self.kwargs.get('tcislo')) resitele = utils.aktivniResitele(tocislo) - """Co je probody? pokud True, funkce vrací všechny rešitele a k nim potřebné informace, pokud False, vrací jen ty, kteří mají změnu v titulu.""" def get_diff(from_deadline: Deadline, to_deadline: Deadline, probody=False): + """Co je probody? pokud True, funkce vrací všechny rešitele a k nim potřebné informace, pokud False, vrací jen ty, kteří mají změnu v titulu.""" frombody = body_resitelu(resitele=resitele, jen_verejne=False, do=from_deadline) tobody = body_resitelu(resitele=resitele, jen_verejne=False, do=to_deadline) outlist = [] From 66ec9bb33faaa7cdf565f6107b0c1325a29fd0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Havelka?= <jonas.havelka@volny.cz> Date: Wed, 19 Mar 2025 18:50:39 +0100 Subject: [PATCH 30/30] Fix bugu s location.hash (v chromu) #1557 --- korektury/templates/korektury/korekturovatko/_main.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/korektury/templates/korektury/korekturovatko/_main.html b/korektury/templates/korektury/korekturovatko/_main.html index fe5c6cac..94539a23 100644 --- a/korektury/templates/korektury/korekturovatko/_main.html +++ b/korektury/templates/korektury/korekturovatko/_main.html @@ -38,7 +38,11 @@ window.addEventListener("load", _ => { update_all({}, true, _ => { - if (location.hash !== "") location.hash = location.hash; // Po rozházení korektur sescrollujeme na kotvu v URL + if (location.hash !== "") { // Po rozházení korektur sescrollujeme na kotvu v URL + const h = location.hash.substring(1); + location.hash = "HACK"; + location.hash = h; + } }); });