Add in the generated PDF
This commit is contained in:
parent
a3123d469f
commit
4237a957dd
|
@ -47,6 +47,12 @@
|
|||
{% if form.learning_step.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.learning_step.errors %}{{error}}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_information" class="col-4 col-sm-3 col-form-label">Points of attention</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-fill btn-warning" />
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{% 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 skill_id %}Edit{% else %}Add{% endif %} Skill informations</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{% if skill_id %}{% url 'skill_update' skill_id %}{% else %}{% url 'skill_create' %}{% endif %}" method="post" class="form-horizontal" id="formulaire" name="formulaire">
|
||||
{% csrf_token %}
|
||||
<div class="form-group row ">
|
||||
<label for="id_information" 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 %}
|
|
@ -97,7 +97,10 @@
|
|||
{% if skill.twist %}
|
||||
with <a href="#">{{ skill.twist }} half-twist</a>
|
||||
{% endif %}
|
||||
in a <a href="#">{{ skill.get_position_display }}</a> position, landing on <a href="#">{{ skill.landing }}</a>.
|
||||
{% if skill.get_position_display %}
|
||||
in a <a href="#">{{ skill.get_position_display }}</a> position
|
||||
{% endif %}
|
||||
, landing on <a href="#">{{ skill.landing }}</a>.
|
||||
</p>
|
||||
<br />
|
||||
{% if skill.informations %}
|
||||
|
@ -105,13 +108,17 @@
|
|||
{% else %}
|
||||
<p class="text-muted">No more informations provided for this skill.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer pt-0 row">
|
||||
<div class="col-md-12 text-right">
|
||||
<a href="{% url 'skill_update' skill.id %}">
|
||||
<span class="tim-icons icon-pencil text-warning"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -107,8 +107,12 @@
|
|||
</td>
|
||||
{% endif %}
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td>{{ skill.plan_date | date:"d-m-Y" }}</td>
|
||||
<td class="text-left">
|
||||
<a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ skill.plan_date | date:"d-m-Y" }}
|
||||
</td>
|
||||
<td>{{ skill.difficulty }}</td>
|
||||
<td>{{ skill.level }}</td>
|
||||
<td>{{ skill.rank }}</td>
|
||||
|
|
|
@ -441,7 +441,7 @@ class PlanForm(forms.ModelForm):
|
|||
|
||||
class Meta:
|
||||
model = Plan
|
||||
fields = ("date", "gymnast", "educative", "learning_step", "is_done")
|
||||
fields = ("date", "gymnast", "educative", "learning_step", "is_done", "informations")
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"educative": forms.HiddenInput(),
|
||||
|
@ -456,6 +456,12 @@ class PlanForm(forms.ModelForm):
|
|||
"is_done": forms.CheckboxInput(
|
||||
attrs={"class": "form-control form-check-input ml-0 mt-0"}
|
||||
),
|
||||
"informations": forms.Textarea(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Informations about gymnast for this particular skill: usual mistake, fear, …", # pylint: disable=line-too-long
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-16 06:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0028_rename_cando_learnedskill_learning_step_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="plan",
|
||||
name="informations",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Only MarkDown is authorized",
|
||||
null=True,
|
||||
verbose_name="Comments",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -169,7 +169,7 @@ class LearnedSkill(Seasonisable):
|
|||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
|
||||
class Plan(Seasonisable):
|
||||
class Plan(Seasonisable, Markdownizable):
|
||||
"""
|
||||
Classe représentant les objectifs qu'un gymnaste devra savoir faire pour une date donnée.
|
||||
"""
|
||||
|
@ -206,6 +206,9 @@ class Plan(Seasonisable):
|
|||
self.date,
|
||||
)
|
||||
|
||||
# @property
|
||||
# def is_due(self):
|
||||
# return pendulum.now().date() > self.date
|
||||
|
||||
class Point(models.Model):
|
||||
"""
|
||||
|
|
|
@ -91,6 +91,10 @@ class Seasonisable(models.Model):
|
|||
self.season, self.week_number = from_date_to_week_number(self.date)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
# @property
|
||||
# def is_past(self):
|
||||
# return pendulum.now().date() > self.date
|
||||
|
||||
|
||||
class TemporizableQuerySet(models.QuerySet):
|
||||
"""
|
||||
|
|
|
@ -44,7 +44,7 @@ environ.Env.read_env()
|
|||
|
||||
X = 35
|
||||
Y = 841.89
|
||||
INDENT = 5
|
||||
INDENT = 15
|
||||
RIGHT_X = 595.27 - X
|
||||
TITLED_X = 125
|
||||
INDENTED_X = X + INDENT
|
||||
|
@ -85,6 +85,12 @@ class PDFDocument(object):
|
|||
self.mobile_phone = env("MOBILE_PHONE", default=None)
|
||||
self.coach_email = env("HEAD_COACH_EMAIL", default=None)
|
||||
|
||||
def new_page(self):
|
||||
""" """
|
||||
# self.y = Y - X
|
||||
self.document.showPage()
|
||||
self.y = Y - X
|
||||
|
||||
def add_vspace(self, height=COMMON_LINE_HEIGHT):
|
||||
""" Passe à la ligne, la hauteur de la ligne étant passée en paramètre.
|
||||
|
||||
|
@ -190,11 +196,16 @@ class GymnastReportDocument(PDFDocument):
|
|||
self.add_gymnast_best_scores(gymnast)
|
||||
self.add_gymnast_active_routine(gymnast)
|
||||
# self.add_gymnast_level_information(gymnast)
|
||||
self.add_gymnast_next_skills(gymnast)
|
||||
planned_skill = self.add_gymnast_planned_skill(gymnast)
|
||||
print(planned_skill)
|
||||
self.add_gymnast_last_learned_skill(gymnast)
|
||||
self.add_gymnast_next_events(gymnast)
|
||||
self.add_gymnast_week_notes(gymnast)
|
||||
|
||||
if planned_skill:
|
||||
self.new_page()
|
||||
self.add_planned_skills_details(planned_skill)
|
||||
|
||||
def add_gymnast_personnal_information(self, gymnast):
|
||||
""" Ajoute les informations personnelles du gymnast.
|
||||
|
||||
|
@ -563,7 +574,7 @@ class GymnastReportDocument(PDFDocument):
|
|||
)
|
||||
|
||||
|
||||
def add_gymnast_next_skills(self, gymnast):
|
||||
def add_gymnast_planned_skill(self, gymnast):
|
||||
""" Ajoute les prochains skill (skill planifié) à apprendre
|
||||
|
||||
Args:
|
||||
|
@ -584,27 +595,29 @@ class GymnastReportDocument(PDFDocument):
|
|||
# le double F ne fonctionne qu'en précisant le distinct, sinon ca dédouble les résultats.
|
||||
# qui lui même ne fonctionne que sur un champ présent dans le `order_by` (que le premier champ ?)
|
||||
#
|
||||
planified_skills = (
|
||||
planned_skills = (
|
||||
Skill.objects.filter(plan__gymnast=gymnast.id)
|
||||
.filter(
|
||||
Q(plan__is_done=False)
|
||||
| Q(plan__date__gte=date.today())
|
||||
)
|
||||
# .annotate(plan_date=F("plan__date"))
|
||||
.annotate(plan_date=F("plan__date"), learning_step=F("plan__learning_step"))
|
||||
.order_by("notation", "-plan__date").distinct('notation')[:6]
|
||||
.annotate(plan_date=F("plan__date"), learning_step=F("plan__learning_step"), plan_id=F("plan__id"))
|
||||
.order_by("id", "-plan__date").distinct('id')[:6]
|
||||
)
|
||||
|
||||
if planified_skills:
|
||||
for planified_skill in planified_skills:
|
||||
if planned_skills:
|
||||
for planned_skill in planned_skills:
|
||||
self.add_new_line(
|
||||
X, planified_skill.short_label + " " + str(LEARNING_STEP_CHOICES[planified_skill.learning_step][1]).lower() + " (" + planified_skill.notation + ") for " + planified_skill.plan_date.strftime("%d-%m-%Y")
|
||||
X, planned_skill.short_label + " " + str(LEARNING_STEP_CHOICES[planned_skill.learning_step][1]).lower() + " (" + planned_skill.notation + ") for " + planned_skill.plan_date.strftime("%d-%m-%Y")
|
||||
)
|
||||
else:
|
||||
self.add_new_line(
|
||||
X,
|
||||
"No next skill to learn plannified.",
|
||||
)
|
||||
print(planned_skills)
|
||||
return planned_skills
|
||||
|
||||
def add_gymnast_next_events(self, gymnast):
|
||||
""" Ajoute les évènements futurs du gymnaste """
|
||||
|
@ -678,3 +691,27 @@ class GymnastReportDocument(PDFDocument):
|
|||
X,
|
||||
"No note associated to this gymnast this week.",
|
||||
)
|
||||
|
||||
def add_planned_skills_details(self, planned_skills):
|
||||
""" """
|
||||
# self.y = 20*cm
|
||||
self.add_new_line(
|
||||
X,
|
||||
"Points of attention",
|
||||
font_decoration="Bold",
|
||||
)
|
||||
self.add_vspace(-0.5*cm)
|
||||
|
||||
for planned_skill in planned_skills:
|
||||
plan = Plan.objects.get(pk=planned_skill.plan_id)
|
||||
|
||||
html_text = "<u>" + planned_skill.short_label + " (" + planned_skill.notation + ") :</u>"
|
||||
paragraph = Paragraph(html_text, self.style)
|
||||
width, height = paragraph.wrap(18*cm, 10*cm)
|
||||
paragraph.drawOn(self.document, INDENTED_X, self.y - (height / 2))
|
||||
|
||||
self.add_new_line(
|
||||
INDENTED_X,
|
||||
plan.informations
|
||||
)
|
||||
self.add_vspace(-0.4*cm)
|
||||
|
|
Loading…
Reference in New Issue