Files
usmt-dash/Demo/New-DemoData.ps1
T
Johan Sandoval 9731368687 Faster first load; demo date tags stay current
First load:
- Draw the Overview as soon as the data arrives instead of on its next
  2-second timer tick (about 2.5 s to 0.6 s on a typical connection).
- Start on DOMContentLoaded instead of window.onload.
- Load the ~900 KB PDF library only when someone exports a PDF.
- Fetch the startup files side by side, and build the docs search index
  after the dashboard has drawn (unless the visit starts on /docs).
- Show a loading placeholder on the Overview until the data arrives.

Demo: the date-batch tags sit on fixed working-day offsets from today.
The seed records them in Demo-Dates.json and the worker relabels them when
the day changes, so a long-running container never looks stale.
2026-10-07 20:22:09 +00:00

119 lines
6.2 KiB
PowerShell

# Seeds Data\ with a simulated fleet for demo mode: tracking tags (Tracked-Devices.json),
# the app blacklist, and a pre-warmed software cache so the first worker cycle is quick.
# Run before starting the services. -Force wipes any existing state first.
param(
[switch]$Force,
[string]$ConfigPath
)
$root = Split-Path $PSScriptRoot -Parent
. (Join-Path $root "Lib/Common.ps1")
$config = Import-DashConfig -Path $ConfigPath -Demo
$v = $false
. (Join-Path $root "Providers/Demo.ps1")
. (Join-Path $root "Lib/Common.ps1") # re-import so nothing in the provider shadows the helpers
$dataDir = Join-Path $root "Data"
if ($Force -and (Test-Path $dataDir)) {
Get-ChildItem $dataDir -Recurse -File | Remove-Item -Force
}
if (-not (Test-Path $dataDir)) { New-Item -ItemType Directory -Path $dataDir | Out-Null }
$trackedPath = Join-Path $dataDir "Tracked-Devices.json"
if ((Test-Path $trackedPath) -and -not $Force) {
Write-Host "Demo data already present (use -Force to reseed)." -ForegroundColor DarkGray
return
}
$count = [int]$config.Demo.DeviceCount
Write-Host "Seeding demo fleet ($count tracked devices)..." -ForegroundColor Cyan
# --- 1. Generate source devices ---
function New-FleetName([int]$i, [string]$prefix) { return "$prefix-$(New-DemoSerial "fleet$i")" }
$skipPublic = [System.Collections.Generic.List[string]]::new()
$skipLaptops = [System.Collections.Generic.List[string]]::new()
$pool = [System.Collections.Generic.List[string]]::new()
$i = 0
while ($skipPublic.Count -lt 14) { $skipPublic.Add((New-FleetName ($i++) "PUBDT")) }
while ($skipLaptops.Count -lt 16) { $skipLaptops.Add((New-FleetName ($i++) (Get-DemoPick "lt$i" 'p' @("PRVLT", "PRVLT", "PRVLT", "PUBLT")))) }
while ($pool.Count -lt ($count - $skipPublic.Count - $skipLaptops.Count - 3)) {
$r = Get-DemoRand "mix$i" 'prefix'
$prefix = if ($r -lt 0.55) { "PRVDT" } elseif ($r -lt 0.80) { "PUBDT" } elseif ($r -lt 0.95) { "PRVLT" } else { "PUBLT" }
$pool.Add((New-FleetName ($i++) $prefix))
}
# Manual "Source, Destination" pairs - hardware exceptions with no SCCM association
$manual = @()
for ($m = 0; $m -lt 3; $m++) {
$src = New-FleetName ($i++) "PRVDT"
$dst = New-FleetName ($i++) "PRVDT"
$manual += "$src, $dst"
}
# --- 2. Date-batch tags (recent and upcoming working days; the worker keeps them current) ---
$dateTags = Get-DemoDateTags
[System.IO.File]::WriteAllText((Join-Path $dataDir "Demo-Dates.json"), (@{ Tags = $dateTags } | ConvertTo-Json), [System.Text.Encoding]::UTF8)
$tags = [ordered]@{}
foreach ($t in $dateTags) { $tags[$t] = [System.Collections.Generic.List[string]]::new() }
for ($n = 0; $n -lt $pool.Count; $n++) { $tags[$dateTags[$n % $dateTags.Count]].Add($pool[$n]) }
$tags["Manual Pairs"] = [System.Collections.Generic.List[string]]::new([string[]]$manual)
# Department tags overlap the date batches, like a tech grouping their own work
$byDept = @{}
foreach ($d in $pool) {
$dep = (Get-DemoProfile $d).Department.Name
if (-not $byDept.ContainsKey($dep)) { $byDept[$dep] = [System.Collections.Generic.List[string]]::new() }
$byDept[$dep].Add($d)
}
foreach ($pair in @(@("Accounting", "Accounting"), @("Sales Floor", "Sales"), @("Exec Suite", "Executive"))) {
if ($byDept.ContainsKey($pair[1])) { $tags[$pair[0]] = [System.Collections.Generic.List[string]]::new([string[]]@($byDept[$pair[1]] | Select-Object -First 12)) }
}
$tags["Broken WMI"] = [System.Collections.Generic.List[string]]::new([string[]]@($pool | Where-Object { (Get-DemoRand $_ 'wmi') -lt 0.03 } | Select-Object -First 5))
$tags["Bad Client"] = [System.Collections.Generic.List[string]]::new([string[]]@($pool | Where-Object { (Get-DemoRand $_ 'badclient') -lt 0.03 } | Select-Object -First 4))
$tags["Public PCs"] = $skipPublic
$tags["Laptops"] = $skipLaptops
$skipTags = @("Public PCs", "Laptops")
$tracked = [ordered]@{}
foreach ($t in $tags.Keys) {
$tracked[$t] = [ordered]@{ devices = @($tags[$t]); skipUSMT = ($skipTags -contains $t) }
}
($tracked | ConvertTo-Json -Depth 5) | Set-Content -Path $trackedPath -Encoding UTF8
# --- 3. Blacklist / suite rules ---
Copy-Item (Join-Path $PSScriptRoot "Blacklisted-Apps.txt") (Join-Path $dataDir "Blacklisted-Apps.txt") -Force
$blacklist = @(Get-Content (Join-Path $dataDir "Blacklisted-Apps.txt") | Where-Object { $_.Trim() -ne "" } | ForEach-Object { $_.Trim() })
# --- 4. Pre-warmed software cache (the worker would otherwise build it one device at a time) ---
$allDevices = [System.Collections.Generic.List[string]]::new()
foreach ($d in ($pool + $skipPublic + $skipLaptops)) {
$allDevices.Add($d)
$p = Get-DemoProfile $d
if (-not $p.NoAssoc -and -not ($skipPublic -contains $d) -and -not ($skipLaptops -contains $d)) { $allDevices.Add((Get-DemoDestName $d)) }
}
foreach ($pair in $manual) { $allDevices.AddRange([string[]]@($pair -split '\s*,\s*')) }
$stamp = (Get-Date).ToString("o")
$cache = [ordered]@{}
foreach ($d in $allDevices) {
$rows = foreach ($row in (Get-InstalledSoftware -ComputerName $d)) {
$isSpecialty = $true
foreach ($bad in $blacklist) { if ($row.Name -like $bad) { $isSpecialty = $false; break } }
[PSCustomObject]@{ Name = $row.Name; Version = $row.Version; Publisher = $row.Publisher; Source = $row.Source; InstallDate = $row.InstallDate; IsSpecialty = $isSpecialty }
}
$cache[$d] = [PSCustomObject]@{ Timestamp = $stamp; Data = @($rows) }
}
[System.IO.File]::WriteAllText((Join-Path $dataDir "Software-Cache.json"), ($cache | ConvertTo-Json -Depth 6 -Compress), [System.Text.Encoding]::UTF8)
# --- 5. Empty state for the rest ---
Set-Content -Path (Join-Path $dataDir "Completed.json") -Value "[]" -Encoding UTF8
Set-Content -Path (Join-Path $dataDir "Data.json") -Value "[]" -Encoding UTF8
Set-Content -Path (Join-Path $dataDir "Advanced-Cache.json") -Value "{}" -Encoding UTF8
Set-Content -Path (Join-Path $dataDir "Worker-State.json") -Value '{"Status":"Preparing...","Current":0,"Total":0,"LastUpdated":"Never","NextCycle":"Calculating...","LastDuration":"N/A"}' -Encoding UTF8
Set-Content -Path (Join-Path $dataDir "Whitelisted-IPs.txt") -Value "" -Encoding UTF8
$unique = @($tracked.Values | ForEach-Object { $_.devices } | ForEach-Object { $_ }) | Select-Object -Unique
Write-Host "Seeded $($tracked.Count) tags, $(@($unique).Count) roster entries, $($cache.Count) software inventories." -ForegroundColor Green