diff --git a/gen_cons.py b/gen_cons.py index 29a3962..9e593a7 100644 --- a/gen_cons.py +++ b/gen_cons.py @@ -694,6 +694,9 @@ def main( subprocess.run( ["scp", Rota.exported_rota_file, "ross@46.101.13.46:proc/proc-rota/output/"] ) + subprocess.run( + ["scp", "output/timetable.js", "ross@46.101.13.46:proc/proc-rota/output/"] + ) if suspend_on_finish: os.system("systemctl suspend") diff --git a/output/timetable.js b/output/timetable.js index 4fec5b3..bfe18eb 100644 --- a/output/timetable.js +++ b/output/timetable.js @@ -403,36 +403,50 @@ function renderWorkerFilterOptions() { } function renderWorkerList() { - console.log("Rendering worker list with filters"); const $wd = $("#worker_details"); - console.log("Worker details container:", $wd.length ? $wd.get(0) : "not found"); if (!$wd.length) return; let workers = $wd.data("workers"); try { if (typeof workers === 'string') workers = JSON.parse(workers); } catch (e) { workers = null; } const filter = ($("#worker-filter").val() || '').toLowerCase(); - console.log("Text filter:", filter); const shiftFilter = ($("#worker-shift-select").val() || ''); + // Parse the original pre block into per-worker text blocks so rich details are preserved. + const detailsByName = {}; + const preText = (($wd.find("pre").first().text() || '') + '').trim(); + const escapeHtml = (text) => String(text) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + if (preText.length > 0) { + preText.split(/\n\s*\n(?=Name:\s*)/g).forEach(block => { + const trimmed = (block || '').trim(); + if (!trimmed) return; + const nameMatch = trimmed.match(/^Name:\s*(.+)$/m); + if (!nameMatch) return; + detailsByName[nameMatch[1].trim()] = trimmed; + }); + } + let $list = $("#worker-list"); if ($list.length === 0) { $list = $("
"); $("#worker_details").append($list); } + // Hide the static pre block since we render interactive cards + $("#worker_details pre").hide(); + $list.show(); $list.empty(); if (!workers) return; workers.forEach(w => { - console.log("Processing worker:", w.name); const name = (w.name || '') + ''; - const displayName = (w.display_name || '') + ''; const site = (w.site || '') + ''; - const searchName = (displayName || name).toLowerCase(); - console.log(`Worker "${name}" at site "${site}" with display name "${displayName}"`); - if (filter) { - const matchesName = searchName.indexOf(filter) !== -1; + if (filter.length > 0) { + const matchesName = name.toLowerCase().indexOf(filter) !== -1; const matchesSite = site.toLowerCase().indexOf(filter) !== -1; if (!matchesName && !matchesSite) return; } - console.log(`Worker "${name}" passed text filter`); // if shiftFilter, ensure worker has target or assigned for that shift // attempt to read per-worker targets and counts from DOM if not present in JSON let targets = w.shift_target_number || {}; @@ -455,38 +469,62 @@ function renderWorkerList() { if (!hasTarget && !hasAssigned) return; } const fte = w.fte || ''; - const labelName = displayName || name; const grade = w.grade || ''; const id = w.id ? String(w.id).substring(0, 8) : ''; - const card = $(`${escapeHtml(fullDetails)}