From 626561a1fa66c656e1f5976f9ebef72e8155d422 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Thu, 23 Jul 2026 13:27:08 -0400 Subject: [PATCH] shopfloor menu: data-driven from menu.json (picker + webapp editor) Replace the hardcoded GEA Shopfloor PC-type sub-menu with a data-driven one: - menu.json on the enrollment share lists the shopfloor items {key=PCTYPE, label, hint, enabled}; key must match a shopfloor-setup/gea-shopfloor-* handler dir. - select-shopfloor-type.ps1 renders it in WinPE and writes the chosen PCTYPE (mirrors the CMM bay picker); startnet.cmd runs it and falls back to the baked-in menu if the share/picker is unavailable. - Webapp /shopfloor-menu editor: reorder/rename/hide/add items; the PC-type is a dropdown of existing handler dirs (can't wire a choice to a non-existent type); writes menu.json. Nav link under Tools. Kills the duplicated-knowledge problem (menu list was hardcoded in startnet AND the handler dirs AND site-config); add a PC-type = drop in the handler dir + it appears in the menu. --- playbook/shopfloor-setup/menu.json | 15 +++ .../shopfloor-setup/select-shopfloor-type.ps1 | 63 ++++++++++++ playbook/startnet.cmd | 18 +++- webapp/app.py | 77 +++++++++++++++ webapp/templates/base.html | 6 ++ webapp/templates/shopfloor_menu.html | 99 +++++++++++++++++++ 6 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 playbook/shopfloor-setup/menu.json create mode 100644 playbook/shopfloor-setup/select-shopfloor-type.ps1 create mode 100644 webapp/templates/shopfloor_menu.html diff --git a/playbook/shopfloor-setup/menu.json b/playbook/shopfloor-setup/menu.json new file mode 100644 index 0000000..dd7efef --- /dev/null +++ b/playbook/shopfloor-setup/menu.json @@ -0,0 +1,15 @@ +{ + "_comment": "Data-driven WinPE shopfloor PC-type menu. Read at boot by select-shopfloor-type.ps1 (mirrors the CMM bay picker) and edited by the PXE webapp. 'key' is the PCTYPE value - it MUST match a shopfloor-setup/gea-shopfloor- handler dir. Order = display order. Set enabled=false to hide without deleting. Deployed to the enrollment share; startnet.cmd falls back to its baked-in menu if this file or the picker is unavailable.", + "shopfloor": [ + { "key": "gea-shopfloor-collections", "label": "Machine with Collections", "hint": "eDNC + UDC + Plant Apps", "enabled": true }, + { "key": "gea-shopfloor-nocollections", "label": "Machine without Collections", "hint": "eDNC + Plant Apps, no UDC", "enabled": true }, + { "key": "gea-shopfloor-common", "label": "Common", "hint": "Timeclock, Lab; WJ Shopfloor only", "enabled": true }, + { "key": "gea-shopfloor-keyence", "label": "Keyence", "hint": "VR-3000 / VR-5000 / VR-6000 microscope","enabled": true }, + { "key": "gea-shopfloor-cmm", "label": "CMM", "hint": "Hexagon PC-DMIS + Protect Viewer", "enabled": true }, + { "key": "gea-shopfloor-genspect", "label": "Genspect", "hint": "", "enabled": true }, + { "key": "gea-shopfloor-heattreat", "label": "Heattreat", "hint": "eDNC + HeatTreat app", "enabled": true }, + { "key": "gea-shopfloor-waxtrace", "label": "Wax and Trace", "hint": "", "enabled": true }, + { "key": "gea-shopfloor-display", "label": "Display", "hint": "kiosk dashboard", "enabled": true }, + { "key": "gea-shopfloor-partmarker", "label": "Part Marker", "hint": "eDNC + Telesis Mark", "enabled": true } + ] +} diff --git a/playbook/shopfloor-setup/select-shopfloor-type.ps1 b/playbook/shopfloor-setup/select-shopfloor-type.ps1 new file mode 100644 index 0000000..b13cf60 --- /dev/null +++ b/playbook/shopfloor-setup/select-shopfloor-type.ps1 @@ -0,0 +1,63 @@ +<# + select-shopfloor-type.ps1 - data-driven GEA Shopfloor PC-type picker for WinPE. + + Reads the shopfloor menu from menu.json (edited by the PXE webapp), renders a + numbered menu, and writes the chosen PCTYPE key (e.g. gea-shopfloor-cmm) to + -OutFile. startnet.cmd runs this instead of a hardcoded menu, and falls back + to its baked-in menu if this script or menu.json is missing. Mirrors the CMM + bay picker (select-cmm-bay.ps1). + + Usage (from startnet.cmd): + powershell -NoProfile -ExecutionPolicy Bypass -File select-shopfloor-type.ps1 ` + -MenuJson Y:\menu.json -OutFile X:\pctype.txt + Exit 0 + a written key on success; non-zero (and no file) on any failure so + the batch fallback kicks in. +#> +param( + [Parameter(Mandatory = $true)][string]$MenuJson, + [Parameter(Mandatory = $true)][string]$OutFile +) + +$ErrorActionPreference = 'Stop' +Remove-Item -LiteralPath $OutFile -ErrorAction SilentlyContinue + +try { + if (-not (Test-Path -LiteralPath $MenuJson)) { Write-Host "menu.json not found: $MenuJson"; exit 2 } + $data = Get-Content -LiteralPath $MenuJson -Raw | ConvertFrom-Json + $items = @($data.shopfloor | Where-Object { $_.key -and ($_.enabled -ne $false) }) + if ($items.Count -eq 0) { Write-Host "menu.json has no enabled shopfloor items"; exit 3 } + + while ($true) { + Clear-Host + Write-Host "" + Write-Host "========================================" + Write-Host " GEA Shopfloor PC Sub-Type" + Write-Host "========================================" + Write-Host "" + for ($i = 0; $i -lt $items.Count; $i++) { + $n = $i + 1 + $lbl = $items[$i].label + $hint = $items[$i].hint + $line = "{0,3}. {1}" -f $n, $lbl + if ($hint) { $line = "{0,-45} ({1})" -f $line, $hint } + Write-Host $line + } + Write-Host "" + $sel = Read-Host ("Enter your choice (1-{0})" -f $items.Count) + $num = 0 + if ([int]::TryParse($sel, [ref]$num) -and $num -ge 1 -and $num -le $items.Count) { + $key = $items[$num - 1].key + # OutFile is on X: (WinPE scratch); write the bare PCTYPE key, no BOM/newline surprises + [System.IO.File]::WriteAllText($OutFile, $key) + Write-Host "" + Write-Host ("Selected: {0} ({1})" -f $items[$num - 1].label, $key) + exit 0 + } + Write-Host "Invalid choice - try again." + Start-Sleep -Milliseconds 800 + } +} +catch { + Write-Host "shopfloor picker error: $($_.Exception.Message)" + exit 1 +} diff --git a/playbook/startnet.cmd b/playbook/startnet.cmd index 807ae5a..5298a7c 100644 --- a/playbook/startnet.cmd +++ b/playbook/startnet.cmd @@ -54,6 +54,19 @@ goto enroll_staged :gea_shopfloor_submenu cls +set PCTYPE= +REM Data-driven PC-type menu: the PXE webapp maintains menu.json on the +REM enrollment share; select-shopfloor-type.ps1 renders it and writes the +REM chosen PCTYPE to X:\pctype.txt. Falls back to the baked-in menu below if +REM the share or the picker is unavailable (mirrors the CMM bay picker). +net use Y: \\172.16.9.1\enrollment /user:pxe-upload pxe /persistent:no >NUL 2>NUL +del X:\pctype.txt 2>NUL +if exist "Y:\shopfloor-setup\select-shopfloor-type.ps1" powershell.exe -NoProfile -ExecutionPolicy Bypass -File "Y:\shopfloor-setup\select-shopfloor-type.ps1" -MenuJson "Y:\shopfloor-setup\menu.json" -OutFile "X:\pctype.txt" +if exist X:\pctype.txt set /p PCTYPE= startnet.cmd +