políčko pro zpětnou vazbu #3

Merged
zelvuska merged 3 commits from zpetna_vazba into master 2 years ago
  1. 1
      mamweb/settings_local.py
  2. 4
      mamweb/static/css/mamweb.css
  3. 5
      odevzdavatko/forms.py
  4. 6
      odevzdavatko/templates/odevzdavatko/detail.html
  5. 3
      odevzdavatko/templates/odevzdavatko/detail_resitele.html
  6. 44
      odevzdavatko/views.py
  7. 18
      seminar/migrations/0108_hodnoceni_feedback.py
  8. 2
      seminar/models/odevzdavatko.py

1
mamweb/settings_local.py

@ -31,6 +31,7 @@ TEMPLATES[0]['OPTIONS']['debug'] = True
from ipaddress import ip_network from ipaddress import ip_network
ALLOWED_HOSTS = [str(ip) for ip in ip_network('192.168.0.0/16')] ALLOWED_HOSTS = [str(ip) for ip in ip_network('192.168.0.0/16')]
ALLOWED_HOSTS.append('127.0.0.1') ALLOWED_HOSTS.append('127.0.0.1')
ALLOWED_HOSTS.append('localhost')
# Database # Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases # https://docs.djangoproject.com/en/1.7/ref/settings/#databases

4
mamweb/static/css/mamweb.css

@ -421,6 +421,10 @@ input {
margin: 5px; margin: 5px;
} }
textarea.feedback {
margin: 5px;
}
/* titulni stranka */ /* titulni stranka */

5
odevzdavatko/forms.py

