Add worker checkboxes and help text to shift timetable for improved usability
This commit is contained in:
+99
-30
@@ -382,17 +382,6 @@ oshifts.forEach((shift, i) => {
|
||||
$("#shift-timetable-options").append(
|
||||
`<button id="toggle-grid-view" style="margin-left:10px;">Toggle Linear/Grid View</button><br/>`
|
||||
);
|
||||
// Add help text to the shift timetable section
|
||||
$("#shift-timetable-options").prepend(`
|
||||
<details id="shift-timetable-help" style="margin-bottom:8px; font-size: 0.95em; color: #444;">
|
||||
<summary><b>Shift Timetables Help:</b></summary>
|
||||
<ul style="margin: 4px 0 0 18px; padding: 0;">
|
||||
<li>Select one or more shifts below to view which workers are assigned on each day.</li>
|
||||
<li>Use the colour pickers to customise shift colours in the timetable and main table.</li>
|
||||
<li>Toggle between linear and grid view using the "Toggle Linear/Grid View" button.</li>
|
||||
</ul>
|
||||
</details>
|
||||
`);
|
||||
|
||||
let gridViewEnabled = false;
|
||||
|
||||
@@ -494,32 +483,83 @@ function rgb2hex(rgb) {
|
||||
return "#ffe066";
|
||||
}
|
||||
|
||||
// Add a worker filter input to the shift timetable section
|
||||
$("#shift-timetable-options").prepend(`
|
||||
<div id="shift-timetable-worker-filter" style="margin-bottom:8px;">
|
||||
<label for="worker-filter-input"><b>Filter workers:</b></label>
|
||||
<input type="text" id="worker-filter-input" placeholder="Type to filter by name..." style="margin-left:4px; padding:2px 6px;"/>
|
||||
</div>
|
||||
`);
|
||||
// --- Add worker checkboxes to the shift timetable section ---
|
||||
function renderWorkerCheckboxes() {
|
||||
// Get all unique worker names and IDs from the main table
|
||||
let workerList = [];
|
||||
$("table#main-table td.worker").each(function () {
|
||||
let workerId = $(this).attr("data-worker-id");
|
||||
let workerName = $(this).find("span.name").text().trim();
|
||||
if (workerId && !workerList.some(w => w.id === workerId)) {
|
||||
workerList.push({ id: workerId, name: workerName });
|
||||
}
|
||||
});
|
||||
|
||||
// Store the current filter value
|
||||
let workerFilterValue = "";
|
||||
// Build checkboxes
|
||||
let html = `<details id="shift-timetable-worker-filter" style="margin-bottom:8px;">
|
||||
<summary><b>Show workers:</b></summary>`;
|
||||
// Add a "Toggle All" button
|
||||
html += `<button type="button" id="toggle-all-workers" style="margin-right:10px;">Toggle All</button>`;
|
||||
|
||||
// Update the filter value on input
|
||||
$("#worker-filter-input").on("input", function() {
|
||||
workerFilterValue = $(this).val().toLowerCase();
|
||||
workerList.forEach(w => {
|
||||
html += `<label style="margin-right:8px;">
|
||||
<input type="checkbox" name="worker-filter-checkbox" value="${w.id}" checked> ${w.name}
|
||||
</label>`;
|
||||
});
|
||||
|
||||
// Attach toggle logic after DOM insertion
|
||||
setTimeout(() => {
|
||||
$("#toggle-all-workers").off("click").on("click", function() {
|
||||
const $checkboxes = $("input[name='worker-filter-checkbox']");
|
||||
const allChecked = $checkboxes.length === $checkboxes.filter(":checked").length;
|
||||
$checkboxes.prop("checked", !allChecked);
|
||||
// Update the filter set and re-render once, instead of triggering "change" for each
|
||||
workerFilterSet = new Set(
|
||||
Array.from(document.querySelectorAll("input[name='worker-filter-checkbox']:checked"))
|
||||
.map(cb => cb.value)
|
||||
);
|
||||
// Call your function here after the map has finished
|
||||
renderShiftTimetable();
|
||||
});
|
||||
}, 0);
|
||||
html += `</details>`;
|
||||
|
||||
// Prepend to the shift timetable options
|
||||
$("#shift-timetable-options").prepend(html);
|
||||
}
|
||||
|
||||
// Store the current filter value (set of workerIds)
|
||||
let workerFilterSet = new Set();
|
||||
|
||||
// Call this after the DOM is ready and after timetable is rendered
|
||||
renderWorkerCheckboxes();
|
||||
|
||||
// On first render, select all workers by default
|
||||
$("input[name='worker-filter-checkbox']").each(function() {
|
||||
workerFilterSet.add($(this).val());
|
||||
});
|
||||
renderShiftTimetable();
|
||||
|
||||
// Update the filter set on checkbox change
|
||||
$(document).on("change", "input[name='worker-filter-checkbox']", function() {
|
||||
workerFilterSet = new Set(
|
||||
$("input[name='worker-filter-checkbox']:checked").map(function() { return $(this).val(); }).get()
|
||||
);
|
||||
renderShiftTimetable();
|
||||
});
|
||||
|
||||
// Patch renderShiftTimetable to filter workers in both linear and grid views
|
||||
function renderShiftTimetable() {
|
||||
console.log("Render shift timetable");
|
||||
console.log(workerFilterSet)
|
||||
$("#shift-timetable-div").empty();
|
||||
if (selectedShifts.size === 0) return;
|
||||
if (workerFilterSet.size === 0) return;
|
||||
|
||||
// Helper: returns true if worker name matches filter
|
||||
function workerMatchesFilter(workerName) {
|
||||
if (!workerFilterValue) return true;
|
||||
return workerName.toLowerCase().includes(workerFilterValue);
|
||||
// Helper: returns true if worker id matches filter set or set is empty (all)
|
||||
function workerMatchesFilter(workerId) {
|
||||
if (workerFilterSet.size === 0) return true;
|
||||
return workerFilterSet.has(workerId);
|
||||
}
|
||||
|
||||
if (!gridViewEnabled) {
|
||||
@@ -553,7 +593,8 @@ function renderShiftTimetable() {
|
||||
}).each((n, td) => {
|
||||
let workerTd = $(td).closest("tr").children("td:first");
|
||||
let workerName = workerTd.find("span.name").text().trim();
|
||||
if (!workerMatchesFilter(workerName)) return;
|
||||
let workerId = workerTd.attr("data-worker-id");
|
||||
if (!workerMatchesFilter(workerId)) return;
|
||||
let cell_shifts = $(td).attr("data-shift").split(",").map(s => s.trim());
|
||||
let matchedShifts = Array.from(selectedShifts).filter(s => cell_shifts.includes(s));
|
||||
let color = "#fff";
|
||||
@@ -590,9 +631,9 @@ function renderShiftTimetable() {
|
||||
let workerIdToName = {};
|
||||
$("table#main-table td.worker").each(function () {
|
||||
let workerId = $(this).attr("data-worker-id");
|
||||
let workerName = $(this).find("span.name").text().trim();
|
||||
if (workerId && !workerIds.includes(workerId)) {
|
||||
let workerName = $(this).find("span.name").text().trim();
|
||||
if (workerMatchesFilter(workerName)) {
|
||||
if (workerMatchesFilter(workerId)) {
|
||||
workerIds.push(workerId);
|
||||
workerIdToName[workerId] = workerName;
|
||||
}
|
||||
@@ -650,6 +691,21 @@ function renderShiftTimetable() {
|
||||
$("#shift-timetable-div").append(gridTable);
|
||||
}
|
||||
|
||||
// Re-render worker checkboxes after timetable is updated (in case workers change)
|
||||
function rerenderWorkerCheckboxesIfNeeded() {
|
||||
$("#shift-timetable-worker-filter").remove();
|
||||
renderWorkerCheckboxes();
|
||||
// Restore checked state
|
||||
$("input[name='worker-filter-checkbox']").each(function() {
|
||||
if (workerFilterSet.has($(this).val())) {
|
||||
$(this).prop("checked", true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Call this after timetable is (re)rendered if needed
|
||||
rerenderWorkerCheckboxesIfNeeded();
|
||||
|
||||
// Patch the timetable button logic to use renderShiftTimetable
|
||||
oshifts.forEach((shift) => {
|
||||
let button = $(`<button data-shift='${shift}'>${shift}</button>`);
|
||||
@@ -676,6 +732,19 @@ oshifts.forEach((shift) => {
|
||||
|
||||
$("#shift-timetable-options").append(button);
|
||||
});
|
||||
|
||||
|
||||
// Add help text to the shift timetable section
|
||||
$("#shift-timetable-options").prepend(`
|
||||
<details id="shift-timetable-help" style="margin-bottom:8px; font-size: 0.95em; color: #444;">
|
||||
<summary><b>Shift Timetables Help:</b></summary>
|
||||
<ul style="margin: 4px 0 0 18px; padding: 0;">
|
||||
<li>Select one or more shifts below to view which workers are assigned on each day.</li>
|
||||
<li>Use the colour pickers to customise shift colours in the timetable and main table.</li>
|
||||
<li>Toggle between linear and grid view using the "Toggle Linear/Grid View" button.</li>
|
||||
</ul>
|
||||
</details>
|
||||
`);
|
||||
//$("table.summary")
|
||||
|
||||
// $("body").prepend("<div id='global-settings'>Settings:<br />Customise training days lost per shift (you need to press recalculate for changes to take effect)<form></form></div>")
|
||||
|
||||
Reference in New Issue
Block a user