diff --git a/gen_cons.py b/gen_cons.py index 6fb2739..c29b2cb 100644 --- a/gen_cons.py +++ b/gen_cons.py @@ -350,7 +350,7 @@ def main( assign_as_block=False, constraints=[ PreShiftConstraint(days=2, start_date="2025-11-17", exclude_days=("Fri", "Sat", "Sun")), - PostShiftConstraint(days=1, start_date="2025-11-17", exclude_days=("Fri", "Sat", "Sun")), + PostShiftConstraint(days=1, start_date="2025-11-17", exclude_days=("Fri", "Sat", "Sun"), allow_self=True), #{ # "name": "max_shifts_per_week", # "options": 3, diff --git a/output/timetable.js b/output/timetable.js index eb5749b..299b49a 100644 --- a/output/timetable.js +++ b/output/timetable.js @@ -550,6 +550,7 @@ $(document).on("change", "input[name='worker-filter-checkbox']", function() { renderShiftTimetable(); }); +let showWeekStart = false; // Add a checkbox to show/hide shift names in the shift timetable section $("#shift-timetable-options").prepend(`
@@ -558,7 +559,15 @@ $("#shift-timetable-options").prepend(` Show shift names in timetable
+`).prepend(` +
+ +
`); + // Add a button to remove all shift timetable colours (set to white) $("#shift-colour-controls").append( `` @@ -581,6 +590,12 @@ $("#show-shift-names-checkbox").on("change", function() { renderShiftTimetable(); }); + +$("#show-week-start-checkbox").on("change", function () { + showWeekStart = $(this).is(":checked"); + renderShiftTimetable(); +}); + // Patch renderShiftTimetable to show shift names if enabled function renderShiftTimetable() { console.log("Render shift timetable"); @@ -663,6 +678,18 @@ function renderShiftTimetable() { }); weeks = weeks.sort((a, b) => parseInt(a) - parseInt(b)); + + // Build week -> start date map (earliest date in that week) + let weekStartDates = {}; + $("table#main-table td[data-week][data-date]").each(function () { + let wk = $(this).attr("data-week"); + let d = $(this).attr("data-date"); + if (!wk || !d) return; + if (!weekStartDates[wk] || new Date(d) < new Date(weekStartDates[wk])) { + weekStartDates[wk] = d; + } + }); + let workerIds = []; let workerIdToName = {}; $("table#main-table td.worker").each(function () { @@ -703,9 +730,14 @@ function renderShiftTimetable() { weeks.forEach(week => { let row = $(``); - row.append(`${week}`); + // Show week number and (optionally) the week's start date + let weekLabel = [week]; + if (showWeekStart && weekStartDates[week]) { + weekLabel += `
${weekStartDates[week]}
`; + } + row.append(`${weekLabel}`); daysOfWeek.forEach(day => { - let cellContent = ""; + let cellContent = []; for (const workerId of workerIds) { let worker = cellMap[workerId]; let shifts = (worker.cells[week] && worker.cells[week][day]) || []; @@ -720,10 +752,10 @@ function renderShiftTimetable() { color = `linear-gradient(90deg, ${shiftColors[matchedShifts[0]]} 0 50%, ${shiftColors[matchedShifts[1]]} 50% 100%)`; if (showShiftNames) shiftLabel = ` (${matchedShifts.join(", ")})`; } - cellContent += `
${worker.name}${shiftLabel}
`; + cellContent.push(`
${worker.name}${shiftLabel}
`); } } - row.append(`${cellContent}`); + row.append(`${cellContent.join(" / ")}`); }); gridTable.append(row); }); diff --git a/rota/shifts.py b/rota/shifts.py index 6fd9b85..37373a3 100644 --- a/rota/shifts.py +++ b/rota/shifts.py @@ -93,11 +93,13 @@ class PreShiftConstraint(BaseShiftConstraint): days: Any = None ignore_shifts: List[str] = [] exclude_days: List[str] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] + allow_self: bool = True class PostShiftConstraint(BaseShiftConstraint): days: Any = None ignore_shifts: List[str] = [] exclude_days: List[str] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] + allow_self: bool = True class BalanceAcrossGroupsConstraint(BaseShiftConstraint): """""" @@ -2932,7 +2934,10 @@ class RotaBuilder(object): PreShiftConstraint ): constraint = constraint_shift.get_constraint(PreShiftConstraint) - ignore_shifts = constraint.ignore_shifts + [constraint_shift.name] + if constraint.allow_self: + ignore_shifts = constraint.ignore_shifts + [constraint_shift.name] + else: + ignore_shifts = constraint.ignore_shifts if week not in constraint.weeks: continue for n in range(0, constraint.days): @@ -2969,7 +2974,10 @@ class RotaBuilder(object): PostShiftConstraint ): constraint = constraint_shift.get_constraint(PostShiftConstraint) - ignore_shifts = constraint.ignore_shifts + [constraint_shift.name] + if constraint.allow_self: + ignore_shifts = constraint.ignore_shifts + [constraint_shift.name] + else: + ignore_shifts = constraint.ignore_shifts if week not in constraint.weeks: continue for n in range(0, constraint.days):