Update passe form, migrations, …

This commit is contained in:
Gregory Trullemans 2024-02-25 20:02:20 +01:00
parent b026edbb27
commit 51ac7fc5fb
11 changed files with 429 additions and 194 deletions

View File

@ -1,6 +1,6 @@
from django import forms from django import forms
from .models import Skill, Routine, RoutineSkill from .models import Skill, Routine, RoutineSkill, Passe
class SkillForm(forms.ModelForm): class SkillForm(forms.ModelForm):
@ -64,3 +64,48 @@ class CombinationSkillForm(forms.ModelForm):
"skill": forms.HiddenInput(), "skill": forms.HiddenInput(),
"rank": forms.NumberInput(), "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",
}
),
)

View File

@ -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 from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -22,14 +23,30 @@ class Migration(migrations.Migration):
verbose_name="ID", 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", "educative",
models.ManyToManyField( models.ForeignKey(
related_name="passes", to="objective.educative" on_delete=django.db.models.deletion.CASCADE,
to="objective.educative",
), ),
), ),
], ],
options={
"abstract": False,
},
), ),
] ]

View File

@ -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,
),
]

View File

@ -458,13 +458,59 @@ class RoutineSkill(models.Model):
return f"{self.rank} - {self.routine.short_label} : {self.skill.short_label}" 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).""" """Classe représentant les passages (à faire pendant un entraînement)."""
label = models.CharField(max_length=30, null=True, blank=True) label = models.CharField(max_length=30, null=True, blank=True)
educative = models.ForeignKey(Educative, on_delete=models.CASCADE) 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) 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): def __str__(self):
if self.label: if self.label:

View File

@ -14,30 +14,30 @@
{{ hidden }} {{ hidden }}
{% endfor %} {% endfor %}
<div class="form-group row {% if form.long_label.errors %}has-error has-feedback{% endif %}"> <div class="form-group row {% if form.long_label.errors %}has-error has-feedback{% endif %}">
<label for="id_date" class="col-4 col-sm-2 col-md-3 col-lg-3 col-xl-3 col-form-label">Long label <span class="text-danger"><b>*</b></span></label> <label for="id_long_label" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Long label <span class="text-danger"><b>*</b></span></label>
<div class="col-8 col-sm-9 col-md-9 col-lg-9 col-xl-9"> <div class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10">
{{ form.long_label }}&nbsp;{% if form.long_label.errors %} {{ form.long_label }}&nbsp;{% if form.long_label.errors %}
{% for error in form.long_label.errors %}{{ error }}{% endfor %}</span>{% endif %} {% for error in form.long_label.errors %}{{ error }}{% endfor %}</span>{% endif %}
</div> </div>
</div> </div>
<div class="form-group row {% if form.short_label.errors %}has-error has-feedback{% endif %}"> <div class="form-group row {% if form.short_label.errors %}has-error has-feedback{% endif %}">
<label for="id_date" class="col-4 col-sm-2 col-md-3 col-lg-3 col-xl-3 col-form-label">Short label <span class="text-danger"><b>*</b></span></label> <label for="id_short_label" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Short label <span class="text-danger"><b>*</b></span></label>
<div class="col-8 col-sm-6 col-md-6 col-lg-6 col-xl-6"> <div class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10">
{{ form.short_label }}&nbsp;{% if form.short_label.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.short_label.errors %}{{ error }}{% endfor %}</span>{% endif %} {{ form.short_label }}&nbsp;{% if form.short_label.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.short_label.errors %}{{ error }}{% endfor %}</span>{% endif %}
</div> </div>
</div> </div>
<div class="form-group row {% if form.is_routine.errors %}has-error has-feedback{% endif %}"> <div class="form-group row {% if form.is_routine.errors %}has-error has-feedback{% endif %}">
<label for="id_date" class="col-4 col-sm-2 col-md-3 col-lg-3 col-xl-3 col-form-label">Is routine ? <span class="text-danger"><b>*</b></span></label> <label for="id_is_routine" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Is routine ? <span class="text-danger"><b>*</b></span></label>
<div class="col-6 col-sm-5 col-md-4 col-lg-3 col-xl-2"> <div class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10">
{{ form.is_routine }}&nbsp;{% if form.is_routine.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.is_routine.errors %}{{ error }}{% endfor %}</span>{% endif %} {{ form.is_routine }}&nbsp;{% if form.is_routine.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.is_routine.errors %}{{ error }}{% endfor %}</span>{% endif %}
</div> </div>
</div> </div>
<div class="form-group row {% if form.is_competitive.errors %}has-error has-feedback{% endif %}"> <div class="form-group row {% if form.is_competitive.errors %}has-error has-feedback{% endif %}">
<label for="id_date" class="col-4 col-sm-2 col-md-3 col-lg-3 col-xl-3 col-form-label">Is Competitive ? <span class="text-danger"><b>*</b></span></label> <label for="id_is_competitive" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Is Competitive ? <span class="text-danger"><b>*</b></span></label>
<div class="col-6 col-sm-5 col-md-4 col-lg-3 col-xl-2"> <div class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10">
{{ form.is_competitive }}&nbsp;{% if form.is_competitive.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.is_competitive.errors %}{{ error }}{% endfor %}</span>{% endif %} {{ form.is_competitive }}&nbsp;{% if form.is_competitive.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.is_competitive.errors %}{{ error }}{% endfor %}</span>{% endif %}
</div> </div>
</div> </div>

View File

@ -0,0 +1,117 @@
{% extends "base.html" %}
{% block content %}
<div class="row justify-content-center">
<div class="col-12 col-sm-12 col-md-8 col-lg-7 col-xl-6">
<div class="card">
<div class="card-header">
<h4 class="">{% if passe_id %}Edit{% else %}Add{% endif %} Passe</h4>
</div>
<div class="card-body">
<form action="{% if passe_id %}{% url 'passe_update' passe_id %}{% else %}{% url 'passe_create' %}{% endif %}" method="post" class="form-horizontal" id="formulaire" name="formulaire">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<div class="form-group row {% if form.long_label.errors %}has-error has-feedback{% endif %}">
<label for="id_label" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Label</label>
<div class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10">
{{ form.label }}
{% if form.label.errors %}&nbsp;<span class="btn btn-sm btn-danger-outline">{% for error in form.label.errors %}{{ error }}{% endfor %}</span>{% endif %}
</div>
</div>
<div class="form-group row ">
<label for="id_educative" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Educative <span class="text-danger"><b>*</b></span></label>
<div class="col-8 col-sm-8 col-md-6 col-lg-6 col-xl-6 {% if form.educative.errors %}has-danger{% endif %}">
{{ form.educative_related }}
{% if form.educative.errors %}&nbsp;<span class="btn btn-sm btn-danger-outline">{% for error in form.educative.errors %}{{ error }}{% endfor %}</span>{% endif %}
</div>
</div>
<div class="form-group row {% if form.repetition.errors %}has-error has-feedback{% endif %}">
<label for="id_repetition" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">{{ form.repetition.label }} <span class="text-danger"><b>*</b></span></label>
<div class="col-4 col-sm-4 col-md-4 col-lg-4 col-xl-3">
{{ form.repetition }}
{% if form.repetition.errors %}&nbsp;<span class="btn btn-sm btn-danger-outline">{% for error in form.repetition.errors %}{{ error }}{% endfor %}</span>{% endif %}
</div>
</div>
<div class="form-group row {% if form.regexp.errors %}has-error has-feedback{% endif %}">
<label for="id_regexp" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">{{ form.regexp.label }}<span class="text-danger"><b>*</b></span></label>
<div class="col-4 col-sm-4 col-md-4 col-lg-4 col-xl-3">
{{ form.regexp }}
{% if form.regexp.errors %}&nbsp;<span class="btn btn-sm btn-danger-outline">{% for error in form.regexp.errors %}{{ error }}{% endfor %}</span>{% endif %}
</div>
</div>
<div class="form-group row ">
<label for="id_informations" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Informations</label>
<div class="col-8 col-sm-9 col-md-9 col-lg-9 col-xl-9 {% if form.id_information.errors %}has-danger{% endif %}">
{{ form.informations }}
</div>
</div>
<div class="form-group text-center">
<input type="submit" value="Save" class="btn btn-warning" />
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
{% block footerscript %}
<script type="text/javascript" >
$(function(){
const csrf_token = "{{ csrf_token|escapejs }}";
const educative_lookup = "{% url 'educative_lookup' %}";
$('#id_educative_related').autocomplete({
source: function(request, response) {
$.ajax({
url: educative_lookup,
method: "POST",
data: {
pattern: $('#id_educative_related').val(),
csrfmiddlewaretoken: csrf_token
},
dataType: "json",
success: function(data) {
if(data.length != 0) {
response($.map(data, function(item) {
return {
label: item.long_label,
value: item.short_label,
educativeid: item.ID
}
}))
} else {
response([{ label: 'No result found.', value: '' }]);
};
},
error: function (exception) {
console.log(exception);
}
});
},
minLength: 3,
select: function (event, ui) {
$($(this).data('ref')).val(ui.item.educativeid);
},
{% if request.session.template == 0 %}
classes: {
"ui-widget-content": "custom_autocomplete_ul",
"ui-autocomplete": "custom_autocomplete_ul",
"ui-menu-item-wrapper": "custom_autocomplete_li",
"ui-menu-item": "custom_autocomplete_li",
},
{% endif %}
});
});
</script>
{% endblock %}

View File

@ -7,71 +7,13 @@
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-12 col-sm-12 col-md-8 col-lg-8 col-xl-6"> <div class="col-12 col-sm-12 col-md-8 col-lg-8 col-xl-6">
<div class="card"> <div class="card">
<div class="card-header">
<h4 class="mb-0">{{ combination.short_label }}</h3>
<h5 class="card-category mb-0">{{ combination.long_label }}</h4>
</div>
<div class="card-body"> <div class="card-body">
{% if skill_link_list %} <b><u>Label :</b></u> {{ passe.label }}<br />
<table class="table table-striped table-condensed col-6 offset-3" id="list_skill_table"> <b><u>Educatif :</b></u> {{ passe.educative }}<br />
{% for link in skill_link_list %} <b><u>Répétition :</b></u> {{ passe.repetition }}<br />
<tr> <b><u>RegExp :</b></u> {{ passe.regexp }}<br /><br />
<td></td> <a href="{% url 'combination_details' passe.educative.id %}">{{ passe.label }}{% if passe.regexp %}{{ passe.regexp }}{% endif %}</a>&nbsp;&nbsp;&nbsp;{{ passe.repetition }}<br /><br />
<td><a href="{% url 'skill_details' link.skill.id %}">{{ link.skill.notation }}</a></td> {{ number_of_skill }} - {{ difficulty }}
<td><a href="{% url 'skill_details' link.skill.id %}">{{ link.skill.short_label }}</a></td>
<td class="text-center">{% if link.skill.difficulty != 0.0 %}{{ link.skill.difficulty }}{% endif %}</td>
</tr>
{% endfor %}
<tr>
<td colspan="3" class="text-right"></td>
<td class="text-center"><b>{{ combination.difficulty }}</b></td>
</tr>
</table>
<div class="row">
<div class="col-3 text-center">Niveau : <a href="#">{{ combination.level }}</a></div>
<div class="col-3 text-center">Rank : <a href="#">{{ combination.rank }}</a></div>
<div class="col-3 text-center">Age Boy : <a href="#">{{ combination.age_boy_masterised }}</a></div>
<div class="col-3 text-center">Age Girl : <a href="#">{{ combination.age_girl_masterised }}</a></div>
</div>
{{ combination_string }}
{% else %}
<p>No skill defined for this combination.</p>
{% endif %}
</div>
{% if combination.informations %}
<div class="col-md-12">
<hr class="m-t">
<h4>Informations</h4>
<!-- <p>{{ skill.educative }}</p> -->
<span id="comment">
{{ combination.to_markdown | safe }}
</span>
</div>
{% endif %}
<div class="card-footer row pt-0">
<div class="col-6">
<a href="{% url 'routine_listing' %}">
<button type="submit" value="add" class="btn btn-icon btn-warning ">
<i class="tim-icons icon-double-left"></i>
</button>
</a>
</div>
<div class="col-6 text-right">
{% if request.user|has_group:"trainer" %}
<a href="{% url 'compose_combination' combination.id %}">
<button type="submit" value="add" class="btn btn-icon btn-warning ">
<i class="tim-icons icon-molecule-40"></i>
</button>
</a>
<a href="{% url 'combination_update' combination.id %}">
<button type="submit" value="add" class="btn btn-icon btn-warning ">
<i class="tim-icons icon-pencil"></i>
</button>
</a>
{% endif %}
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,73 +1,42 @@
{% extends "listing.html" %} {% extends "listing.html" %}
{% load has_group %}
{% block datacontent %} {% block datacontent %}
<div class="card mb-0"> <div class="card mb-0">
<div class="card-header"> <div class="card-header">
<div class="row"> <div class="row">
<div class="col-8"> <div class="col-8">
<h4 class=""> {{ title }} Listing {% if gymnast_id %}for <i>{{ gymnast }}</i>{% endif %}</h4> <h4 class=""> Passes Listing</h4>
</div> </div>
<div class="col-1 ml-auto"> <div class="col-1 ml-auto">
<div class="text-right">
{% if request.user|has_group:"trainer" %}
<a href="{% url 'combination_create' %}">
<button type="submit" value="add" class="btn btn-icon btn-warning mb-0">
<i class="fas fa-plus"></i>
</button>
</a>
{% endif %}
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="table-responsive"> <div class="table-responsive">
{% if routine_list %} {% if passes_list %}
<table class="table tablesorter table-striped" data-sort="table" id="routine_table"> <table class="table tablesorter table-striped" data-sort="table" id="routine_table">
<thead> <thead>
<tr> <tr>
{% if request.user|has_group:"trainer" %} <th class="text-center" style="width: 10%">label</th>
<th style="width: 3%"></th> <th class="header text-center" style="width: 7%">educative</th>
{% endif %} <th class="header text-center" style="width: 7%">repetition</th>
<th class="header text-left" style="width: 35%">&nbsp;Long Label</th> <th class="header text-center" style="width: 7%">regexp</th>
<th class="header text-left" style="width: 20%">&nbsp;Short Label</th> </tr>
<th class="text-center" style="width: 10%">Competitive ?</th> </thead>
<th class="header text-center"><i class="far fa-venus"></i></th> <tbody>
<th class="header text-center"><i class="far fa-mars"></i></th> {% for passe in passes_list %}
<th class="header text-center" style="width: 7%">Diff.</th> <tr role="row" class="{% cycle 'odd' 'even' %}">
<th class="header text-center" style="width: 7%">Level</th> <td class="text-center">{{ passe.label }}</td>
<th class="header text-center" style="width: 7%">Rank</th> <td class="text-center">{{ passe.educative }}</td>
</tr> <td class="text-center">{{ passe.repetition }}</td>
</thead> <td class="text-center">{{ passe.regexp }}</td>
<tbody> </tr>
{% for routine in routine_list %} {% endfor %}
<tr role="row" class="{% cycle 'odd' 'even' %}"> </tbody>
{% if request.user|has_group:"trainer" %} </table>
<td>
<a href="{% url 'combination_update' routine.id %}">
<span class="tim-icons icon-pencil text-warning"></span>
</a>
</td>
{% endif %}
<td class="text-left"><a href="{% url 'combination_details' routine.id %}">{{ routine.long_label }}</a></td>
<td class="text-left"><a href="{% url 'combination_details' routine.id %}">{{ routine.short_label }}</a></td>
<td class="text-center">
{% if routine.is_competitive %}<i class="fa fa-check text-success" aria-hidden="true"></i>
{% else %}<i class="fa fa-times text-danger" aria-hidden="true"></i>
{% endif %}
</td>
<td class="text-center">{{ routine.age_girl_masterised }}</td>
<td class="text-center">{{ routine.age_boy_masterised }}</td>
<td class="text-center">{{ routine.difficulty }}</td>
<td class="text-center">{{ routine.level }}</td>
<td class="text-center">{{ routine.rank }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %} {% else %}
<p class="muted-text">There are no {{ title|lower }} corresponding to your criterias.</p> <p class="muted-text">There are no passe corresponding to your criterias.</p>
{% endif %} {% endif %}
</div> </div>
</div> </div>
@ -76,26 +45,26 @@
{% block footerscript %} {% block footerscript %}
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { // $(document).ready(function () {
$('routine_table').tablesorter({ // $('routine_table').tablesorter({
{% if request.user|has_group:"trainer" %} // {% if request.user|has_group:"trainer" %}
headers: { // headers: {
0: { sorter: false }, // 0: { sorter: false },
}, // },
sortList: [[1, 0]], // sortList: [[1, 0]],
{% else %} // {% else %}
sortList: [[0, 0]], // sortList: [[0, 0]],
{% endif %} // {% endif %}
}); // });
$('#routine_table').DataTable({ // $('#routine_table').DataTable({
scrollY: '50vh', // scrollY: '50vh',
scrollCollapse: true, // scrollCollapse: true,
paging: false, // paging: false,
searching: false, // searching: false,
ordering: false, // ordering: false,
"bInfo": false, // "bInfo": false,
}); // });
}); // });
</script> </script>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,29 @@
{% extends "base.html" %}
{% load has_group %}
{% block page_title %}{{ combination.short_label }}{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-12 col-sm-12 col-md-8 col-lg-8 col-xl-6">
<div class="card">
<div class="card-body">
{% if trainingprogram_list %}
<table>
<thead>
<td colspan="3" class="text-center">--DATE--</td>
</thead>
{% for trainingprogram in trainingprogram_list %}
<tr>
<td>{{ trainingprogram.passe.label }} {{ trainingprogram.passe.repetition }}</td>
<td><b>{{ trainingprogram.passe.number_of_skill}}</b></td>
<td>{{ trainingprogram.passe.difficulty }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -3,6 +3,10 @@ from . import views
urlpatterns = [ urlpatterns = [
#
#
#
path(r"educative/lookup/", views.educative_lookup, name="educative_lookup"),
# #
# SKILLS # SKILLS
# #
@ -85,4 +89,14 @@ urlpatterns = [
# #
path(r"passe/<int:passe_id>/", views.passe_details, name="passe_details"), path(r"passe/<int:passe_id>/", views.passe_details, name="passe_details"),
path(r"passe/", views.passe_listing, name="passe_listing"), 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/<int:passe_id>/",
views.passe_create_or_update,
name="passe_update",
),
] ]

View File

@ -9,6 +9,7 @@ from jarvis.people.models import Gymnast
from .forms import ( from .forms import (
SkillForm, SkillForm,
PasseForm,
CombinationForm, CombinationForm,
CombinationSkillForm, CombinationSkillForm,
) )
@ -16,11 +17,35 @@ from .models import (
Skill, Skill,
Passe, Passe,
Routine, Routine,
Educative,
RoutineSkill, RoutineSkill,
PrerequisiteClosure, 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 @login_required
@require_http_methods(["POST"]) @require_http_methods(["POST"])
def skill_lookup(request): def skill_lookup(request):
@ -486,9 +511,78 @@ def passe_details(request, passe_id):
"""Détails d'un passage.""" """Détails d'un passage."""
passe = get_object_or_404(Passe, pk=passe_id) 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 = { context = {
"passe": passe, "passe": passe,
"is_skill": is_skill,
"educative": educative, "educative": educative,
"difficulty": difficulty,
"number_of_skill": number_of_skill,
} }
return render(request, "passes/details.html", context) 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 <Passe>.
"""
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)