Files
pxe-server/playbook/shopfloor-setup/gea-shopfloor-waxtrace/scripts/Select-WaxtraceAsset.ps1
cproudlock b8bb00e2fe Wax/Trace triad: arrow-key bay picker + S: backup path
Two operator-UX improvements for the Backup / Export / Install triad.

1. Backup target moves from \\tsgwp00525\...\formtracepac to S:\2 WJ Scans
   Record Retention\backup\waxtrace\<asset>\. S: is mapped at shopfloor
   imaging time and stays mapped post-categorization, so the same default
   path works whether the operator runs the backup on an old bay (manual
   pre-image capture) or a freshly imaged one. The destination directory
   is created if missing.

2. New Select-WaxtraceAsset.ps1 - arrow-key bay picker patterned after
   the WinPE select-waxtrace-asset.ps1. Reads bay-config.csv (sibling
   file), shows asset_tag + ftpak_version + model + user_id per row, and
   returns the selected asset_tag via stdout. Falls back to a manual
   entry prompt if the CSV is missing or the operator picks "Other".

   Backup / Export / Install now invoke the picker when interactive AND
   bay-config.csv is alongside the script. Non-interactive paths
   (qga / SYSTEM / scheduled task) keep silently defaulting to
   COMPUTERNAME so unattended runs are unchanged.

   Export gained an -AssetNumber parameter and stamps it into the output
   CSV filename so multiple inventories from the same host stay
   distinguishable when the operator is auditing several bays in a row.

bay-config.csv is copied into the scripts\ dir so the picker has a
source of truth that ships next to the scripts (and into pxe-images
for tech distribution).

Smoke tested on win11 VM: all four PS1 parse-clean, non-interactive
backup path still produces a valid ZIP (silent COMPUTERNAME default),
picker handles missing-CSV gracefully (manual-entry fallback). The
arrow-key UX itself is operator-verifiable only on a real terminal.
2026-05-24 07:41:25 -04:00

111 lines
3.8 KiB
PowerShell

<#
.SYNOPSIS
Arrow-key bay picker for Wax/Trace Export / Backup / Install scripts.
.DESCRIPTION
Reads bay-config.csv (asset_tag,ftpak_version,model,user_id) and presents
an Up/Down picker. Returns the chosen asset_tag to stdout so the calling
script can capture it. Always appends an "Other (manual entry)" option.
Same UX as the WinPE select-waxtrace-asset.ps1 used by startnet.cmd.
Distinct from that script because it returns the asset tag via stdout
rather than writing to a file, and presents the richer per-bay columns
(FTPak version + model + USER ID) from bay-config.csv.
.PARAMETER ConfigCsv
Path to bay-config.csv. Defaults to a sibling file next to this script.
.PARAMETER Title
Header text shown above the picker. Defaults to "Wax/Trace Asset".
.OUTPUTS
String. The chosen asset_tag, printed to stdout. Empty string on cancel.
.EXAMPLE
$asset = & .\Select-WaxtraceAsset.ps1
$asset = & .\Select-WaxtraceAsset.ps1 -ConfigCsv 'C:\foo\bay-config.csv' -Title 'Pick bay to back up'
#>
[CmdletBinding()]
param(
[string]$ConfigCsv = (Join-Path $PSScriptRoot 'bay-config.csv'),
[string]$Title = 'Wax/Trace Asset'
)
$ErrorActionPreference = 'Continue'
function Read-BayList {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path)) { return @() }
try {
return Import-Csv -LiteralPath $Path |
Sort-Object -Property asset_tag
} catch {
return @()
}
}
function Show-Menu {
param([object[]]$Items, [int]$Selected, [string]$Title)
Clear-Host
Write-Host ''
Write-Host ' ============================================================'
Write-Host " $Title"
Write-Host ' ============================================================'
Write-Host ''
Write-Host ' Up / Down arrows = navigate, Enter = select, Esc = cancel'
Write-Host ''
Write-Host (' {0,-10} {1,-8} {2,-10} {3}' -f 'ASSET', 'FTPAK', 'MODEL', 'USER ID')
Write-Host (' {0,-10} {1,-8} {2,-10} {3}' -f '-----', '-----', '-----', '-------')
for ($i = 0; $i -lt $Items.Count; $i++) {
$item = $Items[$i]
if ($item -is [string]) {
$line = $item
} else {
$line = '{0,-10} {1,-8} {2,-10} {3}' -f $item.asset_tag, $item.ftpak_version, $item.model, $item.user_id
}
if ($i -eq $Selected) {
Write-Host (' > ' + $line) -ForegroundColor Black -BackgroundColor White
} else {
Write-Host (' ' + $line)
}
}
Write-Host ''
}
$bays = @(Read-BayList -Path $ConfigCsv)
$menuItems = @()
foreach ($b in $bays) { $menuItems += $b }
$menuItems += '** Other (enter asset tag manually) **'
if ($menuItems.Count -eq 1) {
# Only the manual-entry sentinel: CSV missing or unparseable. Fall back
# to a plain prompt rather than wedging the operator in an empty menu.
Write-Host " (bay-config.csv not readable at $ConfigCsv - falling back to manual entry)"
$manual = Read-Host " Enter asset tag (e.g. WJRP9999) or blank to abort"
if ($manual) { return $manual.Trim().ToUpper() } else { return '' }
}
$sel = 0
while ($true) {
Show-Menu -Items $menuItems -Selected $sel -Title $Title
$key = [System.Console]::ReadKey($true)
switch ($key.Key) {
'UpArrow' { if ($sel -gt 0) { $sel-- } }
'DownArrow' { if ($sel -lt ($menuItems.Count - 1)) { $sel++ } }
'Enter' {
if ($sel -eq ($menuItems.Count - 1)) {
Write-Host ''
$manual = Read-Host ' Enter asset tag (e.g. WJRP9999) or blank to abort'
if ($manual) {
return $manual.Trim().ToUpper()
} else {
return ''
}
} else {
return $bays[$sel].asset_tag
}
}
'Escape' { return '' }
}
}