PowerShellUniversal.Component.Perspective.psm1
|
$ErrorActionPreference = 'Stop' #region Shared code and asset registration # The build copies the repository's shared/powershell/*.ps1 into Private/; from a source checkout # they are loaded from there directly. $private = Join-Path $PSScriptRoot 'Private' if (-not (Test-Path -LiteralPath $private)) { $private = Join-Path $PSScriptRoot '..' '..' 'shared' 'powershell' } foreach ($file in Get-ChildItem -LiteralPath $private -Filter '*.ps1' -File) { . $file.FullName } $Script:AssetId = Register-PSUComponentAsset -Path $PSScriptRoot #endregion function New-UDPerspective { <# .SYNOPSIS A Perspective datagrid, pivot table and chart in one, for PowerShell Universal apps. .DESCRIPTION Pass the data as it comes - a DataTable from SQL, objects from Invoke-RestMethod or any PowerShell command. Readers rearrange the view themselves in the configuration panel: group and split by columns (a pivot), filter, sort, aggregate, switch between the datagrid and the charts. The parameters set the view it starts with. The data is held by Perspective's WebAssembly engine in a Web Worker in the browser, so tens of thousands of rows stay fast. Column names are matched without regard to case. .PARAMETER Id Component id. Default: a new GUID. .PARAMETER Data Rows: a DataTable, objects, hashtables, or a script block returning them. .PARAMETER Plugin The view to start with: Datagrid (default) or a chart: X Bar, Y Bar, Y Line, Y Area, Y Scatter, X/Y Scatter, X/Y Line, Density, Treemap, Sunburst, Heatmap, Candlestick, OHLC, Map Scatter, Map Line, Map Density (the map charts need longitude and latitude columns). .PARAMETER Columns Columns to show, in this order. Default: all. .PARAMETER GroupBy Row groups (pivot rows), e.g. Customer, Team. .PARAMETER SplitBy Column groups (pivot columns), e.g. Priority. .PARAMETER Aggregates How grouped values are combined per column: @{ Tickets = 'sum'; LeadHours = 'avg' } (Perspective's names: sum, avg, count, distinct count, min, max, median, first, last, ...). .PARAMETER Sort 'Column' (ascending) or 'Column desc', one or more. .PARAMETER Filter 'Column == value', 'Column > 5', 'Column contains text', one or more. .PARAMETER Settings Open the configuration panel at the start (readers can open it any time). .PARAMETER Config Perspective's full viewer configuration (as from the viewer's "copy config"), merged over the one the parameters built. .PARAMETER Height Height, e.g. 480px (default) or 70vh. .PARAMETER Width Width. Default: the container's. .PARAMETER Theme Auto (follows the app's light/dark switch, default), Light or Dark. .PARAMETER ClassName CSS class of the outer element. .PARAMETER Style CSS styles of the outer element. .PARAMETER OnClick Runs on the server when a cell is clicked. $EventData: row (the values of the clicked row or group), columnNames, filter (the group and split values that lead to the cell, as [column, operator, value]). .EXAMPLE New-UDPerspective -Data (Get-Process | Select-Object Name, CPU, WorkingSet64) -Sort 'CPU desc' .EXAMPLE New-UDPerspective -Data $tickets -GroupBy Team -SplitBy Priority -Columns Id -Aggregates @{ Id = 'count' } -Settings .OUTPUTS System.Collections.Hashtable #> # describes a component for PSU to render; changes no state, so no ShouldProcess [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] [OutputType([hashtable])] param( [string]$Id = [guid]::NewGuid().ToString(), [Parameter(Mandatory)][AllowNull()][object]$Data, [ValidateSet('Datagrid', 'X Bar', 'Y Bar', 'Y Line', 'Y Area', 'Y Scatter', 'X/Y Scatter', 'X/Y Line', 'Density', 'Treemap', 'Sunburst', 'Heatmap', 'Candlestick', 'OHLC', 'Map Scatter', 'Map Line', 'Map Density')] [string]$Plugin = 'Datagrid', [string[]]$Columns, [string[]]$GroupBy, [string[]]$SplitBy, [hashtable]$Aggregates, [string[]]$Sort, [string[]]$Filter, [switch]$Settings, [hashtable]$Config, [string]$Height = '480px', [string]$Width, [ValidateSet('Auto', 'Light', 'Dark')][string]$Theme = 'Auto', [string]$ClassName, [hashtable]$Style, [Endpoint]$OnClick ) if (-not $Script:AssetId) { throw 'PowerShellUniversal.Component.Perspective: the JavaScript bundle (index.<hash>.bundle.js) was not found next to the module, or the module was imported outside PowerShell Universal.' } if ($OnClick) { $OnClick.Register($Id, $PSCmdlet) } # one array (ConvertTo-PSUComponentData returns it as a single object; @() would nest it) $rows = ConvertTo-PSUComponentData -InputObject $Data $props = @{ assetId = $Script:AssetId isPlugin = $true type = 'ud-perspective' id = $Id data = $rows # PSU camelCases the keys of the rows on their way to the browser; Perspective shows the names # as they are, so the original ones travel along as values (which PSU leaves alone) columnNames = @($rows | Select-Object -First 1 | ForEach-Object { $_.PSObject.Properties.Name }) plugin = $Plugin settings = [bool]$Settings height = $Height theme = $Theme.ToLowerInvariant() } $map = [ordered]@{ Columns = 'columns'; GroupBy = 'groupBy'; SplitBy = 'splitBy'; Aggregates = 'aggregates'; Sort = 'sort'; Filter = 'filter'; Config = 'config'; Width = 'width'; ClassName = 'className'; Style = 'style' } foreach ($name in $map.Keys) { if ($PSBoundParameters.ContainsKey($name)) { $props[$map[$name]] = $PSBoundParameters[$name] } } if ($OnClick) { $props['onClick'] = $OnClick } $props } Export-ModuleMember -Function New-UDPerspective |