Update passe form, migrations, …
This commit is contained in:
parent
b026edbb27
commit
51ac7fc5fb
|
@ -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",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
|
@ -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,
|
||||||
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -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,
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 }} {% if form.long_label.errors %}
|
{{ form.long_label }} {% 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 }} {% 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 }} {% 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 }} {% 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 }} {% 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 }} {% 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 }} {% 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>
|
||||||
|
|
|
@ -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 %} <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 %} <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 %} <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 %} <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 %}
|
|
@ -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> {{ 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>
|
||||||
|
|
|
@ -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%"> Long Label</th>
|
<th class="header text-center" style="width: 7%">regexp</th>
|
||||||
<th class="header text-left" style="width: 20%"> 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 %}
|
|
@ -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 %}
|
|
@ -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",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue