Public/ConvertTo-DhYaml.ps1
|
function ConvertTo-DhYaml { <# .SYNOPSIS Serialise a DashHtml report object into a readable YAML layout spec. .DESCRIPTION Takes the report object produced by New-DhDashboard (and mutated by the Add-Dh* cmdlets) and emits a YAML document describing the dashboard's structure — foundation settings, the global summary, tables, blocks, global filters, alert banners, and table links. This is the reliable "reverse" of the design round-trip: it serialises the ALREADY-BUILT object, so loops, computed values, and dynamic data are all captured faithfully — no PowerShell parsing involved. By default the table row data is summarised as a `dataRows: <count>` line to keep the output a layout view. Use -IncludeData to embed the rows. .PARAMETER Report The dashboard object from New-DhDashboard. .PARAMETER OutFile Optional path to write the YAML to. When omitted, the YAML string is returned. .PARAMETER IncludeData Embed each table's full row data instead of a `dataRows` count. .EXAMPLE $r = New-DhDashboard -Title 'Infra' -Theme Azure Add-DhTable -Report $r -TableId 'srv' -Title 'Servers' -Data $rows $r | ConvertTo-DhYaml -OutFile infra.yaml .EXAMPLE ConvertTo-DhYaml -Report $r # returns the YAML as a string #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [System.Collections.Specialized.OrderedDictionary] $Report, [string] $OutFile, [switch] $IncludeData ) process { $model = [ordered]@{} $model['title'] = $Report.Title if ($Report.Subtitle) { $model['subtitle'] = $Report.Subtitle } if ($Report.ThemeFamily) { $model['theme'] = $Report.ThemeFamily } if ($Report.Contains('NavTitle') -and $Report.NavTitle) { $model['navTitle'] = $Report.NavTitle } if ($Report.Contains('AutoRefreshSec') -and [int]$Report.AutoRefreshSec -gt 0) { $model['autoRefresh'] = [int]$Report.AutoRefreshSec } if ($Report.Contains('GeneratedBy') -and $Report.GeneratedBy) { $model['generatedBy'] = $Report.GeneratedBy } if ($Report.Contains('InfoFields') -and @($Report.InfoFields).Count -gt 0) { $model['infoFields'] = @($Report.InfoFields | ForEach-Object { [ordered]@{ label = $_.Label; value = $_.Value } }) } # Global summary (stored separately from Blocks) if ($Report.Contains('Summary') -and @($Report.Summary).Count -gt 0) { $sum = [ordered]@{ items = @($Report.Summary | ForEach-Object { Copy-DhSpec $_ }) } if ($Report.Contains('SummaryOptions') -and $Report.SummaryOptions) { foreach ($k in $Report.SummaryOptions.Keys) { $sum[$k.ToString().ToLower()] = $Report.SummaryOptions[$k] } } $model['summary'] = $sum } # Tables if (@($Report.Tables).Count -gt 0) { $model['tables'] = @($Report.Tables | ForEach-Object { $t = Copy-DhSpec $_ -Drop @('Data') if ($IncludeData) { $t['data'] = @($_.Data) } else { $t['dataRows'] = @($_.Data).Count } $t }) } # Blocks (BlockType -> type, moved to front) if ($Report.Contains('Blocks') -and @($Report.Blocks).Count -gt 0) { $model['blocks'] = @($Report.Blocks | ForEach-Object { $b = Copy-DhSpec $_ -Drop @('BlockType') $ordered = [ordered]@{ type = $_.BlockType } foreach ($k in $b.Keys) { $ordered[$k] = $b[$k] } $ordered }) } # Global filters / alert banners / links if ($Report.Contains('GlobalFilters') -and @($Report.GlobalFilters).Count -gt 0) { $model['globalFilters'] = @($Report.GlobalFilters | ForEach-Object { Copy-DhSpec $_ }) } if ($Report.Contains('AlertBanners') -and @($Report.AlertBanners).Count -gt 0) { $model['alertBanners'] = @($Report.AlertBanners | ForEach-Object { Copy-DhSpec $_ }) } if ($Report.Contains('Links') -and @($Report.Links).Count -gt 0) { $model['links'] = @($Report.Links | ForEach-Object { Copy-DhSpec $_ }) } $yaml = "# DashHtml layout — generated by ConvertTo-DhYaml`n" + (ConvertTo-DhYamlText $model) if ($OutFile) { Set-Content -Path $OutFile -Value $yaml -Encoding UTF8 Write-Verbose "ConvertTo-DhYaml: wrote $OutFile" } else { $yaml } } } function Copy-DhSpec { <# Shallow-clone a spec hashtable, dropping named keys and empty values. #> param([object] $Source, [string[]] $Drop = @()) $out = [ordered]@{} foreach ($k in $Source.Keys) { if ($k -in $Drop) { continue } $v = $Source[$k] # Trim obvious noise: empty strings and empty arrays keep the view clean. if ($v -is [string] -and $v -eq '') { continue } if (($v -is [System.Collections.IEnumerable]) -and ($v -isnot [string]) -and (@($v).Count -eq 0)) { continue } $out[$k] = $v } return $out } |