Améliorer les couleurs et la vue du calendrier
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run
This commit is contained in:
parent
3527adb175
commit
84b4f1326c
2 changed files with 44 additions and 16 deletions
|
|
@ -23,10 +23,22 @@ def index():
|
||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
from calendar import monthrange
|
from calendar import monthrange
|
||||||
from ..core.services.planning_service import PlanningService
|
from ..core.services.planning_service import PlanningService
|
||||||
from ..core.models.planning import PlanningDay, PlanningItem
|
from ..core.models.planning import PlanningDay, PlanningItem, ClosureWorkDay
|
||||||
|
from ..core.models.settings import AppSettings
|
||||||
|
from ..core.services.planning_service import get_french_public_holidays
|
||||||
|
|
||||||
# Récupérer l'année demandée ou année courante
|
# Récupérer l'année demandée ou année courante
|
||||||
|
mode = request.args.get('mode')
|
||||||
|
saved_mode = AppSettings.get(f'planning_calendar_mode_{current_user.id}', 'calendar')
|
||||||
|
if mode not in ('calendar', 'school'):
|
||||||
|
mode = saved_mode if saved_mode in ('calendar', 'school') else 'calendar'
|
||||||
|
else:
|
||||||
|
AppSettings.set(f'planning_calendar_mode_{current_user.id}', mode)
|
||||||
year = request.args.get('year', date.today().year, type=int)
|
year = request.args.get('year', date.today().year, type=int)
|
||||||
|
if mode == 'school' and 'year' not in request.args:
|
||||||
|
year = date.today().year if date.today().month >= 9 else date.today().year - 1
|
||||||
|
display_start = date(year, 9, 1) if mode == 'school' else date(year, 1, 1)
|
||||||
|
display_end = date(year + 1, 8, 31) if mode == 'school' else date(year, 12, 31)
|
||||||
|
|
||||||
# Préparer les données du calendrier. Le calendrier principal est la
|
# Préparer les données du calendrier. Le calendrier principal est la
|
||||||
# source unique : il rassemble les interventions et les échéances
|
# source unique : il rassemble les interventions et les échéances
|
||||||
|
|
@ -37,9 +49,13 @@ def index():
|
||||||
|
|
||||||
# Récupérer les vacances
|
# Récupérer les vacances
|
||||||
closures = CollegeClosure.query.filter(
|
closures = CollegeClosure.query.filter(
|
||||||
CollegeClosure.start_date <= date(year, 12, 31),
|
CollegeClosure.start_date <= display_end,
|
||||||
CollegeClosure.end_date >= date(year, 1, 1)
|
CollegeClosure.end_date >= display_start
|
||||||
).all()
|
).all()
|
||||||
|
permanence_dates = {item.work_date for item in ClosureWorkDay.query.filter(ClosureWorkDay.work_date >= display_start, ClosureWorkDay.work_date <= display_end).all()}
|
||||||
|
holiday_dates = {item[0] for item in get_french_public_holidays(year)}
|
||||||
|
if mode == 'school':
|
||||||
|
holiday_dates |= {item[0] for item in get_french_public_holidays(year + 1)}
|
||||||
|
|
||||||
# Fonction pour vérifier si une date est en vacances
|
# Fonction pour vérifier si une date est en vacances
|
||||||
def is_vacation(d):
|
def is_vacation(d):
|
||||||
|
|
@ -50,13 +66,13 @@ def index():
|
||||||
|
|
||||||
# Récupérer les congés personnels
|
# Récupérer les congés personnels
|
||||||
leaves = TechnicianAvailability.query.filter(
|
leaves = TechnicianAvailability.query.filter(
|
||||||
TechnicianAvailability.date >= date(year, 1, 1),
|
TechnicianAvailability.date >= display_start,
|
||||||
TechnicianAvailability.date <= date(year, 12, 31)
|
TechnicianAvailability.date <= display_end
|
||||||
).all()
|
).all()
|
||||||
leave_dates = {l.date: l for l in leaves}
|
leave_dates = {l.date: l for l in leaves}
|
||||||
|
|
||||||
year_start = date(year, 1, 1)
|
year_start = display_start
|
||||||
year_end = date(year, 12, 31)
|
year_end = display_end
|
||||||
terminal_intervention_statuses = ('terminee', 'cloturee', 'annulee', 'ignoree')
|
terminal_intervention_statuses = ('terminee', 'cloturee', 'annulee', 'ignoree')
|
||||||
interventions = Intervention.query.filter(
|
interventions = Intervention.query.filter(
|
||||||
Intervention.scheduled_date >= year_start,
|
Intervention.scheduled_date >= year_start,
|
||||||
|
|
@ -108,18 +124,20 @@ def index():
|
||||||
'color': 'info',
|
'color': 'info',
|
||||||
})
|
})
|
||||||
|
|
||||||
for month in range(1, 13):
|
month_order = list(range(9, 13)) + list(range(1, 9)) if mode == 'school' else list(range(1, 13))
|
||||||
|
for month in month_order:
|
||||||
|
actual_year = year if mode != 'school' or month >= 9 else year + 1
|
||||||
# Nombre de jours dans le mois
|
# Nombre de jours dans le mois
|
||||||
days_in_month = monthrange(year, month)[1]
|
days_in_month = monthrange(actual_year, month)[1]
|
||||||
|
|
||||||
# Jour de la semaine du premier jour (0=lundi, 6=dimanche)
|
# Jour de la semaine du premier jour (0=lundi, 6=dimanche)
|
||||||
first_weekday = date(year, month, 1).weekday()
|
first_weekday = date(actual_year, month, 1).weekday()
|
||||||
|
|
||||||
weeks = []
|
weeks = []
|
||||||
week = [None] * first_weekday # Cases vides avant le 1er jour
|
week = [None] * first_weekday # Cases vides avant le 1er jour
|
||||||
|
|
||||||
for day in range(1, days_in_month + 1):
|
for day in range(1, days_in_month + 1):
|
||||||
d = date(year, month, day)
|
d = date(actual_year, month, day)
|
||||||
vacation = is_vacation(d)
|
vacation = is_vacation(d)
|
||||||
leave = leave_dates.get(d)
|
leave = leave_dates.get(d)
|
||||||
weekday = d.weekday()
|
weekday = d.weekday()
|
||||||
|
|
@ -130,6 +148,8 @@ def index():
|
||||||
'is_weekend': weekday >= 5,
|
'is_weekend': weekday >= 5,
|
||||||
'is_vacation': vacation is not None,
|
'is_vacation': vacation is not None,
|
||||||
'vacation_name': vacation,
|
'vacation_name': vacation,
|
||||||
|
'is_holiday': d in holiday_dates,
|
||||||
|
'is_permanence': d in permanence_dates,
|
||||||
'is_leave': leave is not None,
|
'is_leave': leave is not None,
|
||||||
'leave_type': leave.availability_type if leave else None,
|
'leave_type': leave.availability_type if leave else None,
|
||||||
'events': events_by_date.get(d, []),
|
'events': events_by_date.get(d, []),
|
||||||
|
|
@ -145,6 +165,7 @@ def index():
|
||||||
|
|
||||||
months_data.append({
|
months_data.append({
|
||||||
'name': months_names[month - 1],
|
'name': months_names[month - 1],
|
||||||
|
'year': actual_year,
|
||||||
'weeks': weeks
|
'weeks': weeks
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -158,6 +179,7 @@ def index():
|
||||||
|
|
||||||
return render_template('planning/calendar.html',
|
return render_template('planning/calendar.html',
|
||||||
year=year,
|
year=year,
|
||||||
|
mode=mode,
|
||||||
months=months_data,
|
months=months_data,
|
||||||
stats=stats
|
stats=stats
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<h1><i class="bi bi-calendar3 me-2"></i>Planning {{ year }}</h1>
|
<h1><i class="bi bi-calendar3 me-2"></i>Planning {% if mode == 'school' %}{{ year }}–{{ year + 1 }}{% else %}{{ year }}{% endif %}</h1>
|
||||||
<div>
|
<div>
|
||||||
<a href="{{ url_for('planning.index', year=year-1) }}" class="btn btn-outline-secondary">
|
<a href="{{ url_for('planning.index', year=year-1) }}" class="btn btn-outline-secondary">
|
||||||
<i class="bi bi-chevron-left"></i> {{ year-1 }}
|
<i class="bi bi-chevron-left"></i> {{ year-1 }}
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
<a href="{{ url_for('planning.index', year=year+1) }}" class="btn btn-outline-secondary">
|
<a href="{{ url_for('planning.index', year=year+1) }}" class="btn btn-outline-secondary">
|
||||||
{{ year+1 }} <i class="bi bi-chevron-right"></i>
|
{{ year+1 }} <i class="bi bi-chevron-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
<div class="btn-group ms-2"><a href="{{ url_for('planning.index', year=year, mode='calendar') }}" class="btn btn-outline-primary {% if mode == 'calendar' %}active{% endif %}">Année civile</a><a href="{{ url_for('planning.index', year=year, mode='school') }}" class="btn btn-outline-primary {% if mode == 'school' %}active{% endif %}">Année scolaire</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -61,7 +62,8 @@
|
||||||
<div class="d-flex flex-wrap gap-3">
|
<div class="d-flex flex-wrap gap-3">
|
||||||
<span><span class="badge bg-secondary">Week-end</span></span>
|
<span><span class="badge bg-secondary">Week-end</span></span>
|
||||||
<span><span class="badge bg-dark">Vacances</span></span>
|
<span><span class="badge bg-dark">Vacances</span></span>
|
||||||
<span><span class="badge bg-warning text-dark">Congé</span></span>
|
<span><span class="badge bg-warning text-dark">Jour férié</span></span>
|
||||||
|
<span><span class="badge" style="background:#b7e4c7;color:#14532d;">Permanence</span></span>
|
||||||
<span><span class="badge bg-primary">Intervention</span></span>
|
<span><span class="badge bg-primary">Intervention</span></span>
|
||||||
<span><span class="badge bg-info text-dark">Échéance préventive</span></span>
|
<span><span class="badge bg-info text-dark">Échéance préventive</span></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -76,7 +78,7 @@
|
||||||
<div class="col-lg-4 col-md-6 mb-4">
|
<div class="col-lg-4 col-md-6 mb-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-center">
|
<div class="card-header text-center">
|
||||||
<strong>{{ month.name }}</strong>
|
<strong>{{ month.name }} {{ month.year }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-1">
|
<div class="card-body p-1">
|
||||||
<table class="table table-sm table-bordered mb-0" style="font-size: 0.8rem;">
|
<table class="table table-sm table-bordered mb-0" style="font-size: 0.8rem;">
|
||||||
|
|
@ -95,14 +97,18 @@
|
||||||
<td class="bg-light"></td>
|
<td class="bg-light"></td>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set td_class = '' %}
|
{% set td_class = '' %}
|
||||||
{% if day_info.is_vacation %}
|
{% if day_info.is_permanence %}
|
||||||
|
{% set td_class = 'table-success' %}
|
||||||
|
{% elif day_info.is_holiday %}
|
||||||
|
{% set td_class = 'table-warning' %}
|
||||||
|
{% elif day_info.is_vacation %}
|
||||||
{% set td_class = 'table-dark' %}
|
{% set td_class = 'table-dark' %}
|
||||||
{% elif day_info.is_leave %}
|
{% elif day_info.is_leave %}
|
||||||
{% set td_class = 'table-warning' %}
|
{% set td_class = 'table-warning' %}
|
||||||
{% elif day_info.is_weekend %}
|
{% elif day_info.is_weekend %}
|
||||||
{% set td_class = 'table-secondary' %}
|
{% set td_class = 'table-secondary' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td class="{{ td_class }} text-center">
|
<td class="{{ td_class }} text-center" title="{% if day_info.is_permanence %}Permanence{% elif day_info.is_holiday %}Jour férié{% elif day_info.vacation_name %}{{ day_info.vacation_name }}{% endif %}">
|
||||||
{% set date_str = day_info.date.strftime('%Y-%m-%d') %}
|
{% set date_str = day_info.date.strftime('%Y-%m-%d') %}
|
||||||
<a href="{{ url_for('planning.day', date_str=date_str) }}"
|
<a href="{{ url_for('planning.day', date_str=date_str) }}"
|
||||||
class="text-decoration-none {{ 'text-white' if td_class else '' }}"
|
class="text-decoration-none {{ 'text-white' if td_class else '' }}"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue