Public/Add-DhAlertBanner.ps1
|
function Add-DhAlertBanner { <# .SYNOPSIS Add a top-of-page alert banner to the dashboard. .DESCRIPTION Renders a strip *above* the KPI summary tiles. Useful for surfacing current operational conditions — open incidents, recent failures, compliance breaches — so they are visible the moment the report opens. Multiple banners can be added; they stack vertically in the order they were declared. Each banner carries a severity (info / ok / warning / critical) which drives the colour via the existing RAG palette. Optionally: -Dismissible — adds a close button; the dismissal is remembered in the URL hash so it survives a page reload. -Action — adds a button that either navigates to a registered table (with an optional pre-filter) or opens an external URL. Distinct from Add-DhEventFeed (v1.4+): a banner surfaces a single current condition; an event feed lists a chronological audit trail. .PARAMETER Report Dashboard object from New-DhDashboard. .PARAMETER Id Unique identifier (alphanumeric, dash, or underscore). Used as the DOM id and as the dismissal key in the URL hash. .PARAMETER Severity Visual treatment: 'info' | 'ok' | 'warning' | 'critical'. Default: 'info'. .PARAMETER Message The text shown in the banner (required). May contain inline HTML — use Add-DhHtmlBlock for richer content. .PARAMETER Icon Optional emoji / unicode glyph shown before the message. .PARAMETER Dismissible Adds a close (x) button. Dismissal persists across reloads via the URL hash. The banner re-appears in a new browser session. .PARAMETER Action Optional action button hashtable: @{ Label = 'View incidents' # REQUIRED — button text TableId = 'incidents' # navigate to this registered table Filter = 'severity:critical' # optional pre-filter text # ─ OR ─ Url = 'https://...' # external link instead of TableId } .EXAMPLE # Simplest banner — just a message Add-DhAlertBanner -Report $report -Id 'maintenance' ` -Severity 'info' -Message 'Maintenance window tonight 22:00–02:00 UTC' .EXAMPLE # Critical alert with action button — clicking jumps to a filtered table Add-DhAlertBanner -Report $report -Id 'open-incidents' ` -Severity 'critical' -Icon '!' ` -Message '3 critical incidents open in the last 24h' ` -Dismissible ` -Action @{ Label='View incidents'; TableId='incidents'; Filter='critical' } .EXAMPLE # External link Add-DhAlertBanner -Report $report -Id 'release-notes' ` -Severity 'ok' -Message 'Patch level KB5044277 applied to 98% of hosts' ` -Action @{ Label='Open KB'; Url='https://support.microsoft.com/kb/5044277' } #> [CmdletBinding()] param( [Parameter(Mandatory)] [System.Collections.Specialized.OrderedDictionary] $Report, [Parameter(Mandatory)] [ValidatePattern('^[A-Za-z0-9_-]+$')] [string] $Id, [Parameter(Mandatory)] [string] $Message, [ValidateSet('info','ok','warning','critical')] [string] $Severity = 'info', [string] $Icon = '', [switch] $Dismissible, [hashtable] $Action = $null, # v1.4.2+ — optional NavGroup binding. When set, the banner is visible # only while the matching nav group (and optional subgroup) is active. # Without these, the banner stays page-global (visible everywhere) as # in v1.4.x — full backward compatibility. [string] $NavGroup = '', [string] $NavSubGroup = '' ) # Init the collection lazily — keeps reports that don't use banners clean if (-not $Report.Contains('AlertBanners')) { $Report['AlertBanners'] = [System.Collections.Generic.List[hashtable]]::new() } # Duplicate-Id guard (same rule as Add-DhTable) foreach ($existing in $Report['AlertBanners']) { if ($existing.Id -eq $Id) { throw "Add-DhAlertBanner: A banner with Id '$Id' already exists in this report. Use a unique Id." } } # Validate Action shape when provided $normAction = $null if ($Action) { if (-not $Action.Contains('Label') -or [string]::IsNullOrWhiteSpace([string]$Action.Label)) { throw "Add-DhAlertBanner: -Action requires a non-empty 'Label' key." } $hasTableId = $Action.Contains('TableId') -and -not [string]::IsNullOrWhiteSpace([string]$Action.TableId) $hasUrl = $Action.Contains('Url') -and -not [string]::IsNullOrWhiteSpace([string]$Action.Url) if (-not $hasTableId -and -not $hasUrl) { throw "Add-DhAlertBanner: -Action requires either a 'TableId' key (jump to table) or a 'Url' key (external link)." } if ($hasTableId -and $hasUrl) { throw "Add-DhAlertBanner: -Action must specify EITHER 'TableId' OR 'Url', not both." } $normAction = @{ Label = [string]$Action.Label TableId = if ($hasTableId) { [string]$Action.TableId } else { '' } Filter = if ($Action.Contains('Filter')) { [string]$Action.Filter } else { '' } Url = if ($hasUrl) { [string]$Action.Url } else { '' } } } $banner = [ordered]@{ Id = $Id Severity = $Severity Message = $Message Icon = $Icon Dismissible = [bool]$Dismissible Action = $normAction NavGroup = $NavGroup NavSubGroup = $NavSubGroup } $Report['AlertBanners'].Add($banner) Write-Verbose "Add-DhAlertBanner: Added '$Id' (severity=$Severity, dismissible=$([bool]$Dismissible))." } |