Velká revize stylů (a některých JS) #44

Merged
zelvuska merged 50 commits from static-files-upgrade into master 2024-10-22 20:00:12 +02:00
14 changed files with 340 additions and 23 deletions
Showing only changes of commit 48123a8ce2 - Show all commits

View file

@ -59,3 +59,22 @@
walkText(document.body);
</script>
{% endif %}
{% if april == 2024 %}
<script>
{# By https://stackoverflow.com/a/34559316 #}
function walkText(node) {
if (node.nodeType == 3) {
node.data = node.data.replace(/M&M/g, "W8W");
}
if (node.nodeType == 1 && node.nodeName != "SCRIPT") {
for (var i = 0; i < node.childNodes.length; i++) {
walkText(node.childNodes[i]);
}
}
}
walkText(document.body);
</script>
{% endif %}

View file

@ -121,6 +121,6 @@
<script src="{% static 'bootstrap/js/bootstrap.bundle.js' %}"></script>
{% include 'april.html' %}
{% block js %}{% endblock %}
{% block js %}{% endblock %}
</body>
</html>

View file

@ -8,6 +8,7 @@ from django.http import Http404
from django.db.models import Q, Sum, Count
from django.views.generic.base import RedirectView
from django.core.exceptions import PermissionDenied
from django.contrib.staticfiles.finders import find
import seminar.models as s
import seminar.models as m
@ -36,6 +37,7 @@ import unicodedata
import logging
import time
from collections.abc import Sequence
import http
from seminar.utils import aktivniResitele
@ -562,17 +564,25 @@ def cisloObalkyView(request, rocnik, cislo):
def obalkyView(request, resitele):
if len(resitele) == 0:
return HttpResponse(
render(request, 'universal.html', {
'title': 'Není pro koho vyrobit obálky.',
'text': 'Právě ses pokusil/a vygenerovat obálky pro prázdnou množinu lidí. Můžeš to zkusit změnit, případně se zeptej webařů :-)',
}),
status=http.HTTPStatus.NOT_FOUND,
)
tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content
tempdir = tempfile.mkdtemp()
with open(tempdir+"/obalky.tex","w") as texfile:
texfile.write(tex.decode())
shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.pdf'), tempdir)
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
with tempfile.TemporaryDirectory() as tempdir:
with open(tempdir+"/obalky.tex","w") as texfile:
texfile.write(tex.decode())
shutil.copy(find('seminar/lisak.pdf'), tempdir)
subprocess.call(["pdflatex","obalky.tex"], cwd = tempdir)
with open(tempdir+"/obalky.pdf","rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
shutil.rmtree(tempdir)
with open(tempdir+"/obalky.pdf","rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
return response

View file

@ -1,8 +1,10 @@
from django.contrib import admin
from .models import OdpovedUcastnika, SpravnaOdpoved
from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
# Register your models here.
admin.site.register(OdpovedUcastnika)
admin.site.register(SpravnaOdpoved)
admin.site.register(Napoveda)
admin.site.register(NapovezenoUcastnikovi)

View file

@ -1,6 +1,6 @@
from django.core.exceptions import ValidationError
from django.forms import ModelForm, Textarea
from .models import OdpovedUcastnika, SpravnaOdpoved
from .models import OdpovedUcastnika, SpravnaOdpoved, NapovezenoUcastnikovi, Napoveda
class SifrovackaForm(ModelForm):
@ -16,3 +16,15 @@ class SifrovackaForm(ModelForm):
if SpravnaOdpoved.objects.filter(sifra=sifra).count() == 0:
raise ValidationError("Tohle číslo šifry v databázi nemáme. Zkontrolujte si ho prosím.")
return sifra
class NapovedaForm(ModelForm):
class Meta:
model = NapovezenoUcastnikovi
fields = ["sifra",]
def clean_sifra(self):
sifra = self.cleaned_data.get('sifra')
if Napoveda.objects.filter(sifra=sifra).count() == 0:
raise ValidationError("K tomuto číslu šifry nemáme nápovědu. Zkontrolujte si ho prosím.")
return sifra

View file

@ -0,0 +1,65 @@
# Generated by Django 4.2.8 on 2024-04-14 12:57
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
(
"seminar",
"0114_related_name_se_zmenilo_a_django_chce_migraci_tak_dostane_migraci",
),
("sifrovacka", "0003_odpoveducastnika_uspech"),
]
operations = [
migrations.CreateModel(
name="Napoveda",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("text", models.TextField()),
("sifra", models.IntegerField()),
],
),
migrations.CreateModel(
name="NapovezenoUcastnikovi",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("sifra", models.IntegerField(verbose_name="Číslo šifry")),
(
"timestamp",
models.DateTimeField(
default=django.utils.timezone.now, verbose_name="Timestamp"
),
),
(
"resitel",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="seminar.resitel",
),
),
],
options={
"ordering": ["-timestamp"],
},
),
]

