Private/Test-DhReportLinks.ps1
|
function Test-DhReportLinks { <# .SYNOPSIS Export-time cross-reference check (v2.1.4). Returns one message per dangling table reference or unknown block type. Export-DhDashboard writes each as a warning. .DESCRIPTION Every reference below is a silent no-op in the browser when the table it names does not exist: the chart renders empty, the cell or tile click does nothing. Some cmdlets check at Add-time, but only when the table was declared first, and several never checked at all. Checking once here, against the finished report, catches all of them whatever the declaration order. Warnings, never throws: a report that exports today must keep exporting (plan-v2.2 decision D4). #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)] [System.Collections.Specialized.OrderedDictionary] $Report, # Block types Export-DhDashboard knows how to serialise. Kept as a # parameter so the list lives next to the switch it mirrors. [Parameter(Mandatory)] [string[]] $KnownBlockTypes ) $tableIds = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal) foreach ($t in $Report.Tables) { [void]$tableIds.Add([string]$t.Id) } $missing = { param([string] $Id) -not [string]::IsNullOrWhiteSpace($Id) -and -not $tableIds.Contains($Id) } # Global summary tiles if ($Report.Contains('Summary')) { foreach ($it in @($Report.Summary)) { if ($it -is [System.Collections.IDictionary] -and $it.Contains('Action') -and $it.Action -is [System.Collections.IDictionary]) { $tid = [string]$it.Action['TableId'] if (& $missing $tid) { "summary tile '$($it.Label)': Action.TableId '$tid' is not a table in this report - the tile click will do nothing." } } } } # Alert banners if ($Report.Contains('AlertBanners')) { foreach ($a in $Report.AlertBanners) { if ($a.Contains('Action') -and $a.Action -is [System.Collections.IDictionary]) { $tid = [string]$a.Action['TableId'] if (& $missing $tid) { "alert banner '$($a.Id)': Action.TableId '$tid' is not a table in this report - the action button will do nothing." } } } } # Table master/detail links if ($Report.Contains('Links')) { foreach ($l in @($Report.Links)) { foreach ($k in 'MasterTableId', 'DetailTableId') { $tid = [string]$l[$k] if (& $missing $tid) { "Set-DhTableLink: $k '$tid' is not a table in this report - the link will do nothing." } } } } if (-not $Report.Contains('Blocks')) { return } foreach ($b in $Report.Blocks) { $bt = [string]$b.BlockType $bid = [string]$b.Id if ($bt -notin $KnownBlockTypes) { "block '$bid': unknown BlockType '$bt' - it is not rendered." continue } switch ($bt) { { $_ -in 'barchart', 'piechart', 'rangebar' } { $tid = [string]$b['TableId'] if (& $missing $tid) { "$bt '$bid': TableId '$tid' is not a table in this report - the chart will be empty." } # v2.2.0 - a ValueField can only be checked at Add-time when the # table came first; check again here for the other order elseif ($bt -eq 'barchart' -and $b.Contains('ValueField') -and $b.ValueField) { $tbl = $Report.Tables | Where-Object { $_.Id -eq $tid } | Select-Object -First 1 if ($tbl -and [string]$b.ValueField -cnotin (Get-DhTableFieldNames -Table $tbl)) { "barchart '$bid': ValueField '$($b.ValueField)' is not a field of table '$tid' - every bar will be empty." } } } 'filtercardgrid' { $tid = [string]$b['TargetTableId'] if (& $missing $tid) { "filter card '$bid': TargetTableId '$tid' is not a table in this report - the cards will filter nothing." } } 'statusgrid' { foreach ($c in @($b.Cells)) { $tid = [string]$c['LinkTableId'] if (& $missing $tid) { "status grid '$bid' cell ($($c['Row']), $($c['Column'])): LinkTableId '$tid' is not a table in this report - the click will do nothing." } } } 'topologymap' { foreach ($n in @($b.Nodes)) { $tid = [string]$n['LinkTableId'] if (& $missing $tid) { "topology map '$bid' node '$($n['Id'])': LinkTableId '$tid' is not a table in this report - the click will do nothing." } } } 'findings' { foreach ($f in @($b.Findings)) { $tid = [string]$f['AffectedTableId'] if (& $missing $tid) { "findings '$bid' finding '$($f['Title'])': AffectedTableId '$tid' is not a table in this report - 'Show in table' will do nothing." } } } 'summarystrip' { foreach ($it in @($b.Items)) { if ($it -is [System.Collections.IDictionary] -and $it.Contains('Action') -and $it.Action -is [System.Collections.IDictionary]) { $tid = [string]$it.Action['TableId'] if (& $missing $tid) { "summary strip '$bid' tile '$($it.Label)': Action.TableId '$tid' is not a table in this report - the tile click will do nothing." } } } } } } } |