Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
750 changes: 374 additions & 376 deletions fixtures/schools.csv

Large diffs are not rendered by default.

Binary file added fixtures/schools.xlsx
Binary file not shown.
1 change: 0 additions & 1 deletion ksicht/core/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from sched import Event
from cuser.admin import UserAdmin
from django import forms
from django.contrib import admin
Expand Down
3 changes: 2 additions & 1 deletion ksicht/core/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ class CurrentGradeAppliationForm(forms.Form):
applied = forms.BooleanField(initial="y", required=True, widget=forms.HiddenInput)

def __init__(self, *args, **kwargs):
has_birth_date = kwargs.pop("has_birth_date", False)
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.layout = Layout(
Field("applied"),
Submit("submit", "Přihlásit se do ročníku", css_class="is-medium"),
Submit("submit", "Přihlásit se do ročníku", css_class="is-medium", disabled=(not has_birth_date)),
)
self.helper.form_action = reverse("core:current_grade_application")

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Generated by Django 5.2.4 on 2025-08-01 19:00

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("core", "0011_gradeseries_expected_publish_date_and_more"),
]

operations = [
migrations.AlterField(
model_name="gradeapplication",
name="participant_current_grade",
field=models.CharField(
choices=[
("5", "absolvent"),
("4", "SŠ, 4."),
("3", "SŠ, 3."),
("2", "SŠ, 2."),
("1", "SŠ, 1."),
("0", "ZŠ, 9."),
("-1", "ZŠ, 8."),
("-2", "ZŠ, 7."),
("-3", "ZŠ, 6."),
],
max_length=10,
null=True,
verbose_name="Ročník",
),
),
migrations.AlterField(
model_name="participant",
name="school_year",
field=models.CharField(
choices=[
("5", "absolvent"),
("4", "SŠ, 4."),
("3", "SŠ, 3."),
("2", "SŠ, 2."),
("1", "SŠ, 1."),
("0", "ZŠ, 9."),
("-1", "ZŠ, 8."),
("-2", "ZŠ, 7."),
("-3", "ZŠ, 6."),
],
max_length=5,
verbose_name="Ročník",
),
),
]
49 changes: 37 additions & 12 deletions ksicht/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ def __str__(self):
def is_participant(self):
return Participant.objects.filter(user=self).exists()

def is_applied_in_current_grade(self):
current_date = date.today()
current_grade = Grade.objects.filter(
start_date__lte=current_date, end_date__gte=current_date
).first()

return GradeApplication.objects.filter(
grade=current_grade, participant=self.participant_profile
).exists()


@receiver(user_activated)
def create_grade_application(sender, user: User, **kwargs):
Expand Down Expand Up @@ -200,6 +210,9 @@ class GradeSeries(models.Model):
null=False,
db_index=True,
)
expected_publish_date = models.DateField(
verbose_name="Předpokládané datum zvěřejnění zadání", null=True, blank=True
)
submission_deadline = models.DateTimeField(
verbose_name="Deadline pro odeslání řešení", null=False
)
Expand Down Expand Up @@ -232,6 +245,9 @@ def get_absolute_url(self):
"core:series_detail", kwargs={"pk": self.pk, "grade_id": self.grade_id}
)

def is_expected_publish_date_passed(self):
return self.expected_publish_date and self.expected_publish_date < datetime.now().date()

@property
def accepts_solution_submissions(self):
return self.task_file is not None and self.submission_deadline > datetime.now(
Expand Down Expand Up @@ -441,11 +457,16 @@ class Participant(models.Model):
("sk", "Slovensko"),
)
GRADE_CHOICES = (
("4", "4."),
("3", "3."),
("2", "2."),
("1", "1."),
("l", "nižší"),
("5", "absolvent"),
("4", "SŠ, 4."),
("3", "SŠ, 3."),
("2", "SŠ, 2."),
("1", "SŠ, 1."),
("0", "ZŠ, 9."),
("-1", "ZŠ, 8."),
("-2", "ZŠ, 7."),
("-3", "ZŠ, 6."),
# ("l", "nižší"),
)

user = models.OneToOneField(
Expand Down Expand Up @@ -481,7 +502,7 @@ class Participant(models.Model):
)
school_year = models.CharField(
verbose_name="Ročník",
max_length=1,
max_length=5,
null=False,
choices=GRADE_CHOICES,
)
Expand Down Expand Up @@ -531,14 +552,18 @@ def __str__(self):
def get_full_name(self):
return f"{self.user.get_full_name() or self.user.email}"


