Merge pull request 'Upgrade odevzdavatka' (!30) from upgrade_odevzdavatka into master
Reviewed-on: #30
This commit is contained in:
commit
0528dbbb9c
15 changed files with 205 additions and 49 deletions
|
@ -70,23 +70,17 @@ class PublicResitelAutocomplete(LoginRequiredAjaxMixin, autocomplete.Select2Quer
|
||||||
class OdevzdatelnyProblemAutocomplete(autocomplete.Select2QuerySetView):
|
class OdevzdatelnyProblemAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
""" View k :mod:`dal.autocomplete` pro vyhledávání problémů především v odevzdávátku. """
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
nastaveni = get_object_or_404(m.Nastaveni)
|
qs = m.Problem.objects.filter(stav=m.Problem.STAV_ZADANY)
|
||||||
rocnik = nastaveni.aktualni_rocnik
|
|
||||||
# Od tohoto místa dál jsem zkoušel spoustu variací podle https://django-polymorphic.readthedocs.io/en/stable/advanced.html
|
|
||||||
temaQ = Q(Tema___rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
|
||||||
ulohaQ = Q(Uloha___cislo_zadani__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
|
||||||
clanekQ = Q(Clanek___cislo__rocnik = rocnik, stav=m.Problem.STAV_ZADANY)
|
|
||||||
qs = m.Problem.objects.filter(temaQ | ulohaQ | clanekQ)
|
|
||||||
#print(temata, ulohy, clanky)
|
|
||||||
#ulohy.union(temata, all=True)
|
|
||||||
#print(ulohy)
|
|
||||||
#ulohy.union(clanky, all=True)
|
|
||||||
#print(ulohy)
|
|
||||||
#qs = ulohy
|
|
||||||
print(qs)
|
|
||||||
if self.q:
|
if self.q:
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
Q(nazev__icontains=self.q))
|
Q(nazev__icontains=self.q))
|
||||||
|
|
||||||
|
nadproblem_id = int(self.forwarded.get("nadproblem_id", -1))
|
||||||
|
if nadproblem_id != -1:
|
||||||
|
# Seřadíme tak, aby ty s nadproblem==None byly dole (větší motivace tam naklikat konkrétní úlohy) a pak nějak rozumně.
|
||||||
|
# Tohle je řazení pro odevzdávátko, kde je definován nadproblém, proto je to v tomto ifu. (Jinde si to netroufám řadit)
|
||||||
|
qs = qs.order_by("nadproblem", "kod", "nazev")
|
||||||
|
qs = list(filter(lambda problem: problem.hlavni_problem.id == nadproblem_id, qs))
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
class ProblemAutocomplete(autocomplete.Select2QuerySetView):
|
class ProblemAutocomplete(autocomplete.Select2QuerySetView):
|
||||||
|
|
|
@ -437,7 +437,7 @@
|
||||||
"insitetree": true,
|
"insitetree": true,
|
||||||
"parent": 21,
|
"parent": 21,
|
||||||
"sort_order": 36,
|
"sort_order": 36,
|
||||||
"title": "Poslat řešení",
|
"title": "Nahrát řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_nahraj_reseni",
|
"url": "seminar_nahraj_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
|
@ -719,7 +719,7 @@
|
||||||
"insitetree": true,
|
"insitetree": true,
|
||||||
"parent": 21,
|
"parent": 21,
|
||||||
"sort_order": 36,
|
"sort_order": 36,
|
||||||
"title": "Nahrát řešení",
|
"title": "Vložit řešení",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "seminar_vloz_reseni",
|
"url": "seminar_vloz_reseni",
|
||||||
"urlaspattern": true
|
"urlaspattern": true
|
||||||
|
@ -1026,6 +1026,36 @@
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
"pk": 51
|
"pk": 51
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"access_guest": false,
|
||||||
|
"access_loggedin": false,
|
||||||
|
"access_perm_type": 1,
|
||||||
|
"access_permissions": [
|
||||||
|
[
|
||||||
|
"resitel",
|
||||||
|
"auth",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"access_restricted": true,
|
||||||
|
"alias": null,
|
||||||
|
"description": "",
|
||||||
|
"hidden": false,
|
||||||
|
"hint": "",
|
||||||
|
"inbreadcrumbs": true,
|
||||||
|
"inmenu": true,
|
||||||
|
"insitetree": true,
|
||||||
|
"parent": 23,
|
||||||
|
"sort_order": 52,
|
||||||
|
"title": "Nahrát řešení k nadproblému {{nadproblem_id}}",
|
||||||
|
"tree": 1,
|
||||||
|
"url": "seminar_nahraj_reseni nadproblem_id",
|
||||||
|
"urlaspattern": true
|
||||||
|
},
|
||||||
|
"model": "sitetree.treeitem",
|
||||||
|
"pk": 52
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fields": {
|
"fields": {
|
||||||
"access_guest": false,
|
"access_guest": false,
|
||||||
|
@ -1041,13 +1071,13 @@
|
||||||
"inmenu": true,
|
"inmenu": true,
|
||||||
"insitetree": true,
|
"insitetree": true,
|
||||||
"parent": 28,
|
"parent": 28,
|
||||||
"sort_order": 52,
|
"sort_order": 53,
|
||||||
"title": "Přidat PDF",
|
"title": "Přidat PDF",
|
||||||
"tree": 1,
|
"tree": 1,
|
||||||
"url": "/admin/korektury/korekturovanepdf/add/",
|
"url": "/admin/korektury/korekturovanepdf/add/",
|
||||||
"urlaspattern": false
|
"urlaspattern": false
|
||||||
},
|
},
|
||||||
"model": "sitetree.treeitem",
|
"model": "sitetree.treeitem",
|
||||||
"pk": 52
|
"pk": 53
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -28,7 +28,7 @@ Generuje se za pomocí::
|
||||||
|
|
||||||
nebo (v případě meníčka)::
|
nebo (v případě meníčka)::
|
||||||
|
|
||||||
./manage.py dumpdata sitetree --natrual-foreign > data/sitetree_new.json
|
./manage.py dumpdata sitetree --natural-foreign > data/sitetree_new.json
|
||||||
./fix_json.py data/sitetree_new.json data/sitetree.json
|
./fix_json.py data/sitetree_new.json data/sitetree.json
|
||||||
|
|
||||||
deploy_v2
|
deploy_v2
|
||||||
|
|
|
@ -1260,3 +1260,22 @@ label[for=id_skola] {
|
||||||
.bodovani>input {
|
.bodovani>input {
|
||||||
width: 4em;
|
width: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Select2 používaný hlavně multiple selectem. Přidání checkboxů a změna barvy. */
|
||||||
|
/* Podle https://stackoverflow.com/a/48290544 */
|
||||||
|
/* U autocomplete.ModelSelect2Multiple vyžaduje 'data-dropdown-css-class': 's2m-se-zaskrtavatky' */
|
||||||
|
.s2m-se-zaskrtavatky .select2-results__option[aria-selected=true]:before {
|
||||||
|
content: '☑ ';
|
||||||
|
padding: 0 0 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.s2m-se-zaskrtavatky .select2-results__option[aria-selected=false]:before {
|
||||||
|
content: '◻ ';
|
||||||
|
padding: 0 0 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Oranžové zvýraznění v Select2 */
|
||||||
|
.select2-results__option--highlighted {
|
||||||
|
background-color: #e84e10 !important;
|
||||||
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ Obsahuje vše, co se týká odevzdávání (+ nahrávání) a opravování řeš
|
||||||
Slovníček:
|
Slovníček:
|
||||||
Moje řešení = Přehled řešení = Řešení, která odevzdal aktuálního uživatel sám.
|
Moje řešení = Přehled řešení = Řešení, která odevzdal aktuálního uživatel sám.
|
||||||
Došlá řešení = Tabulka + seznam + detail + ... = Řešení, která poslal někdo jiný.
|
Došlá řešení = Tabulka + seznam + detail + ... = Řešení, která poslal někdo jiný.
|
||||||
Poslat řešení = Odevdat mé řešení. (Tj. řešení se vztahem k aktuálnímu uživateli.)
|
Nahrát řešení = Odevdat mé řešení. (Tj. řešení se vztahem k aktuálnímu uživateli.)
|
||||||
Nahrát řešení = Nahrání řešení bez vztahu k aktuálnímu uživateli.
|
Vlož řešení = Vložit řešení bez vztahu k aktuálnímu uživateli.
|
||||||
|
|
||||||
TODO: Místo vložit řešení v nahrávání a posílání řešení dát něco jiného?
|
TODO: Místo vložit řešení v nahrávání a posílání řešení dát něco jiného?
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -29,6 +29,8 @@ class PosliReseniForm(forms.Form):
|
||||||
attrs={
|
attrs={
|
||||||
'data-placeholder--id': '-1',
|
'data-placeholder--id': '-1',
|
||||||
'data-placeholder--text': '---',
|
'data-placeholder--text': '---',
|
||||||
|
'data-close-on-select': 'false',
|
||||||
|
'data-dropdown-css-class': 's2m-se-zaskrtavatky',
|
||||||
'data-allow-clear': 'true'
|
'data-allow-clear': 'true'
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -43,6 +45,8 @@ class PosliReseniForm(forms.Form):
|
||||||
url='autocomplete_resitel',
|
url='autocomplete_resitel',
|
||||||
attrs = {'data-placeholder--id': '-1',
|
attrs = {'data-placeholder--id': '-1',
|
||||||
'data-placeholder--text' : '---',
|
'data-placeholder--text' : '---',
|
||||||
|
'data-close-on-select': 'false',
|
||||||
|
'data-dropdown-css-class': 's2m-se-zaskrtavatky',
|
||||||
'data-allow-clear': 'true'})
|
'data-allow-clear': 'true'})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -62,12 +66,6 @@ class PosliReseniForm(forms.Form):
|
||||||
#poznamka = models.TextField('neveřejná poznámka', blank=True,
|
#poznamka = models.TextField('neveřejná poznámka', blank=True,
|
||||||
# help_text='Neveřejná poznámka k řešení (plain text)')
|
# help_text='Neveřejná poznámka k řešení (plain text)')
|
||||||
|
|
||||||
#TODO body do cisla
|
|
||||||
#TODO prilohy
|
|
||||||
|
|
||||||
##def __init__(self, *args, **kwargs):
|
|
||||||
## super().__init__(*args, **kwargs)
|
|
||||||
## #self.fields['favorite_color'] = forms.ChoiceField(choices=[(color.id, color.name) for color in Resitel.objects.all()])
|
|
||||||
|
|
||||||
class NahrajReseniForm(forms.ModelForm):
|
class NahrajReseniForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -80,23 +78,40 @@ class NahrajReseniForm(forms.ModelForm):
|
||||||
url='autocomplete_problem_odevzdatelny',
|
url='autocomplete_problem_odevzdatelny',
|
||||||
attrs = {'data-placeholder--id': '-1',
|
attrs = {'data-placeholder--id': '-1',
|
||||||
'data-placeholder--text' : '---',
|
'data-placeholder--text' : '---',
|
||||||
|
'data-close-on-select': 'false',
|
||||||
|
'data-dropdown-css-class': 's2m-se-zaskrtavatky',
|
||||||
'data-allow-clear': 'true'},
|
'data-allow-clear': 'true'},
|
||||||
|
forward=["nadproblem_id"],
|
||||||
),
|
),
|
||||||
'resitele':
|
'resitele':
|
||||||
autocomplete.ModelSelect2Multiple(
|
autocomplete.ModelSelect2Multiple(
|
||||||
url='autocomplete_resitel_public',
|
url='autocomplete_resitel_public',
|
||||||
attrs = {'data-placeholder--id': '-1',
|
attrs = {'data-placeholder--id': '-1',
|
||||||
'data-placeholder--text' : '---',
|
'data-placeholder--text' : '---',
|
||||||
|
'data-close-on-select': 'false',
|
||||||
|
'data-dropdown-css-class': 's2m-se-zaskrtavatky',
|
||||||
'data-allow-clear': 'true'},
|
'data-allow-clear': 'true'},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nadproblem_id = forms.IntegerField(required=False, disabled=True, widget=forms.HiddenInput())
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
# FIXME Z nějakého důvodu se do této třídy dostaneme i bez resitele
|
# FIXME Z nějakého důvodu se do této třídy dostaneme i bez resitele
|
||||||
if 'resitele' in self.fields:
|
if 'resitele' in self.fields:
|
||||||
# FIXME Mnohem hezčí by to bylo u definice resitele výše, ale nepodařilo se mi to.
|
# FIXME Mnohem hezčí by to bylo u definice resitele výše, ale nepodařilo se mi to.
|
||||||
self.fields['resitele'].required = False
|
self.fields['resitele'].required = False
|
||||||
|
self.fields['resitele'].label = "Další autoři"
|
||||||
|
if 'problem' in self.fields:
|
||||||
|
self.fields['problem'].label = "Všechny řešené problémy"
|
||||||
|
|
||||||
|
def clean_problem(self):
|
||||||
|
problem = self.cleaned_data.get('problem')
|
||||||
|
for p in problem:
|
||||||
|
if p.stav != m.Problem.STAV_ZADANY:
|
||||||
|
raise forms.ValidationError("Problém " + str(p) + " již nelze řešit!")
|
||||||
|
return problem
|
||||||
|
|
||||||
ReseniSPrilohamiFormSet = inlineformset_factory(m.Reseni,m.PrilohaReseni,
|
ReseniSPrilohamiFormSet = inlineformset_factory(m.Reseni,m.PrilohaReseni,
|
||||||
form = NahrajReseniForm,
|
form = NahrajReseniForm,
|
||||||
|
|
|
@ -7,19 +7,20 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>
|
<h1>
|
||||||
{% block nadpis1a %}
|
{% block nadpis1a %}
|
||||||
Vložit řešení
|
Nahrát řešení
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p style="text-align: justify">Když řešení různých témátek vložíš každé zvlášť, lépe se v nich vyznáme a třeba ti je i rychleji opravíme.</p>
|
<form enctype="multipart/form-data" action="{% url 'seminar_nahraj_reseni' nadproblem_id %}" method="post" onsubmit="return zkontroluj_prilohy();">
|
||||||
|
|
||||||
<p>Pokud řešíte ve více lidech, je <strong>nutné</strong> přidat tyto lidi jako „Autory řešení“. V tomto poli se vyhledává podle přezdívek, které si lze nastavit v „Osobní údaje“. Sebe vyplňovat nemusíte a za skupinu odevzdávejte pouze <strong>jednou</strong> (ne každý sám).</p>
|
|
||||||
|
|
||||||
<form enctype="multipart/form-data" action="{% url 'seminar_nahraj_reseni' %}" method="post" onsubmit="return zkontroluj_prilohy();">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<table class='form' id="reseni">
|
<table class='form'>
|
||||||
|
<tr>
|
||||||
|
<td><label class="field-label field-required" for="tema">Téma:</label></td>
|
||||||
|
<td><input id="tema" disabled="" type="text" value="{{ nadproblem }}"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% with field=form.problem %}
|
||||||
<tr>
|
<tr>
|
||||||
{% for field in form %}
|
|
||||||
<td>
|
<td>
|
||||||
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
|
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
|
||||||
{{ field.label }}:
|
{{ field.label }}:
|
||||||
|
@ -28,15 +29,54 @@
|
||||||
<td>
|
<td>
|
||||||
{{ field }}
|
{{ field }}
|
||||||
</td>
|
</td>
|
||||||
{% endfor %}
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
{% if field.errors %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endwith %}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
{% for field in form.hidden_fields %}
|
||||||
|
{{ field }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4>Spolupráce s dalšími řešiteli</h4>
|
||||||
|
|
||||||
|
<p>Pokud řešíte ve více lidech, je <strong>potřeba</strong> přidat tyto lidi jako „Další autory“. V tomto poli se vyhledává podle přezdívek, které si lze nastavit v „Osobních údajích“. Sebe vyplňovat nemusíte a za skupinu odevzdávejte pouze <strong>jednou</strong> (ne každý sám).</p>
|
||||||
|
|
||||||
|
<table class='form'>
|
||||||
|
{% with field=form.resitele %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
|
||||||
|
{{ field.label }}:
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ field }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% if field.errors %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endwith %}
|
||||||
|
</table>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
{% include "odevzdavatko/prilohy.html" %}
|
{% include "odevzdavatko/prilohy.html" %}
|
||||||
|
|
||||||
|
{{form.non_field_errors}}
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h4>Odevzdat řešení</h4>
|
<h4>Odevzdat řešení</h4>
|
||||||
<input type="submit" value="Odevzdat">
|
<input type="submit" value="Odevzdat">
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>
|
||||||
|
{% block nadpis1a %}
|
||||||
|
Nahrát řešení
|
||||||
|
{% endblock %}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<h4>Seznam témat k odevzdání</h4>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for problem in object_list %}
|
||||||
|
<li><a href="{% url 'seminar_nahraj_reseni' problem.id %}">{{ problem }}</a></li>
|
||||||
|
{% empty %}
|
||||||
|
<li>Nelze nic odevzdávat.</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
<h4>Soubory s řešením</h4>
|
<h4>Soubory s řešením</h4>
|
||||||
|
|
||||||
<p style="text-align: justify">Maximální součet velikostí příloh je cca 49 MB. Pokud je to možné a dává to smysl, pošli nám prosím své řešení ve formátu PDF, ostatní formáty nemusíme umět otevřít.</p>
|
<p style="text-align: justify">Pokud je to možné a dává to smysl (tj. není to třeba kód nebo doprovodný obrázek), pošli nám prosím své řešení ve formátu <strong>PDF</strong>, ostatní formáty nemusíme umět otevřít.</p>
|
||||||
<p style="text-align: justify">Pokud svůj soubor rozumně pojmenuješ, urychlíš opravování a předejdeš tomu, že si nějakého tvého řešení nevšimneme. Například z <code>img_250921_101205.pdf</code> nepoznáme, kterou úlohu jsi odevzdal, zato <code>uloha_3.pdf</code> nebo <code>tema_1.pdf</code>, to už je něco jiného. Případně můžeš využít i poznámku řešitele.</p>
|
<p style="text-align: justify">Pokud svůj soubor <strong>rozumně pojmenuješ</strong>, urychlíš opravování a předejdeš tomu, že si nějakého tvého řešení nevšimneme. Například z <code>img_250921_101205.pdf</code> nepoznáme, kterou úlohu jsi odevzdal, zato <code>uloha_3.pdf</code> nebo <code>tema_1.pdf</code>, to už je něco jiného. Případně můžeš využít i poznámku řešitele.</p>
|
||||||
|
<p style="text-align: justify">Maximální součet velikostí příloh je cca <strong>49 MB</strong>.</p>
|
||||||
|
|
||||||
<div id="form_set">
|
<div id="form_set">
|
||||||
{% for form in prilohy.forms %}
|
{% for form in prilohy.forms %}
|
||||||
|
|
|
@ -19,8 +19,9 @@ from seminar.utils import org_required, resitel_required, viewMethodSwitch, \
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('org/add_solution', org_required(views.PosliReseniView.as_view()), name='seminar_vloz_reseni'),
|
path('org/add_solution', org_required(views.VlozReseniView.as_view()), name='seminar_vloz_reseni'),
|
||||||
path('resitel/nahraj_reseni', resitel_required(views.NahrajReseniView.as_view()), name='seminar_nahraj_reseni'),
|
path('resitel/nahraj_reseni', resitel_required(views.NahrajReseniRozcestnikTematekView.as_view()), name='seminar_nahraj_reseni'),
|
||||||
|
path('resitel/nahraj_reseni/<int:nadproblem_id>/', resitel_required(views.NahrajReseniView.as_view()), name='seminar_nahraj_reseni'),
|
||||||
path('resitel/odevzdana_reseni/', resitel_or_org_required(views.PrehledOdevzdanychReseni.as_view()), name='seminar_resitel_odevzdana_reseni'),
|
path('resitel/odevzdana_reseni/', resitel_or_org_required(views.PrehledOdevzdanychReseni.as_view()), name='seminar_resitel_odevzdana_reseni'),
|
||||||
|
|
||||||
path('org/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
path('org/reseni/', org_required(views.TabulkaOdevzdanychReseniView.as_view()), name='odevzdavatko_tabulka'),
|
||||||
|
|
|
@ -367,8 +367,8 @@ class SeznamAktualnichReseniView(SeznamReseniView):
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
class PosliReseniView(LoginRequiredMixin, FormView):
|
class VlozReseniView(LoginRequiredMixin, FormView):
|
||||||
template_name = 'odevzdavatko/posli_reseni.html'
|
template_name = 'odevzdavatko/vloz_reseni.html'
|
||||||
form_class = f.PosliReseniForm
|
form_class = f.PosliReseniForm
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
@ -399,12 +399,27 @@ class PosliReseniView(LoginRequiredMixin, FormView):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class NahrajReseniRozcestnikTematekView(LoginRequiredMixin, ListView):
|
||||||
|
model = m.Problem
|
||||||
|
template_name = 'odevzdavatko/nahraj_reseni_nadproblem.html'
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return super().get_queryset().filter(stav=m.Problem.STAV_ZADANY, nadproblem__isnull=True)
|
||||||
|
|
||||||
|
|
||||||
class NahrajReseniView(LoginRequiredMixin, CreateView):
|
class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||||
model = m.Reseni
|
model = m.Reseni
|
||||||
template_name = 'odevzdavatko/nahraj_reseni.html'
|
template_name = 'odevzdavatko/nahraj_reseni.html'
|
||||||
form_class = f.NahrajReseniForm
|
form_class = f.NahrajReseniForm
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
|
# Zaříznutí nezadaných problémů
|
||||||
|
nadproblem_id = self.kwargs["nadproblem_id"]
|
||||||
|
self.nadproblem = get_object_or_404(m.Problem, id=nadproblem_id)
|
||||||
|
if self.nadproblem.stav != "zadany":
|
||||||
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
|
||||||
# Zaříznutí starých řešitelů:
|
# Zaříznutí starých řešitelů:
|
||||||
# FIXME: Je to tady dost naprasené, mělo by to asi být jinde…
|
# FIXME: Je to tady dost naprasené, mělo by to asi být jinde…
|
||||||
osoba = m.Osoba.objects.get(user=self.request.user)
|
osoba = m.Osoba.objects.get(user=self.request.user)
|
||||||
|
@ -417,12 +432,23 @@ class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||||
})
|
})
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_initial(self):
|
||||||
|
nadproblem_id = self.nadproblem.id
|
||||||
|
return {
|
||||||
|
"nadproblem_id": nadproblem_id,
|
||||||
|
"problem": [] if self.nadproblem.podproblem.filter(stav=m.Problem.STAV_ZADANY).exists() else nadproblem_id
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
def get_context_data(self,**kwargs):
|
def get_context_data(self,**kwargs):
|
||||||
data = super().get_context_data(**kwargs)
|
data = super().get_context_data(**kwargs)
|
||||||
if self.request.POST:
|
if self.request.POST:
|
||||||
data['prilohy'] = f.ReseniSPrilohamiFormSet(self.request.POST,self.request.FILES)
|
data['prilohy'] = f.ReseniSPrilohamiFormSet(self.request.POST,self.request.FILES)
|
||||||
else:
|
else:
|
||||||
data['prilohy'] = f.ReseniSPrilohamiFormSet()
|
data['prilohy'] = f.ReseniSPrilohamiFormSet()
|
||||||
|
|
||||||
|
data["nadproblem_id"] = self.nadproblem.id
|
||||||
|
data["nadproblem"] = get_object_or_404(m.Problem, id=self.nadproblem.id)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
# FIXME prepsat tak, aby form_valid se volalo jen tehdy, kdyz je form i formset validni
|
# FIXME prepsat tak, aby form_valid se volalo jen tehdy, kdyz je form i formset validni
|
||||||
|
@ -474,4 +500,8 @@ class NahrajReseniView(LoginRequiredMixin, CreateView):
|
||||||
to=list(prijemci),
|
to=list(prijemci),
|
||||||
).send()
|
).send()
|
||||||
|
|
||||||
return formularOKView(self.request, text='Řešení úspěšně odevzdáno')
|
return formularOKView(
|
||||||
|
self.request,
|
||||||
|
text='Řešení úspěšně odevzdáno',
|
||||||
|
dalsi_odkazy=[("Odevzdat další řešení", reverse("seminar_nahraj_reseni"))],
|
||||||
|
)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<a href="{% url 'logout' %}">Odhlásit se</a><br>
|
<a href="{% url 'logout' %}">Odhlásit se</a><br>
|
||||||
<a href="{% url 'seminar_resitel_edit' %}">Upravit údaje</a><br>
|
<a href="{% url 'seminar_resitel_edit' %}">Upravit údaje</a><br>
|
||||||
<a href="{% url 'seminar_nahraj_reseni' %}">Poslat řešení</a><br>
|
<a href="{% url 'seminar_nahraj_reseni' %}">Nahrát řešení</a><br>
|
||||||
<a href="{% url 'seminar_resitel_odevzdana_reseni' %}">Již odevzdaná řešení</a><br>
|
<a href="{% url 'seminar_resitel_odevzdana_reseni' %}">Již odevzdaná řešení</a><br>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,11 @@ def resitelEditView(request):
|
||||||
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa'])
|
msg = "Unknown school {}, {}".format(fcd['skola_nazev'],fcd['skola_adresa'])
|
||||||
resitel_edit.save()
|
resitel_edit.save()
|
||||||
osoba_edit.save()
|
osoba_edit.save()
|
||||||
return formularOKView(request, text=f'Údaje byly úspěšně uloženy. <a href="{reverse("profil")}">Vrátit se zpět na profil.</a>')
|
return formularOKView(
|
||||||
|
request,
|
||||||
|
text='Údaje byly úspěšně uloženy.',
|
||||||
|
dalsi_odkazy=[("Vrátit se zpět na profil", reverse("profil"))],
|
||||||
|
)
|
||||||
|
|
||||||
return render(request, 'personalni/udaje/edit.html', {'form': form})
|
return render(request, 'personalni/udaje/edit.html', {'form': form})
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ from django.conf import settings
|
||||||
import unicodedata
|
import unicodedata
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
from collections.abc import Sequence
|
||||||
|
|
||||||
from seminar.utils import aktivniResitele
|
from seminar.utils import aktivniResitele
|
||||||
|
|
||||||
|
@ -677,9 +678,9 @@ def StavDatabazeView(request):
|
||||||
|
|
||||||
|
|
||||||
# Interní, nemá se nikdy objevit v urls (jinak to účastníci vytrolí)
|
# Interní, nemá se nikdy objevit v urls (jinak to účastníci vytrolí)
|
||||||
def formularOKView(request, text=''):
|
def formularOKView(request, text='', dalsi_odkazy: Sequence[tuple[str, str]] = ()):
|
||||||
template_name = 'seminar/formular_ok.html'
|
template_name = 'seminar/formular_ok.html'
|
||||||
odkazy = [
|
odkazy = list(dalsi_odkazy) + [
|
||||||
# (Text, odkaz)
|
# (Text, odkaz)
|
||||||
('Vrátit se na titulní stránku', reverse('titulni_strana')),
|
('Vrátit se na titulní stránku', reverse('titulni_strana')),
|
||||||
('Zobrazit aktuální zadání', reverse('seminar_aktualni_zadani')),
|
('Zobrazit aktuální zadání', reverse('seminar_aktualni_zadani')),
|
||||||
|
|
Loading…
Reference in a new issue