feat: add 7j view mode to team planning
This commit is contained in:
parent
40ce03d812
commit
5e9fced68f
3 changed files with 45 additions and 10 deletions
|
|
@ -726,9 +726,10 @@
|
|||
<div class="d-flex align-items-center gap-1">
|
||||
<span class="text-muted small text-nowrap"><i class="bi bi-eye me-1"></i>{% trans "Vue :" %}</span>
|
||||
<div class="btn-group btn-group-sm" role="group" id="planning-viewmode-group">
|
||||
<button type="button" class="btn btn-outline-primary" data-mode="work_week">{% trans "5j (Ouvré)" %}</button>
|
||||
<button type="button" class="btn btn-primary" data-mode="week">{% trans "Semaine" %}</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-mode="month">{% trans "Mois" %}</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-mode="work_week" title="{% trans "Semaine de travail de 5 jours (du lundi au vendredi)" %}">{% trans "5j (Ouvré)" %}</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-mode="days_7" title="{% trans "Semaine complète de 7 jours (avec week-end)" %}">{% trans "7j" %}</button>
|
||||
<button type="button" class="btn btn-primary" data-mode="week" title="{% trans "Vue par semaine (5 semaines glissantes)" %}">{% trans "Semaine" %}</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-mode="month" title="{% trans "Vue par mois (6 mois glissants)" %}">{% trans "Mois" %}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -1650,7 +1651,7 @@ const initialDate = (function() {
|
|||
|
||||
const initialViewMode = (function() {
|
||||
const saved = getStoredSetting('view_mode', 'week');
|
||||
if (['work_week', 'week', 'two_weeks', 'month'].includes(saved)) return saved;
|
||||
if (['work_week', 'days_7', '7_days', 'week', 'two_weeks', 'month'].includes(saved)) return saved;
|
||||
return 'week';
|
||||
})();
|
||||
|
||||
|
|
@ -1719,7 +1720,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
loadPlanningData();
|
||||
});
|
||||
|
||||
// Changement de mode de vue (5j / Semaine / Mois)
|
||||
// Changement de mode de vue (5j / 7j / Semaine / Mois)
|
||||
$('#planning-viewmode-group button').on('click', function() {
|
||||
$('#planning-viewmode-group button').removeClass('btn-primary').addClass('btn-outline-primary');
|
||||
$(this).removeClass('btn-outline-primary').addClass('btn-primary');
|
||||
|
|
@ -1736,7 +1737,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
setStoredSetting('assign_scope', 'week');
|
||||
$('#planning-assign-scope-group button').removeClass('btn-primary').addClass('btn-outline-primary');
|
||||
$('#planning-assign-scope-group button[data-scope="week"]').removeClass('btn-outline-primary').addClass('btn-primary');
|
||||
} else if (_planningState.viewMode === 'work_week') {
|
||||
} else if (_planningState.viewMode === 'work_week' || _planningState.viewMode === 'days_7' || _planningState.viewMode === '7_days') {
|
||||
_planningState.assignScope = 'day';
|
||||
setStoredSetting('assign_scope', 'day');
|
||||
$('#planning-assign-scope-group button').removeClass('btn-primary').addClass('btn-outline-primary');
|
||||
|
|
@ -1941,10 +1942,12 @@ function renderPlanningMatrix(data) {
|
|||
quickDupTitle = "{% trans 'Dupliquer vers le mois suivant (avec absences)'|escapejs %}";
|
||||
optionsTitle = "{% trans 'Options du mois'|escapejs %}";
|
||||
dupCustomTitle = "{% trans 'Dupliquer ce mois…'|escapejs %}";
|
||||
} else if (_planningState.viewMode === 'work_week') {
|
||||
} else if (_planningState.viewMode === 'work_week' || _planningState.viewMode === 'days_7' || _planningState.viewMode === '7_days') {
|
||||
const dParts = day.date.split('-');
|
||||
const dateObj = new Date(parseInt(dParts[0], 10), parseInt(dParts[1], 10) - 1, parseInt(dParts[2], 10));
|
||||
if (dateObj.getDay() === 5) {
|
||||
if (_planningState.viewMode === 'work_week' && dateObj.getDay() === 5) {
|
||||
quickDupTitle = "{% trans 'Dupliquer vers le lundi suivant (avec absences)'|escapejs %}";
|
||||
} else if (dateObj.getDay() === 0) {
|
||||
quickDupTitle = "{% trans 'Dupliquer vers le lundi suivant (avec absences)'|escapejs %}";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -622,6 +622,18 @@ class TeamPlanningAjaxViewsTests(TestCase):
|
|||
self.assertEqual(len(data['days']), 5)
|
||||
self.assertEqual(data['days'][0]['col_type'], 'day')
|
||||
|
||||
def test_planning_data_ajax_days_7_view(self):
|
||||
"""Tester le retour du mode 'days_7' (7 jours complets avec week-end) dans team_planning_data_ajax."""
|
||||
url = reverse('contracts:team_planning_data_ajax')
|
||||
response = self.client.get(url, {'date': '2026-09-02', 'view_mode': 'days_7'})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data = response.json()
|
||||
self.assertEqual(len(data['days']), 7)
|
||||
self.assertEqual(data['days'][0]['col_type'], 'day')
|
||||
self.assertFalse(data['days'][0]['is_weekend']) # Lundi
|
||||
self.assertTrue(data['days'][5]['is_weekend']) # Samedi
|
||||
self.assertTrue(data['days'][6]['is_weekend']) # Dimanche
|
||||
|
||||
def test_planning_assign_member_ajax_week_scope(self):
|
||||
"""Tester l'assignation avec portée 'week' via l'API AJAX."""
|
||||
# Prendre un lundi dans le futur
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ def team_planning_data_ajax(request):
|
|||
Retourne la matrice complète de planification des équipes sur une période.
|
||||
Paramètres GET :
|
||||
- date : date d'ancrage (YYYY-MM-DD), par défaut aujourd'hui
|
||||
- view_mode : 'week' (7j, défaut), 'two_weeks' (14j), 'work_week' (5j)
|
||||
- view_mode : 'work_week' (5j), 'days_7' (7j), 'week' (5 semaines), 'month' (6 mois), 'two_weeks' (14j)
|
||||
- company_id : filtrer sur une société spécifique (optionnel)
|
||||
"""
|
||||
if not user_can_view_teams(request.user):
|
||||
|
|
@ -477,6 +477,24 @@ def team_planning_data_ajax(request):
|
|||
'is_weekend': False,
|
||||
'col_type': 'day',
|
||||
})
|
||||
elif view_mode in ('days_7', '7_days'):
|
||||
num_days = 7
|
||||
start_date = monday
|
||||
end_date = monday + timedelta(days=6)
|
||||
for i in range(num_days):
|
||||
d = start_date + timedelta(days=i)
|
||||
w_idx = d.weekday()
|
||||
days_list.append({
|
||||
'date': d.isoformat(),
|
||||
'day_name': DAYS_FR_FULL[w_idx],
|
||||
'day_short': DAYS_FR_SHORT[w_idx],
|
||||
'day_num': f"{d.day:02d}/{d.month:02d}",
|
||||
'formatted': f"{DAYS_FR_SHORT[w_idx]} {d.day:02d} {MONTHS_FR[d.month]}",
|
||||
'is_today': d == today,
|
||||
'is_past': d < today,
|
||||
'is_weekend': w_idx >= 5,
|
||||
'col_type': 'day',
|
||||
})
|
||||
elif view_mode == 'two_weeks':
|
||||
num_days = 14
|
||||
start_date = monday
|
||||
|
|
@ -643,13 +661,15 @@ def team_planning_data_ajax(request):
|
|||
})
|
||||
|
||||
# 7. Structurer les membres pour le volet latéral (Sidebar)
|
||||
if view_mode == 'week':
|
||||
if view_mode in ('week', 'days_7', '7_days'):
|
||||
absent_member_ids = {mid for (mid, d) in absences.keys() if monday <= d <= monday + timedelta(days=6)}
|
||||
elif view_mode == 'month':
|
||||
_, d_in_m = calendar.monthrange(anchor_date.year, anchor_date.month)
|
||||
m_s = date(anchor_date.year, anchor_date.month, 1)
|
||||
m_e = date(anchor_date.year, anchor_date.month, d_in_m)
|
||||
absent_member_ids = {mid for (mid, d) in absences.keys() if m_s <= d <= m_e}
|
||||
elif view_mode == 'work_week':
|
||||
absent_member_ids = {mid for (mid, d) in absences.keys() if monday <= d <= monday + timedelta(days=4)}
|
||||
else:
|
||||
absent_member_ids = {mid for (mid, d) in absences.keys() if d == anchor_date}
|
||||
members_data = []
|
||||
|
|
|
|||
Loading…
Reference in a new issue