From 51ac7fc5fb0a2768298f02b7240200cfdd0bb650 Mon Sep 17 00:00:00 2001 From: Gregory Trullemans Date: Sun, 25 Feb 2024 20:02:20 +0100 Subject: [PATCH] =?UTF-8?q?Update=20passe=20form,=20migrations,=20?= =?UTF-8?q?=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jarvis/objective/forms.py | 47 ++++++- jarvis/objective/migrations/0017_passe.py | 27 +++- ..._regexp_remove_passe_educative_and_more.py | 38 ------ jarvis/objective/models.py | 50 +++++++- .../templates/combinations/create.html | 16 +-- jarvis/objective/templates/passes/create.html | 117 +++++++++++++++++ .../objective/templates/passes/details.html | 70 +---------- jarvis/objective/templates/passes/list.html | 119 +++++++----------- .../templates/trainingprograms/details.html | 29 +++++ jarvis/objective/urls.py | 14 +++ jarvis/objective/views.py | 96 +++++++++++++- 11 files changed, 429 insertions(+), 194 deletions(-) delete mode 100644 jarvis/objective/migrations/0018_passe_regexp_remove_passe_educative_and_more.py create mode 100644 jarvis/objective/templates/passes/create.html create mode 100644 jarvis/objective/templates/trainingprograms/details.html diff --git a/jarvis/objective/forms.py b/jarvis/objective/forms.py index baffdf8..0e26731 100644 --- a/jarvis/objective/forms.py +++ b/jarvis/objective/forms.py @@ -1,6 +1,6 @@ from django import forms -from .models import Skill, Routine, RoutineSkill +from .models import Skill, Routine, RoutineSkill, Passe class SkillForm(forms.ModelForm): @@ -64,3 +64,48 @@ class CombinationSkillForm(forms.ModelForm): "skill": forms.HiddenInput(), "rank": forms.NumberInput(), } + + +class PasseForm(forms.ModelForm): + class Meta: + model = Passe + fields = ("label", "educative", "repetition", "regexp", "informations") + widgets = { + "label": forms.TextInput( + attrs={ + "class": "form-control", + "placeholder": "Label (not mandatory)", + "maxlength": 30, + } + ), + "repetition": forms.NumberInput( + attrs={ + "class": "form-control", + "placeholder": "x", + "min": "0", + "max": "1000", + "step": "1", + } + ), + "regexp": forms.TextInput( + attrs={"class": "form-control", "placeholder": "[2-8]"} + ), + "informations": forms.Textarea( + attrs={ + "class": "form-control", + "placeholder": "Informations about the passe…", # pylint: disable=line-too-long + } + ), + "educative": forms.HiddenInput(), + } + + educative_related = forms.CharField( + required=False, + widget=forms.TextInput( + attrs={ + "class": "form-control", + "placeholder": "Searching educative", + "data-ref": "#id_educative", + } + ), + ) diff --git a/jarvis/objective/migrations/0017_passe.py b/jarvis/objective/migrations/0017_passe.py index d64685b..1b0ef98 100644 --- a/jarvis/objective/migrations/0017_passe.py +++ b/jarvis/objective/migrations/0017_passe.py @@ -1,6 +1,7 @@ -# Generated by Django 4.2 on 2024-02-25 07:33 +# Generated by Django 4.2 on 2024-02-25 18:38 from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): @@ -22,14 +23,30 @@ class Migration(migrations.Migration): verbose_name="ID", ), ), - ("label", models.CharField(blank=True, max_length=25, null=True)), - ("repetition", models.PositiveSmallIntegerField()), + ( + "informations", + models.TextField( + blank=True, + help_text="Only MarkDown is authorized", + null=True, + verbose_name="Comments", + ), + ), + ("label", models.CharField(blank=True, max_length=30, null=True)), + ("repetition", models.PositiveSmallIntegerField(default=1)), + ("regexp", models.CharField(blank=True, max_length=50, null=True)), + ("number_of_skill", models.PositiveSmallIntegerField()), + ("difficulty", models.DecimalField(decimal_places=1, max_digits=4)), ( "educative", - models.ManyToManyField( - related_name="passes", to="objective.educative" + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="objective.educative", ), ), ], + options={ + "abstract": False, + }, ), ] diff --git a/jarvis/objective/migrations/0018_passe_regexp_remove_passe_educative_and_more.py b/jarvis/objective/migrations/0018_passe_regexp_remove_passe_educative_and_more.py deleted file mode 100644 index 72f857e..0000000 --- a/jarvis/objective/migrations/0018_passe_regexp_remove_passe_educative_and_more.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 4.2 on 2024-02-25 08:54 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ("objective", "0017_passe"), - ] - - operations = [ - migrations.AddField( - model_name="passe", - name="regexp", - field=models.CharField(blank=True, max_length=50, null=True), - ), - migrations.RemoveField( - model_name="passe", - name="educative", - ), - migrations.AlterField( - model_name="passe", - name="label", - field=models.CharField(blank=True, max_length=30, null=True), - ), - migrations.AddField( - model_name="passe", - name="educative", - field=models.ForeignKey( - default=None, - on_delete=django.db.models.deletion.CASCADE, - to="objective.educative", - ), - preserve_default=False, - ), - ] diff --git a/jarvis/objective/models.py b/jarvis/objective/models.py index e205acc..e83ac2c 100644 --- a/jarvis/objective/models.py +++ b/jarvis/objective/models.py @@ -458,13 +458,59 @@ class RoutineSkill(models.Model): return f"{self.rank} - {self.routine.short_label} : {self.skill.short_label}" -class Passe(models.Model): +class Passe(Markdownizable): """Classe représentant les passages (à faire pendant un entraînement).""" label = models.CharField(max_length=30, null=True, blank=True) educative = models.ForeignKey(Educative, on_delete=models.CASCADE) - repetition = models.PositiveSmallIntegerField() + repetition = models.PositiveSmallIntegerField(default=1) regexp = models.CharField(max_length=50, null=True, blank=True) + number_of_skill = models.PositiveSmallIntegerField() + difficulty = models.DecimalField(max_digits=4, decimal_places=1) + + def save(self, *args, **kwargs): + """Sauve les informations de la personne et initialise les champs nettoyés.""" + is_skill = False + try: + educative = Routine.objects.get(pk=self.educative) + except Routine.DoesNotExist: + educative = Skill.objects.get(pk=self.educative) + is_skill = True + + if is_skill: + self.number_of_skill = self.repetition + self.difficulty = educative.difficulty * self.repetition + else: + if self.regexp is not None: + regexp = self.regexp.replace("[", "").replace("]", "") + position = regexp.find("-") + + start = regexp[:position] + if start == "": + start = 0 + else: + start = int(start) + + end = regexp[position + 1 :] + if end == "": + end = educative.jumps.all().count() + else: + end = int(end) + + self.number_of_skill = (end - (start - 1)) * self.repetition + list_of_skill = educative.skill_links.filter( + rank__gte=start, rank__lte=end + ) + # .aggregate(total=Sum("value")) + self.difficulty = 0 + for routine_skill in list_of_skill: + self.difficulty += routine_skill.skill.difficulty + self.difficulty *= self.repetition + + else: + self.number_of_skill = educative.jumps.all().count() * self.repetition + self.difficulty = educative.difficulty * self.repetition + super().save(*args, **kwargs) def __str__(self): if self.label: diff --git a/jarvis/objective/templates/combinations/create.html b/jarvis/objective/templates/combinations/create.html index cd1c475..6c584b5 100644 --- a/jarvis/objective/templates/combinations/create.html +++ b/jarvis/objective/templates/combinations/create.html @@ -14,30 +14,30 @@ {{ hidden }} {% endfor %}
- -
+ +
{{ form.long_label }} {% if form.long_label.errors %} {% for error in form.long_label.errors %}{{ error }}{% endfor %}{% endif %}
- -
+ +
{{ form.short_label }} {% if form.short_label.errors %}{% for error in form.short_label.errors %}{{ error }}{% endfor %}{% endif %}
- -
+ +
{{ form.is_routine }} {% if form.is_routine.errors %}{% for error in form.is_routine.errors %}{{ error }}{% endfor %}{% endif %}
- -
+ +
{{ form.is_competitive }} {% if form.is_competitive.errors %}{% for error in form.is_competitive.errors %}{{ error }}{% endfor %}{% endif %}
diff --git a/jarvis/objective/templates/passes/create.html b/jarvis/objective/templates/passes/create.html new file mode 100644 index 0000000..dbe8f8b --- /dev/null +++ b/jarvis/objective/templates/passes/create.html @@ -0,0 +1,117 @@ +{% extends "base.html" %} + +{% block content %} +
+
+
+
+

{% if passe_id %}Edit{% else %}Add{% endif %} Passe

+
+
+
+ + {% csrf_token %} + {% for hidden in form.hidden_fields %} + {{ hidden }} + {% endfor %} + +
+ +
+ {{ form.label }} + {% if form.label.errors %} {% for error in form.label.errors %}{{ error }}{% endfor %}{% endif %} +
+
+ +
+ +
+ {{ form.educative_related }} + {% if form.educative.errors %} {% for error in form.educative.errors %}{{ error }}{% endfor %}{% endif %} +
+
+ +
+ +
+ {{ form.repetition }} + {% if form.repetition.errors %} {% for error in form.repetition.errors %}{{ error }}{% endfor %}{% endif %} +
+
+ +
+ +
+ {{ form.regexp }} + {% if form.regexp.errors %} {% for error in form.regexp.errors %}{{ error }}{% endfor %}{% endif %} +
+
+ +
+ +
+ {{ form.informations }} +
+
+
+ +
+
+
+
+
+
+ +{% endblock %} + +{% block footerscript %} + +{% endblock %} diff --git a/jarvis/objective/templates/passes/details.html b/jarvis/objective/templates/passes/details.html index 00bc272..4ec8725 100644 --- a/jarvis/objective/templates/passes/details.html +++ b/jarvis/objective/templates/passes/details.html @@ -7,71 +7,13 @@
-
-

{{ combination.short_label }}

-
{{ combination.long_label }}
-
- {% if skill_link_list %} - - {% for link in skill_link_list %} - - - - - - - {% endfor %} - - - - -
{{ link.skill.notation }}{{ link.skill.short_label }}{% if link.skill.difficulty != 0.0 %}{{ link.skill.difficulty }}{% endif %}
{{ combination.difficulty }}
- - {{ combination_string }} - {% else %} -

No skill defined for this combination.

- {% endif %} -
- - {% if combination.informations %} -
-
-

Informations

- - - {{ combination.to_markdown | safe }} - -
- {% endif %} - -
diff --git a/jarvis/objective/templates/passes/list.html b/jarvis/objective/templates/passes/list.html index 7e3665e..aa5e2b2 100644 --- a/jarvis/objective/templates/passes/list.html +++ b/jarvis/objective/templates/passes/list.html @@ -1,73 +1,42 @@ {% extends "listing.html" %} -{% load has_group %} {% block datacontent %}
-

{{ title }} Listing {% if gymnast_id %}for {{ gymnast }}{% endif %}

+

Passes Listing

-
- {% if request.user|has_group:"trainer" %} - - - - {% endif %} -
+
- {% if routine_list %} - - - - {% if request.user|has_group:"trainer" %} - - {% endif %} - - - - - - - - - - - - {% for routine in routine_list %} - - {% if request.user|has_group:"trainer" %} - - {% endif %} - - - - - - - - - - {% endfor %} - -
 Long Label Short LabelCompetitive ?Diff.LevelRank
- - - - {{ routine.long_label }}{{ routine.short_label }} - {% if routine.is_competitive %} - {% else %} - {% endif %} - {{ routine.age_girl_masterised }}{{ routine.age_boy_masterised }}{{ routine.difficulty }}{{ routine.level }}{{ routine.rank }}
+ {% if passes_list %} + + + + + + + + + + + {% for passe in passes_list %} + + + + + + + {% endfor %} + +
labeleducativerepetitionregexp
{{ passe.label }}{{ passe.educative }}{{ passe.repetition }}{{ passe.regexp }}
{% else %} -

There are no {{ title|lower }} corresponding to your criterias.

+

There are no passe corresponding to your criterias.

{% endif %}
@@ -76,26 +45,26 @@ {% block footerscript %} {% endblock %} \ No newline at end of file diff --git a/jarvis/objective/templates/trainingprograms/details.html b/jarvis/objective/templates/trainingprograms/details.html new file mode 100644 index 0000000..53a8508 --- /dev/null +++ b/jarvis/objective/templates/trainingprograms/details.html @@ -0,0 +1,29 @@ +{% extends "base.html" %} +{% load has_group %} + +{% block page_title %}{{ combination.short_label }}{% endblock %} + +{% block content %} +
+
+
+
+ {% if trainingprogram_list %} + + + + + {% for trainingprogram in trainingprogram_list %} + + + + + + {% endfor %} +
--DATE--
{{ trainingprogram.passe.label }} {{ trainingprogram.passe.repetition }}{{ trainingprogram.passe.number_of_skill}}{{ trainingprogram.passe.difficulty }}
+ {% endif %} +
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/jarvis/objective/urls.py b/jarvis/objective/urls.py index 6626bba..f6c7ffd 100644 --- a/jarvis/objective/urls.py +++ b/jarvis/objective/urls.py @@ -3,6 +3,10 @@ from . import views urlpatterns = [ + # + # + # + path(r"educative/lookup/", views.educative_lookup, name="educative_lookup"), # # SKILLS # @@ -85,4 +89,14 @@ urlpatterns = [ # path(r"passe//", views.passe_details, name="passe_details"), path(r"passe/", views.passe_listing, name="passe_listing"), + path( + r"passe/add/", + views.passe_create_or_update, + name="passe_create", + ), + path( + r"passe/edit//", + views.passe_create_or_update, + name="passe_update", + ), ] diff --git a/jarvis/objective/views.py b/jarvis/objective/views.py index 9c801a4..4d89062 100644 --- a/jarvis/objective/views.py +++ b/jarvis/objective/views.py @@ -9,6 +9,7 @@ from jarvis.people.models import Gymnast from .forms import ( SkillForm, + PasseForm, CombinationForm, CombinationSkillForm, ) @@ -16,11 +17,35 @@ from .models import ( Skill, Passe, Routine, + Educative, RoutineSkill, PrerequisiteClosure, ) +@login_required +@require_http_methods(["POST"]) +def educative_lookup(request): + """ + Récupère la liste des skill à la volée suivant des caractères de recherche entrés (min 3 + caractères). + """ + results = [] + pattern = request.POST.get("pattern", None) + + # Ignore queries shorter than length 2 + if pattern is not None and len(pattern) > 2: + model_results = Educative.objects.filter( + Q(short_label__icontains=pattern) | Q(long_label__icontains=pattern) + ) + results = [ + {"ID": x.id, "long_label": x.long_label, "short_label": x.short_label} + for x in model_results + ] + + return JsonResponse(results, safe=False) + + @login_required @require_http_methods(["POST"]) def skill_lookup(request): @@ -486,9 +511,78 @@ def passe_details(request, passe_id): """Détails d'un passage.""" passe = get_object_or_404(Passe, pk=passe_id) - educative = passe.educative + + try: + educative = Routine.objects.get(pk=passe.educative) + is_skill = False + except Routine.DoesNotExist: + educative = Skill.objects.get(pk=passe.educative) + is_skill = True + + if is_skill: + number_of_skill = passe.repetition + difficulty = educative.difficulty * passe.repetition + else: + if passe.regexp is not None: + regexp = passe.regexp.replace("[", "").replace("]", "") + position = regexp.find("-") + + start = regexp[:position] + if start == "": + start = 0 + else: + start = int(start) + + end = regexp[position + 1 :] + if end == "": + end = educative.jumps.all().count() + else: + end = int(end) + + number_of_skill = (end - (start - 1)) * passe.repetition + list_of_skill = educative.skill_links.filter(rank__gte=start, rank__lte=end) + # .aggregate(total=Sum("value")) + difficulty = 0 + for routine_skill in list_of_skill: + difficulty += routine_skill.skill.difficulty + difficulty *= passe.repetition + + else: + number_of_skill = educative.jumps.all().count() * passe.repetition + difficulty = educative.difficulty * passe.repetition + context = { "passe": passe, + "is_skill": is_skill, "educative": educative, + "difficulty": difficulty, + "number_of_skill": number_of_skill, } return render(request, "passes/details.html", context) + + +@login_required +@require_http_methods(["GET", "POST"]) +def passe_create_or_update(request, passe_id=None): + """Création d'un passage. + + Args: + passe_id (int) identifiant d'un object de classe . + """ + if passe_id: + passe = get_object_or_404(Passe, pk=passe_id) + else: + passe = None + + if request.method == "POST": + form = PasseForm(request.POST, instance=passe) + + if form.is_valid(): + passe = form.save() + return HttpResponseRedirect(reverse("passe_details", args=(passe.pk,))) + + return render(request, "passes/create.html", {"form": form}) + + form = PasseForm(instance=passe) + context = {"form": form, "passe_id": passe_id} + return render(request, "passes/create.html", context)