class GradeApplication(models.Model):
GRADE_CHOICES = (
("4", "4."),
("3", "3."),
("2", "2."),
("1", "1."),
("l", "nižší"),
("5", "absolvent"),
("4", "SŠ, 4."),
("3", "SŠ, 3."),
("2", "SŠ, 2."),
("1", "SŠ, 1."),
("0", "ZŠ, 9."),
("-1", "ZŠ, 8."),
("-2", "ZŠ, 7."),
("-3", "ZŠ, 6."),
#("l", "nižší"),
)

grade = models.ForeignKey(
Expand Down
30 changes: 28 additions & 2 deletions ksicht/core/templates/core/current_grade.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,18 @@
{% if can_apply %}
<div class="notification">
<p class="title is-4">Do tohoto ročníku se ještě můžeš přihlásit!</p>
<p class="is-size-6 mb-4">Před přihlášením si prosím zkontrolujte správnost údajů na <a href="{% url 'edit_profile' %}">svém profilu</a>.</p>
<article class="message is-info">
<div class="message-body">
Před přihlášením si, prosím, zkontrolujte správnost údajů na <a href="{% url 'edit_profile' %}">svém profilu</a>.
</div>
</article>
{% if not has_birth_date %}
<article class="message is-danger">
<div class="message-body">
Pro účast je nově potřeba mít vyplněné datum narození!
</div>
</article>
{% endif %}
{% crispy application_form %}
</div>
{% endif %}
Expand Down Expand Up @@ -64,8 +75,23 @@ <h2 class="subsubtitle">Errata</h2>
<div class="card series-card {% if series == current_series and series.task_file %}is-current{% endif %}">
<div class="card-content">
<h2 class="is-6 is-uppercase has-text-weight-bold">{{ series }}</h2>
<div class="{% if series not in future_series %}subtitle{% endif %} is-6 has-text-grey">odevzdání do {{ series.submission_deadline | date:"d.m." }}</div>
{% if series in future_series %}
<div class="{% if series not in future_series %}subtitle{% endif %} is-6 has-text-grey mb-4">
<p>
zveřejnění:
{% if series.expected_publish_date %}
{{ series.expected_publish_date | date:"d.m." }}
{% else %}
datum není známo
{% endif %}
</p>
<p class="subtitle is-7 has-text-grey">datum je pouze orientační</p>
</div>
{% endif %}

<div class="{% if series not in future_series %}subtitle{% endif %} is-6 has-text-grey">
odevzdání do {{ series.submission_deadline | date:"d.m." }}
</div>
{% if series in future_series %}
<p class="subtitle is-7 has-text-grey">datum je pouze orientační</p>
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion ksicht/core/templates/core/grade_archive.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{% if object_list %}
<div class="columns is-desktop is-multiline">
{% for grade in object_list %}
<div class="column is-one-quarter-fullhd is-half-tablet">
<div class="column is-one-third-fullhd is-half-tablet">
<div class="card">
<div class="card-header">
<div class="p-4">
Expand Down
2 changes: 1 addition & 1 deletion ksicht/core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"series__attachments"
),
template_name="core/grade_archive.html",
paginate_by=10,
paginate_by=6,
),
name="grade_archive",
),
Expand Down
2 changes: 1 addition & 1 deletion ksicht/core/views/envelopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
class SeriesTaskEnvelopesPrintout(View):
def get(self, request, *args, **kwargs):
response = HttpResponse(content_type="application/pdf")
filename = quote("Obálky pro školy")
filename = quote("obalky_pro_skoly")
response["Content-Disposition"] = f"attachment; filename*=UTF-8''{filename}.pdf"

def _build_lines(s):
Expand Down
7 changes: 6 additions & 1 deletion ksicht/core/views/grade.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ def get_context_data(self, **kwargs):
and self.object.participants.filter(user=self.request.user).exists()
)
data["can_apply"] = data["is_participant"] and not data["is_grade_participant"]
data["application_form"] = forms.CurrentGradeAppliationForm()
data["has_birth_date"] = (
hasattr(self.request.user, "participant_profile")
and self.request.user.participant_profile.birth_date is not None
)

