From e6207d9a7aebac663e5e75abcc0636b3452e8100 Mon Sep 17 00:00:00 2001 From: Fred Pauchet Date: Sun, 16 May 2021 21:02:08 +0200 Subject: [PATCH 1/4] =?UTF-8?q?Quelques=20id=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/planning/README.md | 45 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/planning/README.md b/src/planning/README.md index 4c942df..d08b5e4 100644 --- a/src/planning/README.md +++ b/src/planning/README.md @@ -1,7 +1,9 @@ # Application `Planning` ## Saison + Une saison est déinie par : + - un id, - un label, - une date de début et @@ -11,9 +13,12 @@ La date de début est très souvent le : 01/09/xxxx La date de fin est très souvent le : 31/08/xxxy Exemple : 1/9/2015 - 31/8/2016 +NOTE: Le fait que la date de début soit **très souvent** le 01 septembre indique sans doute une date par défaut (modifiable) au niveau du modèle. Idem pour la date de fin. +NOTE: je ne comprends pas la méthode `week_number_from_begin`. Si cela fait référence à la date de début, alors il faut le mentionner dans le nom de la fonction. ## Course + Un cours est un ensemble d'entraînements (`training`) (récurrents ?) défini par : - une heure de début et une heure de fin, - une date de début et une date de fin (un cours est considéré comme donné hebdomadairement entre @@ -24,16 +29,32 @@ Un cours est un ensemble d'entraînements (`training`) (récurrents ?) défini p Réflexion : les cours devraient-ils être liés à une saison ? +NOTE: Je dirais que oui. D'un côté, tu n'aurais pas de possibilité de déduction entre un cours et le moment où il y a réellement lieu - de ce que je comprends, le *cours* correspond en fait à quelque chose qui est prévu selon une récurrence donnée - eg. "tous les mardis (deuxième jour de la semaine), entre 10h et 12h, avec Machin, Chose et Brol". +La *saison* va juste indiquer la date de début et de fin des cours qui y sont liés. +Même s'il y a moyen de le représenter différement, je pense surtout que le concept de saison parle à beaucoup de monde. + +NOTE: la réflexion va surtout être "est-ce qu'un cours est différent entre deux saison ?" A priori, oui, puisque Bidule peut devenir entraineur pour la saison 2020-2021. + +L'avantage, c'est que Machin pourrait se connecter sur son profil et dire "ah ouais, cette année, je donne cours le jeudi et le samedi." ## Training + Un entraînement est une occurence d'un cours pendant lequel des gmnastes sont présents. + Un objet de cette classe lie donc : -- un cours, -- gymnaste et +- un cours, +- des gymnastes présents et - une date. +NOTE: Techniquement, tu peux ici mettre une contrainte ou un avertissement si l'entrainement est situé à une date différente de ce que la saison devrait autoriser. + +NOTE: dans la classe Training, il est question d'une `ForeignKey` vers Gymnast, mais ce devrait être un ManyToManyField. + +NOTE: De la même manière, je reprendrais aussi l'heure de début et de fin. Entre ce qui est prévu (le cours) et la réalité (l'entraintement), il pourrait y avoir des différences. + +Cela permettrait aussi de planifier les cours - dire en gros que, en début d'année, tu (l'appli) planifies les jours fériés, et *projette* les entrainements pour la saison, sur base de ce qui est prévu. ## Round @@ -41,6 +62,10 @@ Un objet de cette classe lie donc : Classe représentant les passages des élèves lors d'un entrainement. Chaque record représente un passage. Il est donc lié à un record de la classe `Training`. +NOTE: Est-ce qu'il est important de savoir qui est l'entraineur qui a donné une évaluation ? + +NOTE: au niveau du round, il y a un ensemble d'informations chronologiques: `nb_of_realisations` (au pluriel...), `nb_of_success`, ... mais c'est incohérent avec le `round_number`, puisque je suppose qu'il pourrait faire un tour de A, puis B, puis revenir à A. +Cette partie-ci me semble très complexe - sans oublier qu'il va falloir la remplir: si tes entraineurs chipotent sur une tablette ou sur un écran pour chaque action que réalise un gymnaste, ça va pas être sympa pour eux. ## Group @@ -48,6 +73,11 @@ Chaque record représente un passage. Il est donc lié à un record de la classe Classe représentant les groupes (Loisir, D1, D2, A, B, …). Un groupe appartient à un club. +NOTE: pourquoi garder un champ `active` ? Il y a un risque qu'un groupe soit désactivé ? Si oui, ne vaut-il pas mieux garder le moment où il l'a été ? + +NOTE: est-ce que le champ `name` n'est pas un dictionnaire fini ? Loisir, D1, D2, ... ? + +NOTE: est-ce que tu n'as pas une contrainte sur le nom, le club et la saison ? ## Subgroup @@ -59,28 +89,33 @@ Un sous-groupe appartient à un groupe (pour rappel, lui-même lié à un club). De cette manière, quand un gymnaste est mis dans un sous-groupe, en remontant via le groupe, nous pouvons connaître le(s) club(s) du gymnaste pour chaque saison. - +NOTE: re-question sur le `name`. A mon avis, si le nom du groupe est fini, tu peux te passer d'une des classes `Group` ou `Subgroup`, et cela simplifierait pas mal la gestion du club. ## Unavailability Classe représentant les indisponibilités. +NOTE: avec la réflexion ci-dessous, cela pourrait ne plus être utile. Les *Courses* correspondent à la modélisation tandis que les entrainements représentent le planifié/réalisé. Du coup, il suffit qu'un entrainenemnts n'existe pas pour qu'il ne soit pas planifié. ## PlanningLine + Classe représentant les passages prévisionnels (incubating idea). +NOTE: en gros, tu veux proposer un entrainement personnalisé pour chaque gymnaste ;) Je ne vois pas la valeur ajoutée. Le mieux serait d'avoir une forme de proposition au niveau des Rounds et des Trainings, quitte à la modifier pendant l'entrainement. Sinon, je ne vois pas trop l'idée. ## EventType Classe représentant les types d'évènements. + C'est un dictionnaire fini : - compétiton qualificative, - compétition finale, - démonstration, - … +NOTE: tu peux utiliser un champ de type Choice, si le dictionnaire est fini. Cela te fera gagner une jointure. Si le dictionnaire a ***une*** chance d'avoir une nouvelle valeur, garde la table. ## Event @@ -95,6 +130,8 @@ Un évènement est caractérisé par : Je ne me rapelle plus à quoi sert le club. - +NOTE: alors, retire le club :-p ## Event_Participation + +NOTE: Dans Event, tu as déjà un lien avec des gymnastes, que tu reprends dans la classe EventParticipation (pas de "*_*"). Autant ne garder qu'une seule liaison entre un évènement et des gymnastes, et compléter ces enregistrements après (ou pendant) pour dire si Choupidou étant bien placé ou pas (quitte à laisser le `rank` vide si Choupidou n'est finalement pas venu ou s'il a sauté comme une bouse - oui, ça arrive). From 6f81a0d5955c9639dc224f298a5a6a6b9c5a9233 Mon Sep 17 00:00:00 2001 From: Fred Date: Wed, 16 Jun 2021 19:27:20 +0200 Subject: [PATCH 2/4] Fix bug https://sources.grimbox.be/Sulley/khana/issues/67 + Simplification de l'URL + Simplification de la vue Fix #67 --- src/profile/urls.py | 2 +- src/profile/views.py | 11 +- src/templates/base.html | 234 +++++++++++++++++++++++----------------- 3 files changed, 138 insertions(+), 109 deletions(-) diff --git a/src/profile/urls.py b/src/profile/urls.py index 7b825c0..2c7bd6b 100644 --- a/src/profile/urls.py +++ b/src/profile/urls.py @@ -7,5 +7,5 @@ from . import views profile_urlpatterns = [ path(r"lookup/", views.user_lookup, name="user_lookup"), - path(r"edit//", views.profile_update, name="profile_update"), + path(r"edit/", views.profile_update, name="profile_update"), ] diff --git a/src/profile/views.py b/src/profile/views.py index e375b3c..8dd71ed 100644 --- a/src/profile/views.py +++ b/src/profile/views.py @@ -60,17 +60,12 @@ def user_lookup(request): @login_required @require_http_methods(["GET", "POST"]) -def profile_update(request, profileid): - """Modification d'un profil utilisateur. +def profile_update(request): + """Modification du profil de l'utilisateur connecté - Args: - profileid (int): L'identifiant du profil utilisateur à modifier. """ - profile = get_object_or_404(Profile, pk=profileid) - - if profile.user != request.user: - raise PermissionDenied("Permission denied : you don't have the permission to update this profile.") + profile = request.user.profile if request.method == "POST": form = ProfileForm(request.POST, instance=profile) diff --git a/src/templates/base.html b/src/templates/base.html index 0b53ca0..f683874 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -87,93 +87,95 @@ - - Dashboard - - - + Dashboard + + + -
-
+ {% csrf_token %}
@@ -59,10 +59,10 @@
- -{% endblock %} +{% endblock %} \ No newline at end of file From 801477eadd545c7938ef7b0be091e6462d617afb Mon Sep 17 00:00:00 2001 From: Fred Date: Wed, 16 Jun 2021 19:37:34 +0200 Subject: [PATCH 4/4] Revert to master base.html --- src/templates/base.html | 57 ++++++++--------------------------------- 1 file changed, 11 insertions(+), 46 deletions(-) diff --git a/src/templates/base.html b/src/templates/base.html index 0f31ad6..c614494 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -301,57 +301,22 @@ $full_page = $('.full-page'); $sidebar_responsive = $('body > .navbar-collapse'); - { - % - if request.session.is_sidebar_minified % - } - sidebar_mini_active = true; { - % - else % - } - sidebar_mini_active = false; { - % - endif % - } - - - { - % - if request.session.template == 0 % - } - white_color = false; { - % - else % - } - white_color = true; { - % - endif % - } + {% if request.session.is_sidebar_minified %} + sidebar_mini_active = true; {% else %} + sidebar_mini_active = false; {% endif %} + {% if request.session.template == 0 %} + white_color = false; {% else %} + white_color = true; {% endif %} window_width = $(window).width(); fixed_plugin_open = $('.sidebar .sidebar-wrapper .nav li.active a p').html(); - { - % - if request.session.sidebar == 1 % - } - color = "blue"; { - % - elif request.session.sidebar == 2 % - } - color = "green"; { - % - elif request.session.sidebar == 3 % - } - color = "orange"; { - % - elif request.session.sidebar == 4 % - } - color = "red"; { - % - endif % - } + {% if request.session.sidebar == 1 %} + color = "blue"; {% elif request.session.sidebar == 2 %} + color = "green"; {% elif request.session.sidebar == 3 %} + color = "orange"; {% elif request.session.sidebar == 4 %} + color = "red"; {% endif %} $sidebar.attr('data', color); $main_panel.attr('data', color); $full_page.attr('filter-color', color);