diff --git a/Palto/Palto/admin.py b/Palto/Palto/admin.py
index 388aed0..86277a2 100644
--- a/Palto/Palto/admin.py
+++ b/Palto/Palto/admin.py
@@ -61,9 +61,9 @@ class AdminAttendance(admin.ModelAdmin):
@admin.register(models.Absence)
class AdminAbsence(admin.ModelAdmin):
- list_display = ("id", "message", "student", "department", "start", "end")
- search_fields = ("id", "message", "student", "department", "start", "end")
- list_filter = ("department", "start", "end")
+ list_display = ("id", "message", "student", "start", "end")
+ search_fields = ("id", "message", "student", "start", "end")
+ list_filter = ("start", "end")
@admin.register(models.AbsenceAttachment)
diff --git a/Palto/Palto/migrations/0001_initial.py b/Palto/Palto/migrations/0001_initial.py
new file mode 100644
index 0000000..56a14d7
--- /dev/null
+++ b/Palto/Palto/migrations/0001_initial.py
@@ -0,0 +1,166 @@
+# Generated by Django 4.2.7 on 2023-12-10 11:31
+
+import Palto.Palto.models
+from django.conf import settings
+import django.contrib.auth.models
+import django.contrib.auth.validators
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+import uuid
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('auth', '0012_alter_user_first_name_max_length'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Absence',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('message', models.TextField()),
+ ('start', models.DateTimeField()),
+ ('end', models.DateTimeField()),
+ ],
+ bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
+ ),
+ migrations.CreateModel(
+ name='Department',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('name', models.CharField(max_length=64, unique=True)),
+ ('email', models.EmailField(max_length=254)),
+ ],
+ bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
+ ),
+ migrations.CreateModel(
+ name='StudentGroup',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('name', models.CharField(max_length=128)),
+ ('department', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student_groups', to='Palto.department')),
+ ],
+ bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
+ ),
+ migrations.CreateModel(
+ name='User',
+ fields=[
+ ('password', models.CharField(max_length=128, verbose_name='password')),
+ ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
+ ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
+ ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
+ ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
+ ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
+ ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
+ ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
+ ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
+ ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
+ ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
+ ],
+ options={
+ 'verbose_name': 'user',
+ 'verbose_name_plural': 'users',
+ 'abstract': False,
+ },
+ bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
+ managers=[
+ ('objects', django.contrib.auth.models.UserManager()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='TeachingUnit',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('name', models.CharField(max_length=64)),
+ ('department', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teaching_units', to='Palto.department')),
+ ('managers', models.ManyToManyField(blank=True, related_name='managing_units', to=settings.AUTH_USER_MODEL)),
+ ('student_groups', models.ManyToManyField(blank=True, related_name='studying_units', to='Palto.studentgroup')),
+ ('teachers', models.ManyToManyField(blank=True, related_name='teaching_units', to=settings.AUTH_USER_MODEL)),
+ ],
+ bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
+ ),
+ migrations.CreateModel(
+ name='TeachingSession',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('start', models.DateTimeField()),
+ ('duration', models.DurationField()),
+ ('note', models.TextField(blank=True)),
+ ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teaching_sessions', to='Palto.studentgroup')),
+ ('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teaching_sessions', to=settings.AUTH_USER_MODEL)),
+ ('unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sessions', to='Palto.teachingunit')),
+ ],
+ bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
+ ),
+ migrations.AddField(
+ model_name='studentgroup',
+ name='owner',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owning_groups', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='studentgroup',
+ name='students',
+ field=models.ManyToManyField(blank=True, related_name='student_groups', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.CreateModel(
+ name='StudentCard',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('uid', models.BinaryField(max_length=7)),
+ ('department', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student_cards', to='Palto.department')),
+ ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student_cards', to=settings.AUTH_USER_MODEL)),
+ ],
+ bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
+ ),
+ migrations.AddField(
+ model_name='department',
+ name='managers',
+ field=models.ManyToManyField(blank=True, related_name='managing_departments', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='department',
+ name='students',
+ field=models.ManyToManyField(blank=True, related_name='studying_departments', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='department',
+ name='teachers',
+ field=models.ManyToManyField(blank=True, related_name='teaching_departments', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.CreateModel(
+ name='Attendance',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('date', models.DateTimeField()),
+ ('session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attendances', to='Palto.teachingsession')),
+ ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attended_sessions', to=settings.AUTH_USER_MODEL)),
+ ],
+ bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
+ ),
+ migrations.CreateModel(
+ name='AbsenceAttachment',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('content', models.FileField(upload_to='absence/attachment/')),
+ ('absence', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='Palto.absence')),
+ ],
+ bases=(models.Model, Palto.Palto.models.ModelPermissionHelper),
+ ),
+ migrations.AddField(
+ model_name='absence',
+ name='department',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='absences', to='Palto.department'),
+ ),
+ migrations.AddField(
+ model_name='absence',
+ name='student',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='absences', to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/Palto/Palto/models.py b/Palto/Palto/models.py
index ac7f3d2..049e80b 100644
--- a/Palto/Palto/models.py
+++ b/Palto/Palto/models.py
@@ -63,6 +63,9 @@ class User(AbstractUser, ModelPermissionHelper):
def __repr__(self):
return f"<{self.__class__.__name__} id={str(self.id)[:8]} username={self.username!r}>"
+ def __str__(self):
+ return f"{self.first_name} {self.last_name.upper()}"
+
@staticmethod
def multiple_related_departments(users: Iterable["User"]) -> QuerySet["Department"]:
"""
diff --git a/Palto/Palto/templates/Palto/homepage.html b/Palto/Palto/templates/Palto/homepage.html
new file mode 100644
index 0000000..bade8c3
--- /dev/null
+++ b/Palto/Palto/templates/Palto/homepage.html
@@ -0,0 +1,5 @@
+{% extends "Palto/base.html" %}
+
+{% block body %}
+ Hello there.
+{% endblock %}
diff --git a/Palto/Palto/templates/Palto/navigation.html b/Palto/Palto/templates/Palto/navigation.html
index bb4c86f..074a3bf 100644
--- a/Palto/Palto/templates/Palto/navigation.html
+++ b/Palto/Palto/templates/Palto/navigation.html
@@ -1,3 +1,11 @@
+{% load static %}
+
diff --git a/Palto/Palto/templates/Palto/teaching_session.html b/Palto/Palto/templates/Palto/teaching_session.html
new file mode 100644
index 0000000..5a6c99c
--- /dev/null
+++ b/Palto/Palto/templates/Palto/teaching_session.html
@@ -0,0 +1,27 @@
+{% extends "Palto/base.html" %}
+
+{% block body %}
+ {# table of all the sessions #}
+
+
+
+ Identifiant |
+ Début |
+ Durée |
+ Unité d'Enseignement |
+ Enseignant |
+ Groupe |
+
+
+
+
+ {{ session.id }} |
+ {{ session.start }} |
+ {{ session.duration }} |
+ {{ session.unit }} |
+ {{ session.teacher }} |
+ {{ session.group }} |
+
+
+
+{% endblock %}
diff --git a/Palto/Palto/templates/Palto/teaching_session_list.html b/Palto/Palto/templates/Palto/teaching_session_list.html
new file mode 100644
index 0000000..f9ecc3e
--- /dev/null
+++ b/Palto/Palto/templates/Palto/teaching_session_list.html
@@ -0,0 +1,36 @@
+{% extends "Palto/base.html" %}
+
+{% block body %}
+ {# table of all the sessions #}
+
+
+
+ Identifiant |
+ Début |
+ Durée |
+
+
+
+ {% for session in sessions %}
+
+ {{ session.id }} |
+ {{ session.start }} |
+ {{ session.duration }} |
+
+ {% endfor %}
+
+
+
+ {# page navigator #}
+
+{% endblock %}
diff --git a/Palto/Palto/urls.py b/Palto/Palto/urls.py
index 19c0b30..357120f 100644
--- a/Palto/Palto/urls.py
+++ b/Palto/Palto/urls.py
@@ -16,6 +16,8 @@ urlpatterns = [
# User
path("login/", views.login_view, name="login"),
path("logout/", views.logout_view, name="logout"),
- path("profile/", views.profile_view, name="profile"),
+ path("profile/", views.profile_view, name="my_profile"),
path("profile//", views.profile_view, name="profile"),
+ path("teaching_sessions/", views.teaching_session_list_view, name="teaching_session_list"),
+ path("teaching_sessions//", views.teaching_session_view, name="teaching_session"),
]
diff --git a/Palto/Palto/views.py b/Palto/Palto/views.py
index 535aabc..b9ac81f 100644
--- a/Palto/Palto/views.py
+++ b/Palto/Palto/views.py
@@ -6,20 +6,24 @@ A view is what control the content of a page, prepare the correct data, react to
import uuid
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
-from django.http import HttpRequest, HttpResponse
+from django.core.handlers.wsgi import WSGIRequest
+from django.core.paginator import Paginator
+from django.http import HttpResponseForbidden
from django.shortcuts import render, get_object_or_404, redirect
+from Palto.Palto import models
from Palto.Palto.forms import LoginForm
-from Palto.Palto.models import User
+
+
+ELEMENT_PER_PAGE: int = 30
# Create your views here.
-def homepage_view(request: HttpRequest):
- # TODO: homepage
- return HttpResponse("Hello there.")
+def homepage_view(request: WSGIRequest):
+ return render(request, "Palto/homepage.html")
-def login_view(request: HttpRequest):
+def login_view(request: WSGIRequest):
# create a login form
form_login = LoginForm(request.POST)
@@ -51,7 +55,7 @@ def login_view(request: HttpRequest):
@login_required
-def logout_view(request: HttpRequest):
+def logout_view(request: WSGIRequest):
# disconnect the user from the website
logout(request)
# redirect him to the main page
@@ -59,13 +63,13 @@ def logout_view(request: HttpRequest):
@login_required
-def profile_view(request: HttpRequest, profile_id: uuid.UUID = None):
+def profile_view(request: WSGIRequest, profile_id: uuid.UUID = None):
if profile_id is None:
# if the profile id is not given, redirect to the page of the current user.
return redirect("Palto:profile", request.user.id)
# get the corresponding user from its id.
- profile = get_object_or_404(User, id=profile_id)
+ profile = get_object_or_404(models.User, id=profile_id)
# render the page
return render(
@@ -75,3 +79,42 @@ def profile_view(request: HttpRequest, profile_id: uuid.UUID = None):
profile=profile
)
)
+
+
+@login_required
+def teaching_session_list_view(request: WSGIRequest):
+ # get all the sessions that the user can see, sorted by starting date
+ raw_sessions = models.TeachingSession.all_visible_by_user(request.user).order_by("start")
+ # paginate them to avoid having too many elements at the same time
+ paginator = Paginator(raw_sessions, ELEMENT_PER_PAGE)
+
+ # get only the session for the requested page
+ page = request.GET.get("page", 0)
+ sessions = paginator.get_page(page)
+
+ # render the page
+ return render(
+ request,
+ "Palto/teaching_session_list.html",
+ context=dict(
+ sessions=sessions
+ )
+ )
+
+
+@login_required
+def teaching_session_view(request: WSGIRequest, session_id: uuid.UUID):
+ session = get_object_or_404(models.TeachingSession, id=session_id)
+
+ if session not in models.TeachingSession.all_visible_by_user(request.user):
+ # TODO: syntaxic sugar session.visible_by_user(request.user)
+ return HttpResponseForbidden()
+
+ # render the page
+ return render(
+ request,
+ "Palto/teaching_session.html",
+ context=dict(
+ session=session
+ )
+ )
\ No newline at end of file