View file

@ -25,3 +25,20 @@ class SpravnaOdpoved(models.Model):
def __str__(self):
return f"{self.sifra}: {self.odpoved}"
class NapovezenoUcastnikovi(models.Model):
class Meta:
ordering = ["-timestamp"]
resitel = models.ForeignKey(Resitel, blank=False, null=False, on_delete=models.CASCADE)
sifra = models.IntegerField("Číslo šifry", blank=False, null=False,)
timestamp = models.DateTimeField("Timestamp", blank=False, null=False, default=timezone.now)
class Napoveda(models.Model):
text = models.TextField(blank=False, null=False,)
sifra = models.IntegerField(blank=False, null=False,)
def __str__(self):
return f"{self.sifra}: {self.text}"

View file

@ -0,0 +1,50 @@
{% extends "base.html" %}
{% block content %}
<br>
<h1>{% block nadpis1a %}M&Mí šifrovačka{% endblock nadpis1a %}</h1>
<br>
<h2>Získat nápovědu k šifře:</h2>
<form action="{% url 'sifrovacka_napoveda' %}" method="post">
<table class="form">
{{form.non_field_errors}}
{% for field in form %}
<tr>
<td>
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
{{ field.label }}
</label>
</td>
<td {% if field.help_text %} class="field-with-comment"{% endif %}>
{{ field }}
<span class="field-comment">{{ field.help_text|safe }}</span>
</td>
</tr>
{% if field.errors %}
<tr>
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td>
</tr>
{% endif %}
{% endfor %}
</table>
{% csrf_token %}
<input type="submit" value="Chci nápovědu">
</form>
<p><a href="{% url 'sifrovacka' %}">Nechceme nápovědu, známe řešení!</a></p>
<p><a href="{% url 'sifrovacka_preskoceni' %}">Přeskoč šifru</a></p>
{% endblock content %}

View file

@ -0,0 +1,23 @@
{% extends "base.html" %}
{% block content %}
<h1>{% block nadpis1a %}Šifrovačka vzaté nápovědy{% endblock nadpis1a %}</h1>
<table class="dosla_reseni">
<tr>
<th>Timestamp</th>
<th>Řešitel</th>
<th>Šifra</th>
</tr>
{% for u in object_list %}
<tr>
<td>{{ u.timestamp }}</td>
<td>{{ u.resitel }}</td>
<td>{{ u.sifra }}</td>
</tr>
{% endfor %}
</table>
{% endblock content %}

View file

@ -0,0 +1,54 @@
{% extends "base.html" %}
{% block content %}
<br>
<h1>{% block nadpis1a %}M&Mí šifrovačka{% endblock nadpis1a %}</h1>
<br>
<h2>Přeskočit šifru:</h2>
<form action="{% url 'sifrovacka_preskoceni' %}" method="post">
<table class="form">
{{form.non_field_errors}}
{% for field in form %}
{% if field.id_for_label != "id_odpoved" %}
<tr>
<td>
<label class="field-label{% if field.field.required %} field-required{% endif %}" for="{{ field.id_for_label }}">
{{ field.label }}
</label>
</td>
<td {% if field.help_text %} class="field-with-comment"{% endif %}>
{{ field }}
<span class="field-comment">{{ field.help_text|safe }}</span>
</td>
</tr>
{% if field.errors %}
<tr>
<td colspan="2"><span class="field-error">{{ field.errors }}</span></td>
</tr>
{% endif %}
{% else %}
{{ field.as_hidden }}
{% endif %}
{% endfor %}
</table>
{% csrf_token %}
<input type="submit" value="Chceme další stanoviště bez vyřešení šifry">
</form>
<p><a href="{% url 'sifrovacka' %}">Nechceme přeskočit, známe řešení!</a></p>
<p><a href="{% url 'sifrovacka_napoveda' %}">Nechceme přeskakovat, ale nápověda by se šikla.</a></p>
{% endblock content %}

View file

@ -43,4 +43,8 @@
<input type="submit" value="Tak pravím!">
</form>
<p><a href="{% url 'sifrovacka_napoveda' %}">Získat nápovědu</a></p>
<p><a href="{% url 'sifrovacka_preskoceni' %}">Přeskoč šifru</a></p>
{% endblock content %}

View file

@ -1,7 +1,7 @@
from django.urls import path
from seminar.utils import org_required, resitel_or_org_required
from .views import SifrovackaView, SifrovackaListView
from .views import SifrovackaView, SifrovackaListView, NapovedaView, NapovedaListView, PreskoceniView
urlpatterns = [
path(
@ -14,4 +14,19 @@ urlpatterns = [
org_required(SifrovackaListView.as_view()),
name='sifrovacka_odpovedi'
),
path(
'napoveda/',
resitel_or_org_required(NapovedaView.as_view()),
name='sifrovacka_napoveda'
),
path(
'napovedy/',
org_required(NapovedaListView.as_view()),
name='sifrovacka_napovedy'
),
path(
'preskoceni/',
resitel_or_org_required(PreskoceniView.as_view()),
name='sifrovacka_preskoceni'
),
]

View file

@ -2,8 +2,8 @@ from django.urls import reverse
from django.views.generic import FormView, ListView
from seminar.views import formularOKView
from .forms import SifrovackaForm
from .models import OdpovedUcastnika, SpravnaOdpoved
from .forms import SifrovackaForm, NapovedaForm
from .models import OdpovedUcastnika, SpravnaOdpoved, Napoveda, NapovezenoUcastnikovi
from seminar.models.personalni import Resitel
@ -31,3 +31,40 @@ class SifrovackaView(FormView):
class SifrovackaListView(ListView):
template_name = 'sifrovacka/odpovedi_list.html'
model = OdpovedUcastnika
class NapovedaView(FormView):
template_name = 'sifrovacka/napoveda.html'
form_class = NapovedaForm
def form_valid(self, form):
instance = form.save(commit=False)
resitel = Resitel.objects.get(osoba__user=self.request.user)
instance.resitel = resitel
if NapovezenoUcastnikovi.objects.filter(resitel=resitel, sifra=instance.sifra).first() is None:
instance.save()
napoveda = Napoveda.objects.filter(sifra=instance.sifra).first()
return formularOKView(self.request, f'<h1>Nápověda k šifře číslo {instance.sifra} je:</h1><p>{napoveda.text}</p> <p><a href="{reverse("sifrovacka")}">Odevzdat řešení.</a></p><br><br><br>')
class NapovedaListView(ListView):
template_name = 'sifrovacka/napovedy_list.html'
model = NapovezenoUcastnikovi
class PreskoceniView(FormView):
template_name = 'sifrovacka/preskoceni.html'
form_class = SifrovackaForm
initial = {"odpoved": "=======PŘESKOČENO======="}
def form_valid(self, form):
instance = form.save(commit=False)
instance.odpoved = "=======PŘESKOČENO======="
resitel = Resitel.objects.get(osoba__user=self.request.user)
instance.resitel = resitel
instance.save()
sifra = SpravnaOdpoved.objects.filter(sifra=instance.sifra).first() # FIXME co když je více "správných" odpovědí?
return formularOKView(self.request, f'<h1>{sifra.skryty_text}</h1> <p><a href="{reverse("sifrovacka")}">Zpět na odevzdávátko.</a></p><br><br><br>')

View file

@ -9,6 +9,7 @@ import tempfile
import shutil
import subprocess
from pathlib import Path
import http
from seminar.views import obalkyView
@ -76,17 +77,25 @@ def soustredeniUcastniciExportView(request, soustredeni):
def soustredeniStvrzenkyView(request, soustredeni):
soustredeni = get_object_or_404(Soustredeni, id=soustredeni)
ucastnici = Resitel.objects.filter(soustredeni=soustredeni)
if ucastnici.count() == 0:
return HttpResponse(
render(request, 'universal.html', {
'title': 'Není pro koho vyrobit stvrzenky.',
'text': 'Právě ses pokusil/a vygenerovat stvrzenky pro prázdnou množinu lidí. Můžeš to zkusit změnit, případně se zeptej webařů :-)',
}),
status=http.HTTPStatus.NOT_FOUND,
)
castka = Nastaveni.get_solo().cena_sous
tex = render(request, 'soustredeni/stvrzenky.tex', {'ucastnici': ucastnici, 'soustredeni': soustredeni, 'castka': castka}).content
tempdir = Path(tempfile.mkdtemp())
with open(tempdir / "stvrzenky.tex", "w") as texfile:
texfile.write(tex.decode())
with tempfile.TemporaryDirectory() as tempdirfn:
tempdir = Path(tempdirfn)
with open(tempdir / "stvrzenky.tex", "w") as texfile:
texfile.write(tex.decode())
shutil.copy(find('images/logomm.pdf'), tempdir)
subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL)
shutil.copy(find('images/logomm.pdf'), tempdir)
subprocess.call(["pdflatex", "stvrzenky.tex"], cwd = tempdir, stdout=subprocess.DEVNULL)
with open(tempdir / "stvrzenky.pdf", "rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
shutil.rmtree(tempdir)
with open(tempdir / "stvrzenky.pdf", "rb") as pdffile:
response = HttpResponse(pdffile.read(), content_type='application/pdf')
return response