Compare commits

...

15 commits

Author SHA1 Message Date
c0fa59a504 Merge branch 'master' into vylepseni_odevzdavatka 2023-03-06 20:17:03 +01:00
6e1b1ef4e8 Komentář 4 změny = beze změny 2023-03-06 20:16:36 +01:00
9868bff329 fuj, print 2023-03-06 20:11:50 +01:00
bec500d61a Merge pull request 'Možnost stáhnout si řešení pojmenovaná podle řešitele' (!26) from jmena-do-priloh-reseni into master
Reviewed-on: #26
2023-02-27 20:48:26 +01:00
2913ea27ab add: lepší vzhled 2023-02-27 20:44:30 +01:00
Pavel "LEdoian" Turinsky
e42b6abec5 Zrušení console.log-ů 2023-02-27 20:25:45 +01:00
c6ff17050b Merge pull request 'Zklidnění testů' (!23) from clean_tests into master
Reviewed-on: #23
2023-02-27 20:12:44 +01:00
3dc6cdd7ed Merge pull request 'Html Deadline Hint' (!24) from html_deadline_hint into master
Reviewed-on: #24
2023-02-27 19:58:57 +01:00
8c9dbb5143 Merge pull request 'Ukaž řešení i orgovi' (!25) from ukaz-reseni-i-orgovi into master
Reviewed-on: #25
2023-02-22 10:07:16 +01:00
Pavel "LEdoian" Turinsky
32dc97e1c4 Možnost přidat si do názvů příloh řešení i jména řešitele
Budu zlobit a vysvětlení napíšu až do pull-requestu. Tady to IMHO čtu
jen já :-P

Pull-Request-URL: #26

(Adresa platí, pokud mě nikdo nepředběhne :-P)
2023-02-22 07:19:33 +01:00
Pavel "LEdoian" Turinsky
01f3537cef Dovolme orgovi kouknout se na řešitelský náhled řešení
Orgovi se může hodit vidět, jak zpětnou vazbu uvidí řešitel.

Možná by taky nebylo špatné odkázat na řešitelskou stránku z orgovské…
2023-02-22 07:15:18 +01:00
Pavel "LEdoian" Turinsky
d5cf81c32a Přidání titulku k výpisu deadlinu
Po najetí myší řekne, co znamenají symboly…
2023-02-21 17:08:10 +01:00
13c8c29bb0 fix: dvojnásobky v tabulce došlých řešení 2023-02-13 20:47:42 +01:00
Pavel "LEdoian" Turinsky
e0eb12cf9e Školy jen zakomentovat, nepsat expectedFailure test
Podle toho, jak dopadne PR se to buď aplikuje takto, nebo se tenhle
commit revertne.
2023-02-06 22:31:42 +01:00
Pavel "LEdoian" Turinsky
fdbbc9c242 Úprava testu na autocomplete, aby nefailoval
… moc nahlas.
2023-02-06 21:58:16 +01:00
8 changed files with 88 additions and 13 deletions

View file

