PowerShellUniversal.Component.Pivot.Demo.psm1
|
function Resolve-ShowcasePath { <# .SYNOPSIS Returns the full path of a file the showcase ships, in the built module or in the source tree. .DESCRIPTION The built module carries the documentation's examples, the data snapshots and the ticket showcase at the paths Build.psd1 names. In the source tree they are at their source; Build.psd1 maps one to the other, so the module also runs straight from a clone of the repository. .PARAMETER Path Path below the built module, e.g. Data or Apps/Docs/examples.ps1. .OUTPUTS System.String #> [CmdletBinding()] [OutputType([string])] param([Parameter(Mandatory)][string]$Path) $built = Join-Path $PSScriptRoot $Path if (Test-Path -LiteralPath $built) { return $built } $buildFile = Join-Path $PSScriptRoot 'Build.psd1' if (Test-Path -LiteralPath $buildFile) { $include = (Import-PowerShellDataFile -LiteralPath $buildFile).Include foreach ($key in $include.Keys) { if ($Path -eq $key -or $Path.StartsWith("$key/")) { $source = Join-Path $PSScriptRoot '..' '..' $include[$key] $rest = $Path.Substring($key.Length).TrimStart('/') if ($rest) { $source = Join-Path $source $rest } if (Test-Path -LiteralPath $source) { return (Resolve-Path -LiteralPath $source).Path } } } } throw ('The showcase misses {0}; build the module with build/Build-Module.ps1.' -f $Path) } function Get-UDPivotShowcaseData { <# .SYNOPSIS Answers a public web API call of the showcase from the snapshot shipped with the module, or live. .DESCRIPTION The showcase's pages call this where an app calls Invoke-RestMethod, so they work without internet access. Without -Live the answer comes from the module's Data folder, one file per address (https://endoflife.date/api/python.json is Data/endoflife.date/api/python.json; an address with a query string is Data/<host>/<path>.json, and Data/Addresses.psd1 holds the exact address it was fetched from). With -Live it calls Invoke-RestMethod with a 30 second timeout. Sources, licences and the attribution each source asks for: Data/SOURCES.md. With -Live it fetches whatever https address it is given: call it with fixed addresses only, never with an address a reader typed or sent (the server would fetch it for them). .PARAMETER Uri The https address of the API call. .PARAMETER Live Fetch the address instead of reading the snapshot. .EXAMPLE Get-UDPivotShowcaseData 'https://endoflife.date/api/python.json' .OUTPUTS What Invoke-RestMethod returns for the address (a JSON array is one object in the pipeline). #> [CmdletBinding()] param( [Parameter(Mandatory, Position = 0)][uri]$Uri, [switch]$Live ) if ($Uri.Scheme -ne 'https') { throw ('Only https addresses: {0}' -f $Uri) } if ($Live) { return Invoke-RestMethod -Uri $Uri -TimeoutSec 30 } $data = Resolve-ShowcasePath -Path 'Data' $relative = '{0}{1}' -f $Uri.Host, $Uri.AbsolutePath if (-not [System.IO.Path]::GetExtension($relative)) { $relative += '.json' } if ($Uri.Query) { # a snapshot stands for exactly the address it was fetched from, query included $addresses = Import-PowerShellDataFile -LiteralPath (Join-Path $data 'Addresses.psd1') if ($addresses[$relative] -ne $Uri.AbsoluteUri) { throw ('No snapshot of {0} in the module; use -Live.' -f $Uri) } } # a snapshot is a .json file below Data/, whatever the address says (no way out of the folder) $root = [System.IO.Path]::GetFullPath($data).TrimEnd([System.IO.Path]::DirectorySeparatorChar) + [System.IO.Path]::DirectorySeparatorChar $file = [System.IO.Path]::GetFullPath((Join-Path $data $relative)) if (-not $file.StartsWith($root, [System.StringComparison]::Ordinal) -or [System.IO.Path]::GetExtension($file) -ne '.json' -or -not (Test-Path -LiteralPath $file -PathType Leaf)) { throw ('No snapshot of {0} in the module; use -Live.' -f $Uri) } Get-Content -LiteralPath $file -Raw | ConvertFrom-Json -NoEnumerate } function New-UDPivotShowcase { <# .SYNOPSIS Returns the showcase app of PowerShellUniversal.Component.Pivot. .DESCRIPTION The app shows New-UDPivotReport on public data and on generated data: the three pivot examples of the documentation on software release cycles from endoflife.date (one line; start view, field names and templates; an app with loading, views per reader and roles), daily weather of six cities from Open-Meteo, a page for the reader's own CSV, JSON and Excel files (read in the browser), and the ticket showcase of the pivot module (5,000 generated tickets, templates, events, field descriptions, page layouts). Public data comes from snapshots shipped with the module, so the app works without internet access; a switch on each page (or -LiveData) fetches it from the APIs instead. A language switch shows the report in English or German. Use it as the whole content of an app: Import-Module PowerShellUniversal.Component.Pivot.Demo New-UDPivotShowcase .PARAMETER LiveData Start with live data from the public APIs instead of the shipped snapshots (needs internet access from the PSU server). .PARAMETER Locale The language the report starts in: en-GB (default) or de-DE. .EXAMPLE New-PSUApp -Name 'PivotShowcase' -BaseUrl '/pivot-showcase' -Content { New-UDPivotShowcase } .OUTPUTS The app PSU renders (New-UDApp). #> # returns the app for PSU to render; changes no state, so no ShouldProcess (as New-UDPivotReport) [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param( [switch]$LiveData, [ValidateSet('en-GB', 'de-DE')][string]$Locale = 'en-GB' ) & (Join-Path $PSScriptRoot 'Apps' 'Showcase.ps1') -LiveData:$LiveData -Locale $Locale } Export-ModuleMember -Function New-UDPivotShowcase, Get-UDPivotShowcaseData |