data["application_form"] = forms.CurrentGradeAppliationForm(has_birth_date=data["has_birth_date"])
return data


Expand Down
15 changes: 11 additions & 4 deletions ksicht/forms.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import logging

from cuser.forms import AuthenticationForm, UserChangeForm, UserCreationForm
from django import forms
from django.contrib.auth.forms import (
Expand All @@ -12,7 +14,7 @@
from webpack_loader.templatetags.webpack_loader import webpack_static

from .core import constants
from .core.models import Grade, Participant, User
from .core.models import Grade, Participant, User, GradeManager, GradeApplication
from .core.form_utils import (
FormHelper,
Field,
Expand Down Expand Up @@ -45,12 +47,12 @@ def __init__(self, *args, **kwargs):
required=False,
empty_value="+420",
initial="+420",
help_text="Telefon ve formátu +420 777 123123.",
help_text="Telefon ve formátu +420 777 123 123.",
)
self.fields["birth_date"] = forms.DateField(
label="Datum narození",
required=False,
help_text="Datum narození ve formátu 1. 1. 1980.",
required=True,
help_text="Datum narození ve formátu 31.12.2000.",
localize=True,
)
self.fields["street"] = forms.CharField(
Expand Down Expand Up @@ -243,6 +245,7 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

self.fields["email"].disabled = True
self.fields["school_year"].disabled = True

self.helper = FormHelper()
self.helper.layout = Layout(
Expand Down Expand Up @@ -279,6 +282,10 @@ def save(self, commit=True):
user = super().save(commit)
cd = self.cleaned_data


logger = logging.getLogger(__name__)
logger.error(user.is_applied_in_current_grade())

user.save()

if user.is_participant():
Expand Down
4 changes: 3 additions & 1 deletion ksicht/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import dsnparse


ADMINS = (("Filip Varecha", "filip@varecha.work"),)
ADMINS = (("Filip Varecha", "filip@varecha.work"),("KSICHT org","ksicht.org@gmail.com"))


# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
Expand Down Expand Up @@ -60,6 +60,8 @@
# Application definition

INSTALLED_APPS = [
"imagefield",
"cabinet",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
Expand Down
24 changes: 22 additions & 2 deletions ksicht/templates/registration/user_change_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,29 @@
{% block headline %}{% block page_title %}Můj profil{% endblock %}{% endblock %}

{% block container %}
{% crispy form %}
<article class="message is-info">
<div class="message-header">
<p>Upozornění</p>
<button class="delete" aria-label="delete"></button>
</div>
<div class="message-body">
Školní ročník se nově zvýší o jednu úroveň automaticky při zahájení dalšího ročníku KSICHTu.
Pokud dojde k situaci, kdy ročník zde v profilu neodpovídá realitě, pošli nám email na <a
href="mailto:ksicht@natur.cuni.cz">ksicht@natur.cuni.cz</a>.
</div>
</article>

{% if no_birth_date %}
<article class="message is-warning">
<div class="message-body">
Pro účast v KSICHTu je nově potřeba mít vyplněné datum narození.
</div>
</article>
{% endif %}

{% crispy form %}
{% endblock %}

{% block after_body %}
<script src="{% webpack_static "js/user-form.js" %}"></script>
<script src="{% webpack_static "js/user-form.js" %}"></script>
{% endblock %}
6 changes: 6 additions & 0 deletions ksicht/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ def form_valid(self, form):
)
return super().form_valid(form)

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)

context["no_birth_date"] = self.object.participant_profile.birth_date is None
return context


def permission_protected_flatpage(request, url):
"""
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/ksicht/ksicht.git"
"url": "git+https://github.com/ksicht-org/ksicht.git"
},
"keywords": [],
"author": "Filip Vařecha",
"license": "ISC",
"bugs": {
"url": "https://github.com/ksicht/ksicht.cz/issues"
"url": "https://github.com/ksicht-org/ksicht/issues"
},
"homepage": "https://github.com/ksicht/ksicht.cz/#readme"
"homepage": "https://github.com/ksicht-org/ksicht/#readme"
}
1 change: 1 addition & 0 deletions requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ pilkit==3.0
# Fix for https://stackoverflow.com/questions/73929564/entrypoints-object-has-no-attribute-get-digital-ocean
# markdownx installs old version of markdown which breaks the app
Markdown==3.8.2
django-cabinet==0.17
Loading