@ -11,19 +11,20 @@ class OrgSkolyAutocompleteTestCase(TestCase):
sync_skoly('https://mam.mff.cuni.cz/') sync_skoly('https://mam.mff.cuni.cz/')
# Správné školy podle toho, co orgové poslali: (prefix, ID školy) # Správné školy podle toho, co orgové poslali: (prefix, ID školy)
# NOTE: Pozor, jedná se o databázové indexy. Pokud se to někdy rozbije, bude potřeba je přepsat nebo předělat na IZO # NOTE: Pozor, jedná se o databázové indexy. Pokud se to někdy rozbije, bude potřeba je přepsat nebo předělat na IZO
# TODO: Opravit zakomentované školy.
cls.spravna_data = [ cls.spravna_data = [
('gymnázium kolín', 53), ('gymnázium kolín', 53),
('kolín', 53), ('kolín', 53),
('gasoš', 96), #('gasoš', 96),
('Rokycany', 96), ('Rokycany', 96),
('gasoš Rokycany', 96), #('gasoš Rokycany', 96),
('SPŠE Pardubice', 815), #('SPŠE Pardubice', 815),
('Jaroše', 164), ('Jaroše', 164),
("Gymnázium, Brno, tř. Kpt. Jaroše", 164), #("Gymnázium, Brno, tř. Kpt. Jaroše", 164),
("Jírovcova", 157), ("Jírovcova", 157),
('České Budějovice', 157), ('České Budějovice', 157),
("Gymnázium, České Budějovice, Jírovcova 8", 157), ("Gymnázium, České Budějovice, Jírovcova 8", 157),
("první soukromé", 2), #("první soukromé", 2),
("Gymnázium Elgartova", 147), ("Gymnázium Elgartova", 147),
("Jihlava", 45), ("Jihlava", 45),
('Milevsko', 223), ('Milevsko', 223),

View file

@ -2,6 +2,7 @@
{% load static %} {% load static %}
{% load deadliny %} {% load deadliny %}
{% load mail %} {% load mail %}
{% load jmena %}
{# Přišlo mi to hezčí, než psát všude if. #} {# Přišlo mi to hezčí, než psát všude if. #}
{% block custom_css %} {% block custom_css %}
@ -15,6 +16,17 @@
{% if edit %} {% if edit %}
<script src="{% static 'odevzdavatko/dynamic_formsets_for_detail.js' %}"></script> <script src="{% static 'odevzdavatko/dynamic_formsets_for_detail.js' %}"></script>
<script src="{% static 'odevzdavatko/check_for_detail.js' %}"></script> <script src="{% static 'odevzdavatko/check_for_detail.js' %}"></script>
<script type="text/javascript">
$(document).ready(function () {
const zaskrtavatko = document.getElementById('pridat-jmena-resitelu');
zaskrtavatko.addEventListener('change', () => {
for (var priloha of document.getElementsByClassName("reseni-ke-stazeni")) {
let new_download = zaskrtavatko.checked ? priloha.dataset.altFilename : '';
priloha.setAttribute('download', new_download);
}
});
});
</script>
{% endif %} {% endif %}
@ -47,11 +59,20 @@
<tr><th>Soubor</th><th>Řešitelova poznámka</th><th>Datum</th></tr> <tr><th>Soubor</th><th>Řešitelova poznámka</th><th>Datum</th></tr>
{% for priloha in object.prilohy.all %} {% for priloha in object.prilohy.all %}
<tr> <tr>
<td><a href="{{ priloha.soubor.url }}" download>{{ priloha.split | last }}</a></td> <td><a class='reseni-ke-stazeni'
href="{{ priloha.soubor.url }}"
download
data-alt-filename="{{object.resitele.first.osoba | jmeno_jako_prefix }}_{{ object.id }}_{{ priloha.split | last}}"
>{{ priloha.split | last }}</a></td>
<td>{{ priloha.res_poznamka }}</td> <td>{{ priloha.res_poznamka }}</td>
<td>{{ priloha.vytvoreno }}</td></tr> <td>{{ priloha.vytvoreno }}</td></tr>
{% endfor %} {% endfor %}
</table> </table>
{% if edit %} {# FIXME: tohle nesouvisí s editací, ale s tím, jestli je člověk org… #}
<br>
<input type=checkbox id="pridat-jmena-resitelu">
<label class="field-label" for="pridat-jmena-resitelu">Uvést jméno řešitele v názvu souboru při stažení.</label>
{% endif %}
{% else %} {% else %}
<p>Žádné přílohy</p> <p>Žádné přílohy</p>
{% endif %} {% endif %}

View file

View file

@ -0,0 +1,9 @@
from django import template
register = template.Library()
from personalni.utils import normalizuj_jmeno
import seminar.models as m # jen kvůli typové anotaci…
@register.filter
def jmeno_jako_prefix(o: m.Osoba):
return normalizuj_jmeno(o).replace(' ', '_')

View file

@ -114,7 +114,7 @@ class TabulkaOdevzdanychReseniView(ListView):
qs = super().get_queryset() qs = super().get_queryset()
if self.jen_neobodovane: if self.jen_neobodovane:
qs = qs.filter(body__isnull=True) qs = qs.filter(body__isnull=True)
qs = qs.filter(problem__in=self.problemy, reseni__in=self.reseni, reseni__resitele__in=self.resitele).select_related('reseni', 'problem').prefetch_related('reseni__resitele__osoba') qs = qs.filter(problem__in=self.problemy, reseni__in=self.reseni, reseni__resitele__in=self.resitele).select_related('reseni', 'problem').prefetch_related('reseni__resitele__osoba').distinct()
# FIXME tohle je ošklivé, na špatném místě a pomalé. Ale moc mě štvalo, že musím hledat správná místa v tabulce. # FIXME tohle je ošklivé, na špatném místě a pomalé. Ale moc mě štvalo, že musím hledat správná místa v tabulce.
self.problemy = self.problemy.filter(id__in=qs.values("problem__id")) self.problemy = self.problemy.filter(id__in=qs.values("problem__id"))
return qs return qs
@ -259,8 +259,8 @@ class DetailReseniView(DetailView):
return response return response
def check_access(self): def check_access(self):
""" Řešitel musí být součástí řešení, jinak se na něj nemá co dívat. """ """ Řešitel musí být součástí řešení, jinak se na něj nemá co dívat. Případně to může být org."""
if not self.object.resitele.filter(osoba__user=self.request.user).exists(): if not self.object.resitele.filter(osoba__user=self.request.user).exists() and not self.request.user.je_org:
raise PermissionDenied() raise PermissionDenied()
@ -315,8 +315,8 @@ def hodnoceniReseniView(request, pk, *args, **kwargs):
zmeny_bodu = [it for it in form.changed_data if it.startswith("body")] zmeny_bodu = [it for it in form.changed_data if it.startswith("body")]
if len(zmeny_bodu) == 1: if len(zmeny_bodu) == 1:
hodnoceni.__setattr__(zmeny_bodu[0], data_for_body[zmeny_bodu[0]]) hodnoceni.__setattr__(zmeny_bodu[0], data_for_body[zmeny_bodu[0]])
if len(zmeny_bodu) != 1 and len(zmeny_bodu) != 4: # > jedna změna je špatně, ale 4 "změny" znamenají že nebylo nic zadáno
print(f"Hodnocení {hodnoceni} mělo mít nastavené víc různých bodů: {zmeny_bodu}. Nastavuji -0.1.") if len(zmeny_bodu) > 1 and len(zmeny_bodu) != 4:
logger.warning(f"Hodnocení {hodnoceni} mělo mít nastavené víc různých bodů: {zmeny_bodu}. Nastavuji -0.1.") logger.warning(f"Hodnocení {hodnoceni} mělo mít nastavené víc různých bodů: {zmeny_bodu}. Nastavuji -0.1.")
hodnoceni.body = -0.1 hodnoceni.body = -0.1
hodnoceni.save() hodnoceni.save()

11
personalni/utils.py Normal file
View file

@ -0,0 +1,11 @@
import seminar.models as m
from various.utils import bez_diakritiky_translate
import re
def normalizuj_jmeno(o: m.Osoba) -> str:
# FIXME: Možná není potřeba vázat na model?
cele_jmeno = f'{o.jmeno} {o.prijmeni}'
cele_jmeno = cele_jmeno.translate(bez_diakritiky_translate)
cele_jmeno = re.sub(r'[^a-zA-Z- ]', '', cele_jmeno)
return cele_jmeno

View file

@ -26,7 +26,7 @@ def deadline_html(deadline: m.Deadline):
m.Deadline.TYP_PRVNI_A_SOUS: 'sous_deadline', m.Deadline.TYP_PRVNI_A_SOUS: 'sous_deadline',
m.Deadline.TYP_CISLA: 'final_deadline', m.Deadline.TYP_CISLA: 'final_deadline',
} }
return mark_safe(f'<span class="{classes[deadline.typ]}">{text}</span>') return mark_safe(f'<span class="{classes[deadline.typ]}" title="{deadline}">{text}</span>')
@register.filter(name='zkrat_nazev_problemu') @register.filter(name='zkrat_nazev_problemu')
def zkrat_nazev_problemu(nazev,width): def zkrat_nazev_problemu(nazev,width):
@ -35,4 +35,4 @@ def zkrat_nazev_problemu(nazev,width):
nazev = nazev[:width-1] + "..." nazev = nazev[:width-1] + "..."
else: else:
nazev = nazev[:width] + "..." nazev = nazev[:width] + "..."
return nazev return nazev

33
various/utils.py Normal file
View file

@ -0,0 +1,33 @@
bez_diakritiky = ({}
# FIXME: funguje jen pro český a slovenský text, jinak jsou špatně
# transliterace. Potenciální řešení:
# https://stackoverflow.com/questions/517923/what-is-the-best-way-to-remove-accents-normalize-in-a-python-unicode-string
# (ale přidává to další závislosti…)
# Tisknutelné ASCII
| {chr(a): chr(a) for a in range(32, 126+1)}
# České, slovenské a blízké diakritiky a divnoznaky
| { x: 'a' for x in 'áÁäÄ'}
| { x: 'c' for x in 'čČ'}
| { x: 'd' for x in 'ďĎ'}
| { x: 'e' for x in 'éÉěĚëË'}
| { x: 'i' for x in 'íÍ'}
| { x: 'l' for x in 'ľĽĺĹ'}
| { x: 'n' for x in 'ňŇ'}
| { x: 'o' for x in 'óÓöÖôÔ'}
| { x: 'r' for x in 'řŘŕŔ'}
| { x: 's' for x in 'šŠßẞ'}
| { x: 't' for x in 'ťŤ'}
| { x: 'u' for x in 'úÚůŮ'}
| { x: 'y' for x in 'ýÝ'}
| { x: 'z' for x in 'žŽ'}
)
# Tabulka pro str.translate
class _bez_diakritiky_translate:
def __getitem__(self, it):
return ord(bez_diakritiky.get(chr(it), None))
bez_diakritiky_translate = _bez_diakritiky_translate()
# TODO: testy?