@ -88,11 +88,12 @@ ReseniSPrilohamiFormSet = inlineformset_factory(m.Reseni,m.PrilohaReseni,
class JednoHodnoceniForm(forms.ModelForm): class JednoHodnoceniForm(forms.ModelForm):
class Meta: class Meta:
model = m.Hodnoceni model = m.Hodnoceni
fields = ('problem', 'body', 'deadline_body') fields = ('problem', 'body', 'deadline_body', 'feedback',)
widgets = { widgets = {
'problem': autocomplete.ModelSelect2( 'problem': autocomplete.ModelSelect2(
url='autocomplete_problem_odevzdatelny', # FIXME: Dovolit i starší? url='autocomplete_problem_odevzdatelny', # FIXME: Dovolit i starší?
) ),
'feedback': forms.Textarea(attrs={'rows': 1, 'cols': 30, 'class': 'feedback'}),
} }
OhodnoceniReseniFormSet = formset_factory(JednoHodnoceniForm, OhodnoceniReseniFormSet = formset_factory(JednoHodnoceniForm,

6
odevzdavatko/templates/odevzdavatko/detail.html

@ -91,7 +91,7 @@ $(document).ready(function(){
<form method=post onsubmit="return zkontroluj_hodnoceni();"> <form method=post onsubmit="return zkontroluj_hodnoceni();">
{# Poznámka #} {# Poznámka #}
<h3>Poznámka:</h3> <h3>Neveřejná poznámka:</h3>
<p>{{ poznamka_form.poznamka }}</p> <p>{{ poznamka_form.poznamka }}</p>
{# Hodnocení: #} {# Hodnocení: #}
@ -101,13 +101,14 @@ $(document).ready(function(){
{{ form.management_form }} {{ form.management_form }}
</table> </table>
<table id="form_set"> <table id="form_set">
<tr><th>Problém</th><th>Body</th><th>Deadline pro body</th></tr> <tr><th>Problém</th><th>Body</th><th>Deadline pro body</th><th>Zpětná vazba pro řešitele</th></tr>
{% for subform in form %} {% for subform in form %}
<tbody> <tbody>
<tr class="hodnoceni"> <tr class="hodnoceni">
<td>{{ subform.problem }}</td> <td>{{ subform.problem }}</td>
<td>{{ subform.body }}</td> <td>{{ subform.body }}</td>
<td>{{ subform.deadline_body }}</td> <td>{{ subform.deadline_body }}</td>
<td>{{ subform.feedback }}</td>
<td><a href="#" class="smazat_hodnoceni" id="id_{{subform.prefix}}-jsremove"><img src="{% static "odevzdavatko/cross.png" %}" alt="Smazat"></a></td> <td><a href="#" class="smazat_hodnoceni" id="id_{{subform.prefix}}-jsremove"><img src="{% static "odevzdavatko/cross.png" %}" alt="Smazat"></a></td>
</tr> </tr>
</tbody> </tbody>
@ -123,6 +124,7 @@ $(document).ready(function(){
<td>{{ form.empty_form.problem }}</td> <td>{{ form.empty_form.problem }}</td>
<td>{{ form.empty_form.body }}</td> <td>{{ form.empty_form.body }}</td>
<td>{{ form.empty_form.deadline_body }}</td> <td>{{ form.empty_form.deadline_body }}</td>
<td>{{ form.empty_form.feedback }}</td>
<td><a href="#" class="smazat_hodnoceni" id="id_{{form.empty_form.prefix}}-jsremove"><img src="{% static "odevzdavatko/cross.png" %}" alt="Smazat"></a></td> <td><a href="#" class="smazat_hodnoceni" id="id_{{form.empty_form.prefix}}-jsremove"><img src="{% static "odevzdavatko/cross.png" %}" alt="Smazat"></a></td>
</tr> </tr>
</table> </table>

3
odevzdavatko/templates/odevzdavatko/detail_resitele.html

@ -37,11 +37,12 @@
{# Hodnocení: #} {# Hodnocení: #}
<h3>Hodnocení:</h3> <h3>Hodnocení:</h3>
<table id="form_set" class="dosla_reseni"> <table id="form_set" class="dosla_reseni">
<tr><th>Problém</th><th>Body</th>{# <th>Deadline pro body</th> #}</tr> <tr><th>Problém</th><th>Body</th><th>Zpětná vazba od opravovatele</th>{# <th>Deadline pro body</th> #}</tr>
{% for h in hodnoceni %} {% for h in hodnoceni %}
<tr class="hodnoceni"> <tr class="hodnoceni">
<td>{{ h.problem }}</td> <td>{{ h.problem }}</td>
<td>{{ h.body }}</td> <td>{{ h.body }}</td>
<td>{{ h.feedback }}</td>
{# <td>{{ h.deadline_body }}</td>#} {# <td>{{ h.deadline_body }}</td>#}
</tr> </tr>
{% endfor %} {% endfor %}

44
odevzdavatko/views.py

@ -218,10 +218,11 @@ class DetailReseniView(DetailView):
self.reseni = get_object_or_404(m.Reseni, id=self.kwargs['pk']) self.reseni = get_object_or_404(m.Reseni, id=self.kwargs['pk'])
result = [] # Slovníky s klíči problem, body, deadline_body -- initial data pro f.OhodnoceniReseniFormSet result = [] # Slovníky s klíči problem, body, deadline_body -- initial data pro f.OhodnoceniReseniFormSet
for hodn in m.Hodnoceni.objects.filter(reseni=self.reseni): for hodn in m.Hodnoceni.objects.filter(reseni=self.reseni):
result.append( result.append({
{"problem": hodn.problem, "problem": hodn.problem,
"body": hodn.body, "body": hodn.body,
"deadline_body": hodn.deadline_body, "deadline_body": hodn.deadline_body,
"feedback": hodn.feedback,
}) })
return result return result
@ -245,30 +246,26 @@ def hodnoceniReseniView(request, pk, *args, **kwargs):
formset = f.OhodnoceniReseniFormSet(request.POST) formset = f.OhodnoceniReseniFormSet(request.POST)
poznamka_form = f.PoznamkaReseniForm(request.POST, instance=reseni) poznamka_form = f.PoznamkaReseniForm(request.POST, instance=reseni)
# TODO: Napsat validaci formuláře a formsetu # TODO: Napsat validaci formuláře a formsetu
# TODO: Implementovat větev, kdy formulář validní není. if not (formset.is_valid() and poznamka_form.is_valid()):
if formset.is_valid() and poznamka_form.is_valid(): raise ValueError(formset.errors, poznamka_form.errors)
with transaction.atomic():
# Poznámka je jednoduchá na zpracování:
poznamka_form.save()
# Smažeme všechna dosavadní hodnocení tohoto řešení with transaction.atomic():
qs = m.Hodnoceni.objects.filter(reseni=reseni) # Poznámka je jednoduchá na zpracování:
logger.info(f"Will delete {qs.count()} objects: {qs}") poznamka_form.save()
qs.delete()
# Smažeme všechna dosavadní hodnocení tohoto řešení
# Vyrobíme nová podle formsetu qs = m.Hodnoceni.objects.filter(reseni=reseni)
for form in formset: logger.info(f"Will delete {qs.count()} objects: {qs}")
problem = form.cleaned_data['problem'] qs.delete()
body = form.cleaned_data['body']
deadline_body = form.cleaned_data['deadline_body'] # Vyrobíme nová podle formsetu
hodnoceni = m.Hodnoceni( for form in formset:
problem=problem, hodnoceni = m.Hodnoceni(
body=body,
deadline_body=deadline_body,
reseni=reseni, reseni=reseni,
**form.cleaned_data,
) )
logger.info(f"Creating Hodnoceni: {hodnoceni}") logger.info(f"Creating Hodnoceni: {hodnoceni}")
hodnoceni.save() hodnoceni.save()
return redirect(success_url) return redirect(success_url)
@ -285,6 +282,7 @@ class ResitelReseniView(DetailView):
{ {
Review

Není tady jednodušší rovnou vracet ten objekt toho hodnocení? Nesouvisí přímo s aktuálními změnami, ale když už to vidím, tak to píšu…

Není tady jednodušší rovnou vracet ten objekt toho hodnocení? Nesouvisí přímo s aktuálními změnami, ale když už to vidím, tak to píšu…
"problem": hodn.problem, "problem": hodn.problem,
"body": hodn.body, "body": hodn.body,
"feedback": hodn.feedback,
# "deadline_body": hodn.deadline_body, # "deadline_body": hodn.deadline_body,
} }
) )

18
seminar/migrations/0108_hodnoceni_feedback.py

@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2022-11-14 19:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('seminar', '0107_zmrazenavysledkovka'),
]
operations = [
migrations.AddField(
model_name='hodnoceni',
name='feedback',
field=models.TextField(blank=True, default='', help_text='Zpětná vazba řešiteli (plain text)', verbose_name='zpětná vazba'),
),
]

2
seminar/models/odevzdavatko.py

@ -113,6 +113,8 @@ class Hodnoceni(bm.SeminarModelBase):
problem = models.ForeignKey(am.Problem, verbose_name='problém', problem = models.ForeignKey(am.Problem, verbose_name='problém',
related_name='hodnoceni', on_delete=models.PROTECT) related_name='hodnoceni', on_delete=models.PROTECT)
feedback = models.TextField('zpětná vazba', blank=True, default='', help_text='Zpětná vazba řešiteli (plain text)')
def __str__(self): def __str__(self):
return "{}, {}, {}".format(self.problem, self.reseni, self.body) return "{}, {}, {}".format(self.problem, self.reseni, self.body)

Loading…
Cancel
Save