diff --git a/colloscope/admin.py b/colloscope/admin.py index d0e2529..7040222 100644 --- a/colloscope/admin.py +++ b/colloscope/admin.py @@ -13,4 +13,4 @@ admin.site.register(Colleur) admin.site.register(Creneau) admin.site.register(Rotation) admin.site.register(Amendement) -admin.site.register(Utilisateur) +admin.site.register(Profil) diff --git a/colloscope/migrations/0007_profil_delete_utilisateur.py b/colloscope/migrations/0007_profil_delete_utilisateur.py new file mode 100644 index 0000000..e1feeeb --- /dev/null +++ b/colloscope/migrations/0007_profil_delete_utilisateur.py @@ -0,0 +1,28 @@ +# Generated by Django 5.0.4 on 2024-04-19 17:07 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('colloscope', '0006_remove_rotation_semaine_rotation_date'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Profil', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('colleur', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='colloscope.colleur')), + ('etudiant', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='colloscope.etudiant')), + ('utilisateur', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, unique=True)), + ], + ), + migrations.DeleteModel( + name='Utilisateur', + ), + ] diff --git a/colloscope/models.py b/colloscope/models.py index 9df10fd..5e25cc4 100644 --- a/colloscope/models.py +++ b/colloscope/models.py @@ -2,6 +2,8 @@ from datetime import date, datetime, timedelta from django.db import models from django.db.models import F, Q +from django.contrib.auth.models import User + calendrier = { "C" : [ @@ -123,6 +125,10 @@ class Periode(models.Model): """ return range(self.classe.no_semaine(self.debut), self.classe.no_semaine(self.fin)+1) + def query_rotations(self): + return Rotation.objects.filter(creneau__periode=self) + + def __str__(self): return self.libelle @@ -318,9 +324,10 @@ class Amendement(models.Model): etudiant = models.ForeignKey(Etudiant, on_delete=models.CASCADE) -class Utilisateur(models.Model): - username = models.CharField(max_length=100) - password = models.CharField(max_length=300) - timestamp = models.DateTimeField(auto_now_add=True) - etudiant = models.ForeignKey(Etudiant, on_delete=models.SET_NULL, null=True) - colleur = models.ForeignKey(Colleur, on_delete=models.SET_NULL, null=True) +class Profil(models.Model): + utilisateur = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True) + etudiant = models.ForeignKey(Etudiant, null=True, on_delete=models.SET_NULL) + colleur = models.ForeignKey(Colleur, null=True, on_delete=models.SET_NULL) + + def __str__(self): + return f"Profil {self.utilisateur} : {self.etudiant} ; {self.colleur}" diff --git a/colloscope/pdfexport.py b/colloscope/pdfexport.py index 1157dbb..cf2f62b 100644 --- a/colloscope/pdfexport.py +++ b/colloscope/pdfexport.py @@ -106,8 +106,6 @@ def generate(periode): pdf.y += 3 pdf.table_colloscope(periode, heading=False, est_colle=False) - pdf.output("test.pdf") - return pdf def main(): diff --git a/colloscope/templates/base.html b/colloscope/templates/base.html deleted file mode 100644 index c93282b..0000000 --- a/colloscope/templates/base.html +++ /dev/null @@ -1,26 +0,0 @@ -{% load static %} - - - - - - {% block title %}{% endblock title %} - - {% block head %}{% endblock head %} - - -
- {% if request.session.overseer is not None %} -
- Vous voyez ce site en tant que... Désactiver -
- {% endif %} - {% block header %}{% endblock header %} -
-
- {% block main %}{% endblock main %} -
- - diff --git a/colloscope/templates/choix_profil.html b/colloscope/templates/choix_profil.html index 12b734b..c4bdfa2 100644 --- a/colloscope/templates/choix_profil.html +++ b/colloscope/templates/choix_profil.html @@ -8,18 +8,10 @@ {% block main %} -{% if user.etudiant is not None and user.colleur is not None %} Vous êtes connecté. Votre compte correspond à deux profils : -{% elif user.colleur is not None and user.etudiant is None %} -Connection en tant que {{ user.colleur }}... classes : {{ user.colleur.get_classes }} -{% elif user.etudiant is not None and user.colleur is None %} -Connection en tant que {{ user.etudiant }} : classe {{ user.etudiant.classe }} -{% else %} -Vous êtes connecté, mais votre compte n'est associé à aucun profil. Veuillez contacter le webmestre à l'adresse valentin@mp2i-vms.fr. -{% endif %} {% endblock main %} diff --git a/colloscope/templates/colloscope.html b/colloscope/templates/colloscope.html index 72696b2..5ff4976 100644 --- a/colloscope/templates/colloscope.html +++ b/colloscope/templates/colloscope.html @@ -22,6 +22,7 @@

Colloscope : {{ periode.libelle }}

+
@@ -78,6 +79,7 @@ {% endfor %}
+

Par groupes

diff --git a/colloscope/templates/profil_non_associe.html b/colloscope/templates/profil_non_associe.html new file mode 100644 index 0000000..cb6cc4f --- /dev/null +++ b/colloscope/templates/profil_non_associe.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} + +{% block title %}Sélection du profil{% endblock title %} + +{% block header %} +

Sélection du profil

+{% endblock header %} + +{% block main %} + +Vous êtes connecté, mais votre compte n'est associé à aucun profil. Veuillez contacter le webmestre à l'adresse valentin@mp2i-vms.fr. + +{% endblock main %} diff --git a/colloscope/templates/trunk.html b/colloscope/templates/trunk.html new file mode 100644 index 0000000..78f0b9c --- /dev/null +++ b/colloscope/templates/trunk.html @@ -0,0 +1,4 @@ +{% extends "base.html" %} + +{% block header %} +{% endblock header %} diff --git a/colloscope/test.pdf b/colloscope/test.pdf deleted file mode 100644 index a3a217c..0000000 Binary files a/colloscope/test.pdf and /dev/null differ diff --git a/colloscope/urls.py b/colloscope/urls.py index 24355a6..70df17a 100644 --- a/colloscope/urls.py +++ b/colloscope/urls.py @@ -2,7 +2,8 @@ from django.urls import path from . import views urlpatterns = [ - path("", views.colloscope, name="colloscope"), - path("export", views.export, name="export"), - path("choix_profil", views.choix_profil, name="choix_profil") + path("", views.home_redirect, name="colloscope.home"), + path("table.html", views.colloscope, name="colloscope.table"), + path("export.pdf", views.export, name="colloscope.export"), + path("choix_profil", views.choix_profil, name="colloscope.choix_profil"), ] diff --git a/colloscope/views.py b/colloscope/views.py index 0573fa2..05b0a29 100644 --- a/colloscope/views.py +++ b/colloscope/views.py @@ -1,7 +1,10 @@ from datetime import timedelta +from django.shortcuts import redirect from django.http import HttpResponse from django.template import loader +from django.contrib.auth.decorators import login_required + from colloscope.models import * from colloscope.table import table_colloscope from colloscope.pdfexport import main # /!\ temporaire @@ -14,18 +17,59 @@ def handler404(request): return HttpResponse(template.render(context)) +def home_redirect(request): + return redirect("/colloscope/table.html") + + +@login_required def choix_profil(request): - template = loader.get_template("choix_profil.html") + user = request.user + session = request.session - utilisateur = Utilisateur.objects.get(id=1) - - context = { - "user": utilisateur, - } - return HttpResponse(template.render(context)) + if not Profil.objects.filter(utilisateur=user).exists(): + profil = Profil(utilisateur=user) + profil.save() + else: + profil = Profil.objects.get(utilisateur=user) + if profil.etudiant is not None and profil.colleur is None: + session["profil"] = "etudiant" + return redirect("/colloscope/") + elif profil.colleur is not None and profil.etudiant is None: + session["profil"] = "colleur" + return redirect("/colloscope/") + else: + if profil.etudiant is not None: + template = loader.get_template("choix_profil.html") + else: + template = loader.get_template("profil_non_associe.html") + + context = { + "profil": profil, + } + return HttpResponse(template.render(context)) + + +@login_required def colloscope(request): + user = request.user + session = request.session + + match session.get("profil"): + case "etudiant": + profil = Profil.objects \ + .select_related("etudiant__classe") \ + .prefetch_related("etudiant__classe__periode_set") \ + .get(utilisateur=user) + etudiant = profil.etudiant + case "colleur": + return HttpResponse("pas (encore) supporté") + case _: + return redirect("/colloscope/choix_profil") + + + """ periode_str = request.GET.get("periode", "") if periode_str=="": periode = Periode.objects.get(id=3) @@ -38,8 +82,14 @@ def colloscope(request): response = HttpResponse(template.render(context, request)) response.status_code = 404 return response + """ + + periode = etudiant.classe.periode_set.order_by("-debut").first() + + creneaux = Creneau.objects \ + .filter(periode=periode, est_colle=True) \ + .prefetch_related("rotation_set") - creneaux = Creneau.objects.filter(periode=periode, est_colle=True) semaines = periode.range_semaines() rotations = [ (c, []) for c in creneaux ] for c, l in rotations: @@ -77,6 +127,7 @@ def colloscope(request): return HttpResponse(template.render(context, request)) + def export(request): return HttpResponse(bytes(main().output()), content_type="application/pdf") diff --git a/kholles_web/urls.py b/kholles_web/urls.py index 166821d..497c974 100644 --- a/kholles_web/urls.py +++ b/kholles_web/urls.py @@ -14,10 +14,14 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ -from django.contrib import admin +from django.contrib import admin, auth from django.urls import include, path +from colloscope.views import home_redirect + urlpatterns = [ + path('', home_redirect, name="home"), path('colloscope/', include('colloscope.urls')), path('admin/', admin.site.urls), + path('comptes/', include("django.contrib.auth.urls")), ] diff --git a/static/main.css b/static/main.css index 309f005..f275b84 100644 --- a/static/main.css +++ b/static/main.css @@ -1,10 +1,46 @@ +* { + box-sizing: border-box; +} + body { font-family: sans-serif; + background-color: #fafafa; margin: 0; } +header .bandeau { + display: block; + background-color: #333; + color: white; + padding: 10px; +} + +header .bandeau form { + display: inline; +} + +header .bandeau button { + border: none; + background-color: gold; + color: black; + padding: 5px 10px; + margin: 0 5px; + border-radius: 3px; +} + +header .bandeau button:hover { + background-color: goldenrod; +} + +header .bandeau button:active { + background-color: darkgoldenrod; +} + main { - margin: 5px; + margin: auto; + width: clamp(350px, 60%, 1200px); + background-color: white; + padding: 10px; } h1 { diff --git a/static/table.css b/static/table.css index f420455..ee3edad 100644 --- a/static/table.css +++ b/static/table.css @@ -1,3 +1,7 @@ +.table-wrapper { + overflow-x: auto; +} + table { border: 1px solid #eee; border-collapse: collapse; diff --git a/colloscope/templates/404.html b/templates/404.html similarity index 100% rename from colloscope/templates/404.html rename to templates/404.html diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..14ad01f --- /dev/null +++ b/templates/base.html @@ -0,0 +1,38 @@ +{% load static %} + + + + + + {% block title %}{% endblock title %} + + {% block head %}{% endblock head %} + + +
+ {% if request.user.is_authenticated %} +
+ Vous êtes connecté avec le compte {{ user.username }}. + {% if request.session.profil == "etudiant" %} + Profil actuel : étudiant. + {% elif request.session.profil == "colleur" %} + Profil actuel : colleur. + {% else %} + Pas de profil. + {% endif %} +
+ {% csrf_token %} + +
+
+ {% endif %} + + {% block header %}{% endblock header %} +
+
+ {% block main %}{% endblock main %} +
+ + diff --git a/templates/registration/login.html b/templates/registration/login.html new file mode 100644 index 0000000..7e9e882 --- /dev/null +++ b/templates/registration/login.html @@ -0,0 +1,44 @@ +{% extends "base.html" %} + +{% block title %}Se connecter{% endblock title %} + +{% block main %} + +

Se connecter

+ +{% if form.errors %} +

Your username and password didn't match. Please try again.

+{% endif %} + +{% if next %} + {% if user.is_authenticated %} +

Your account doesn't have access to this page. To proceed, + please login with an account that has access.

+ {% else %} +

Please login to see this page.

+ {% endif %} +{% endif %} + +
+{% csrf_token %} + + + + + + + + + +
{{ form.username.label_tag }}{{ form.username }}
{{ form.password.label_tag }}{{ form.password }}
+ + + +
+ +{# Assumes you set up the password_reset view in your URLconf #} +

Mot de passe oublié ?

+ +{% endblock main %} + +