Skip to content
Snippets Groups Projects
Commit f6e39dd3 authored by Tomáš Valenta's avatar Tomáš Valenta
Browse files

lecture view, mobile UI, DB settings

parent 361767e0
Branches
No related tags found
No related merge requests found
Pipeline #12768 passed
Showing
with 480 additions and 105 deletions
......@@ -23,7 +23,7 @@ class LectureGroupAdmin(MarkdownxGuardedModelAdmin):
search_fields = ("name",)
class LectureLectorInline(admin.TabularInline):
class LectureLectorInline(admin.StackedInline):
model = LectureLector
extra = 1
......
# Generated by Django 4.1.4 on 2023-04-18 07:33
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lectures', '0001_initial'),
("lectures", "0001_initial"),
]
operations = [
migrations.CreateModel(
name='LectureMaterial',
name="LectureMaterial",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128, verbose_name='Název')),
('link', models.URLField(blank=True, max_length=256, null=True, verbose_name='Odkaz')),
('file', models.FileField(blank=True, null=True, upload_to='', verbose_name='Soubor')),
('lecture', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='lectures.lecture', verbose_name='Událost')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=128, verbose_name="Název")),
(
"link",
models.URLField(
blank=True, max_length=256, null=True, verbose_name="Odkaz"
),
),
(
"file",
models.FileField(
blank=True, null=True, upload_to="", verbose_name="Soubor"
),
),
(
"lecture",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="materials",
to="lectures.lecture",
verbose_name="Událost",
),
),
],
options={
'verbose_name': 'Materiál',
'verbose_name_plural': 'Materiály',
"verbose_name": "Materiál",
"verbose_name_plural": "Materiály",
},
),
migrations.RenameField(
model_name='lecturelector',
old_name='event',
new_name='lecture',
model_name="lecturelector",
old_name="event",
new_name="lecture",
),
migrations.RenameField(
model_name='lecturerecording',
old_name='event',
new_name='lecture',
model_name="lecturerecording",
old_name="event",
new_name="lecture",
),
migrations.DeleteModel(
name='Material',
name="Material",
),
]
......@@ -4,20 +4,34 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lectures', '0002_lecturematerial_rename_event_lecturelector_lecture_and_more'),
(
"lectures",
"0002_lecturematerial_rename_event_lecturelector_lecture_and_more",
),
]
operations = [
migrations.AlterField(
model_name='lecturematerial',
name='file',
field=models.FileField(blank=True, help_text='Zadej prosím pouze odkaz, nebo soubor.', null=True, upload_to='', verbose_name='Soubor'),
model_name="lecturematerial",
name="file",
field=models.FileField(
blank=True,
help_text="Zadej prosím pouze odkaz, nebo soubor.",
null=True,
upload_to="",
verbose_name="Soubor",
),
),
migrations.AlterField(
model_name='lecturematerial',
name='link',
field=models.URLField(blank=True, help_text='Zadej prosím pouze odkaz, nebo soubor.', max_length=256, null=True, verbose_name='Odkaz'),
model_name="lecturematerial",
name="link",
field=models.URLField(
blank=True,
help_text="Zadej prosím pouze odkaz, nebo soubor.",
max_length=256,
null=True,
verbose_name="Odkaz",
),
),
]
......@@ -4,20 +4,31 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lectures', '0003_alter_lecturematerial_file_and_more'),
("lectures", "0003_alter_lecturematerial_file_and_more"),
]
operations = [
migrations.AlterField(
model_name='lecturematerial',
name='file',
field=models.FileField(blank=True, help_text='Pokud máš vložený soubor, nemůžeš definovat odkaz.', null=True, upload_to='', verbose_name='Soubor'),
model_name="lecturematerial",
name="file",
field=models.FileField(
blank=True,
help_text="Pokud máš vložený soubor, nemůžeš definovat odkaz.",
null=True,
upload_to="",
verbose_name="Soubor",
),
),
migrations.AlterField(
model_name='lecturematerial',
name='link',
field=models.URLField(blank=True, help_text='Pokud máš zadaný odkaz, nemůžeš definovat soubor.', max_length=256, null=True, verbose_name='Odkaz'),
model_name="lecturematerial",
name="link",
field=models.URLField(
blank=True,
help_text="Pokud máš zadaný odkaz, nemůžeš definovat soubor.",
max_length=256,
null=True,
verbose_name="Odkaz",
),
),
]
......@@ -4,24 +4,44 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('lectures', '0004_alter_lecturematerial_file_and_more'),
("auth", "0012_alter_user_first_name_max_length"),
("lectures", "0004_alter_lecturematerial_file_and_more"),
]
operations = [
migrations.CreateModel(
name='LectureGroup',
name="LectureGroup",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128, verbose_name='Jméno')),
('lectures', models.ManyToManyField(blank=True, related_name='groups', to='lectures.lecture', verbose_name='Lekce')),
('user_groups', models.ManyToManyField(to='auth.group', verbose_name='Uživatelské skupiny')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=128, verbose_name="Jméno")),
(
"lectures",
models.ManyToManyField(
blank=True,
related_name="groups",
to="lectures.lecture",
verbose_name="Lekce",
),
),
(
"user_groups",
models.ManyToManyField(
to="auth.group", verbose_name="Uživatelské skupiny"
),
),
],
options={
'verbose_name': 'Skupina',
'verbose_name_plural': 'Skupiny',
"verbose_name": "Skupina",
"verbose_name_plural": "Skupiny",
},
),
]
# Generated by Django 4.1.4 on 2023-04-18 10:12
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('lectures', '0005_lecturegroup'),
("auth", "0012_alter_user_first_name_max_length"),
("lectures", "0005_lecturegroup"),
]
operations = [
migrations.AlterModelOptions(
name='lecturegroup',
options={'verbose_name': 'Výuková skupina', 'verbose_name_plural': 'Výukové skupiny'},
name="lecturegroup",
options={
"verbose_name": "Výuková skupina",
"verbose_name_plural": "Výukové skupiny",
},
),
migrations.AlterField(
model_name='lecturegroup',
name='user_groups',
field=models.ManyToManyField(blank=True, help_text='Pokud nedefinuješ žádné, lekce ve skupině jsou dostupné všem.', to='auth.group', verbose_name='Uživatelské skupiny'),
model_name="lecturegroup",
name="user_groups",
field=models.ManyToManyField(
blank=True,
help_text="Pokud nedefinuješ žádné, lekce ve skupině jsou dostupné všem.",
to="auth.group",
verbose_name="Uživatelské skupiny",
),
),
migrations.AlterField(
model_name='lecturelector',
name='lecture',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lectors', to='lectures.lecture', verbose_name='Lekce'),
model_name="lecturelector",
name="lecture",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="lectors",
to="lectures.lecture",
verbose_name="Lekce",
),
),
migrations.AlterField(
model_name='lecturematerial',
name='lecture',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='lectures.lecture', verbose_name='Lekce'),
model_name="lecturematerial",
name="lecture",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="materials",
to="lectures.lecture",
verbose_name="Lekce",
),
),
migrations.AlterField(
model_name='lecturerecording',
name='lecture',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recordings', to='lectures.lecture', verbose_name='Lekce'),
model_name="lecturerecording",
name="lecture",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="recordings",
to="lectures.lecture",
verbose_name="Lekce",
),
),
]
......@@ -4,14 +4,17 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('lectures', '0006_alter_lecturegroup_options_and_more'),
("lectures", "0006_alter_lecturegroup_options_and_more"),
]
operations = [
migrations.AlterModelOptions(
name='lecture',
options={'ordering': ('-timestamp',), 'verbose_name': 'Lekce', 'verbose_name_plural': 'Lekce'},
name="lecture",
options={
"ordering": ("-timestamp",),
"verbose_name": "Lekce",
"verbose_name_plural": "Lekce",
},
),
]
......@@ -4,14 +4,17 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('lectures', '0007_alter_lecture_options'),
("lectures", "0007_alter_lecture_options"),
]
operations = [
migrations.AlterModelOptions(
name='lecture',
options={'ordering': ('-timestamp', '-name'), 'verbose_name': 'Lekce', 'verbose_name_plural': 'Lekce'},
name="lecture",
options={
"ordering": ("-timestamp", "-name"),
"verbose_name": "Lekce",
"verbose_name_plural": "Lekce",
},
),
]
......@@ -4,19 +4,23 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lectures', '0008_alter_lecture_options'),
("lectures", "0008_alter_lecture_options"),
]
operations = [
migrations.RemoveField(
model_name='lecturegroup',
name='lectures',
model_name="lecturegroup",
name="lectures",
),
migrations.AddField(
model_name='lecture',
name='groups',
field=models.ManyToManyField(blank=True, related_name='lectures', to='lectures.lecturegroup', verbose_name='Výukové skupiny'),
model_name="lecture",
name="groups",
field=models.ManyToManyField(
blank=True,
related_name="lectures",
to="lectures.lecturegroup",
verbose_name="Výukové skupiny",
),
),
]
......@@ -4,14 +4,17 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('lectures', '0009_remove_lecturegroup_lectures_lecture_groups'),
("lectures", "0009_remove_lecturegroup_lectures_lecture_groups"),
]
operations = [
migrations.AlterModelOptions(
name='lecturegroup',
options={'ordering': ('name',), 'verbose_name': 'Výuková skupina', 'verbose_name_plural': 'Výukové skupiny'},
name="lecturegroup",
options={
"ordering": ("name",),
"verbose_name": "Výuková skupina",
"verbose_name_plural": "Výukové skupiny",
},
),
]
# Generated by Django 4.1.4 on 2023-04-19 08:20
from django.db import migrations
import markdownx.models
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('lectures', '0010_alter_lecturegroup_options'),
("lectures", "0010_alter_lecturegroup_options"),
]
operations = [
migrations.AddField(
model_name='lecturegroup',
name='description',
field=markdownx.models.MarkdownxField(blank=True, help_text='Můžeš použít Markdown.', null=True, verbose_name='Popis'),
model_name="lecturegroup",
name="description",
field=markdownx.models.MarkdownxField(
blank=True,
help_text="Můžeš použít Markdown.",
null=True,
verbose_name="Popis",
),
),
migrations.AlterField(
model_name='lecture',
name='description',
field=markdownx.models.MarkdownxField(blank=True, help_text='Můžeš použít Markdown.', null=True, verbose_name='Popis'),
model_name="lecture",
name="description",
field=markdownx.models.MarkdownxField(
blank=True,
help_text="Můžeš použít Markdown.",
null=True,
verbose_name="Popis",
),
),
]
# Generated by Django 4.1.4 on 2023-05-08 09:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("lectures", "0011_lecturegroup_description_alter_lecture_description"),
]
operations = [
migrations.AddField(
model_name="lecturelector",
name="username",
field=models.CharField(
blank=True,
help_text="Např. na fóru, nebo v Chobotnici.",
max_length=128,
null=True,
verbose_name="Uživatelské jméno",
),
),
migrations.AlterField(
model_name="lecture",
name="type",
field=models.CharField(
choices=[
("recommended", "Doporučená lekce"),
("optional", "Volitelná lekce"),
],
max_length=11,
verbose_name="Typ",
),
),
]
# Generated by Django 4.1.4 on 2023-05-08 10:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("lectures", "0012_lecturelector_username_alter_lecture_type"),
]
operations = [
migrations.RenameField(
model_name="lecturelector",
old_name="link",
new_name="url",
),
]
# Generated by Django 4.1.4 on 2023-05-08 12:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("lectures", "0013_rename_link_lecturelector_url"),
]
operations = [
migrations.AlterModelOptions(
name="lecture",
options={
"ordering": ("-timestamp", "-name"),
"permissions": [
("can_edit_lecture_settings", "Can edit Lekce settings")
],
"verbose_name": "Lekce",
"verbose_name_plural": "Lekce",
},
),
migrations.AlterField(
model_name="lecturelector",
name="username",
field=models.CharField(
blank=True,
help_text="Např. na fóru, nebo v Chobotnici. Užívá se k synchronizaci profilového obrázku.",
max_length=128,
null=True,
verbose_name="Uživatelské jméno",
),
),
]
......@@ -8,6 +8,8 @@ from markdownx.models import MarkdownxField
from shared.models import NameStrMixin
from . import settings as app_settings
# Create your models here.
......@@ -47,8 +49,8 @@ class Lecture(NameStrMixin, models.Model):
) # If undefined, assume this event was in the past
class TypeChoices(models.TextChoices):
RECOMMENDED = "recommended", "Doporučené"
OPTIONAL = "optional", "Volitelné"
RECOMMENDED = "recommended", "Doporučená lekce"
OPTIONAL = "optional", "Volitelná lekce"
groups = models.ManyToManyField(
LectureGroup,
......@@ -80,6 +82,10 @@ class Lecture(NameStrMixin, models.Model):
# On or after the current time, minus 8 hours
return self.timestamp >= (timezone.now() - self.is_current_treshold)
# Settings
settings = app_settings.LectureSettings("Nastavení")
class Meta:
verbose_name = "Lekce"
verbose_name_plural = verbose_name
......@@ -99,13 +105,24 @@ class LectureLector(NameStrMixin, models.Model):
verbose_name="Jméno",
)
link = models.URLField(
url = models.URLField(
max_length=256,
blank=True,
null=True,
verbose_name="Odkaz",
)
username = models.CharField(
max_length=128,
blank=True,
null=True,
verbose_name="Uživatelské jméno",
help_text=(
"Např. na fóru, nebo v Chobotnici. Užívá se "
"k synchronizaci profilového obrázku."
),
)
class Meta:
verbose_name = "Lektor"
verbose_name_plural = "Lektoři"
......
import dbsettings
from django import forms
class LectureSettings(dbsettings.Group):
motd = dbsettings.StringValue(
"Informace na indexové stránce",
help_text="Poporuje formátování skrze Markdown.",
widget=forms.Textarea,
)
......@@ -4,7 +4,10 @@
<a href="{% url "lectures:view_lecture" lecture.id %}" class="hover:no-underline">
<div class="card elevation-6">
<div class="card__body p-5 hover:bg-gray-100 duration-100">
<h2 class="head-alt-sm mb-4">{{ lecture.name }}</h2>
<h2 class="head-alt-sm mb-4">
<i class="ico--bookmark mr-2"></i>
{{ lecture.name }}
</h2>
<span class="flex gap-2 mb-4">
<span>
......
......@@ -2,7 +2,10 @@
{% load markdownify %}
{% block content %}
<h1 class="head-alt-md mb-10">{{ group.name }} - výuka</h1>
<h1 class="head-alt-md mb-10">
<i class="ico--users mr-3"></i>
{{ group.name }} - výuka
</h1>
{% if group.description %}
<div class="prose max-w-none mb-10">
{{ group.description|markdownify|safe }}
......@@ -38,7 +41,7 @@
<div>
<template v-if="isCurrentView('current_lectures')">
{% if current_lectures %}
<ul class="grid md:grid-cols-2 grid-cols-1 gap-4">
<ul class="grid grid-cols-1 md:grid-cols-2 gap-4">
{% for lecture in current_lectures %}
{% include "lectures/includes/lecture.html" with lecture=lecture %}
{% endfor %}
......@@ -54,7 +57,7 @@
</template>
<template v-if="isCurrentView('recordings')">
{% if past_lectures %}
<ul class="grid md:grid-cols-2 grid-cols-1 gap-4">
<ul class="grid grid-cols-1 md:grid-cols-2 gap-4">
{% for lecture in past_lectures %}
{% include "lectures/includes/lecture.html" with lecture=lecture %}
{% endfor %}
......
......@@ -3,18 +3,22 @@
{% block content %}
<div class="prose max-w-none mb-10">
<p>
Rerum in quibusdam repellendus repellat doloremque sit ad rerum. Aperiam aut architecto non repudiandae tenetur assumenda quidem alias. Adipisci omnis aut rem. <a href="#">Repellat et enim</a> et sed aperiam eligendi <i>accusamus</i>. Molestiae vel vitae sunt pariatur. Aut consectetur perspiciatis alias ut maxime.
</p>
{{ settings.motd|markdownify|safe }}
</div>
<h1 class="head-alt-md mb-10">Výukové skupiny</h1>
<ul class="grid grid-cols-2 gap-3">
<h1 class="head-alt-md mb-10">
<i class="ico--users mr-3"></i>
Výukové skupiny
</h1>
<ul class="grid grid-cols-1 md:grid-cols-2 gap-3">
{% for group in lecture_groups %}
<li>
<a href="{% url "lectures:view_lecture_index" group.id %}" class="hover:no-underline">
<a href="{% url "lectures:view_group_lectures" group.id %}" class="hover:no-underline">
<div class="card elevation-6">
<div class="card__body hover:bg-gray-100 duration-100">
<h2 class="head-alt-sm">{{ group.name }}</h2>
<h2 class="head-alt-sm">
<i class="ico--users mr-2"></i>
{{ group.name }}
</h2>
{% if group.description %}
<div class="prose max-w-none mt-4">
{{ group.description|markdownify|safe }}
......
{% extends "shared/includes/base.html" %}
{% load markdownify %}
{% block content %}
{% include "shared/includes/double_heading.html" with heading=lecture.name subheading=lecture.get_type_display icon="ico--bookmark" %}
<div class="flex flex-col gap-2 my-4 py-4 border-y border-gray-200">
<div class="flex justify-between gap-2 text-lg text-gray-600">
<div class="flex gap-2 items-center">
<i class="ico--clock"></i>
<span>Datum konání</span>
</div>
<div>
{{ lecture.timestamp }}
</div>
</div>
<div class="flex justify-between gap-2 text-lg text-gray-600">
<div class="flex gap-2 items-center">
<i class="ico--users"></i>
<span>Skupiny</span>
</div>
<ul class="flex gap-2">
{% for group in lecture.groups.all %}
<li>
<a
class="px-1.5 py-1 bg-gray-200 rounded-sm duration-150 hover:no-underline hover:bg-gray-300"
href="{% url "lectures:view_group_lectures" group.id %}"
>{{ group.name }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
{% if lecture.description %}
<div class="prose max-w-none mb-10">
{{ lecture.description|markdownify|safe }}
</div>
{% endif %}
<div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-5 md:gap-3">
<section>
{% with lecture.materials.all as materials %}
<h2 class="head-alt-sm mb-3">
<i class="ico--attachment mr-2"></i>{% comment %}t{% endcomment %}
Materiály
</h2>
{% if materials %}
<ul class="flex flex-col gap-2 my-3 py-3 border-y border-gray-200">
{% for material in materials %}
<li>
<i class="ico--{% if material.link %}link{% elif material.file %}folder-download{% endif %} mr-2"></i>
<a
{% if material.link %}
href="{{ material.link }}"
{% elif material.file %}
href="{{ material.file }}"
{% endif %}
class="text-lg"
>{{ material.name }}</a>
</li>
{% endfor %}
</ul>
{% else %}
<span class="text-gray-200">Žádné materiály.</span>
{% endif %}
{% endwith %}
</section>
<section>
{% with lecture.recordings.all as recordings %}
<h2 class="head-alt-sm mb-3">
<i class="ico--eye mr-2"></i>
Nahrávky
</h2>
{% if recordings %}
<ul class="flex flex-col gap-2 my-3 py-3 border-y border-gray-200">
{% for recording in recordings %}
<li>
<i class="ico--link mr-2 hover:no-underline"></i>
<a
href="{{ recording.link }}"
class="text-lg"
>{{ recording.name }}</a>
</li>
{% endfor %}
</ul>
{% else %}
<span class="text-gray-200">Žádné nahrávky.</span>
{% endif %}
{% endwith %}
</section>
</div>
{% with lecture.lectors.all as lectors %}
{% if lectors %}
<section class="mt-6 flex flex-col gap-4">
<h2 class="head-alt-sm">
<i class="ico--users mr-2"></i>
Lektoři
</h2>
<ul class="grid grid-cols-1 md:grid-cols-2 gap-2">
{% for lector in lectors %}
<li class="card elevation-3">
{% if lector.url %}
<a href="{{ lector.url }}"
{% else %}
<div
{% endif %}
class="hover:no-underline flex items-center gap-4 {% if lector.url %}duration-150 hover:bg-gray-100{% endif %} card__body"
>
<div class="avatar badge__avatar avatar--sm">
<img
src="https://a.pirati.cz/piratar/300/{% if lector.username %}{{ lector.username }}{% else %}default{% endif %}.webp"
alt="Profilový obrázek {{ lector.name }}"
>
</div>
<div class="flex flex-col gap-2">
<span class="head-heavy-2xs">
<div class="content-block--nostyle">
{{ lector.name }}
</div>
</span>
{% if lector.url %}
<div
class="block text-ellipsis overflow-hidden"
href="{{ lector.url }}"
>{{ lector.url }}</div>
{% endif %}
</div>
{% if lector.url %}
</a>
{% else %}
</div>
{% endif %}
</li>
{% endfor %}
</ul>
</section>
{% endif %}
{% endwith %}
{% endblock %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment