I would like to share something I worked on the last days.
If many people are interested in I can extend it and will open a GH repo.
But this is only my beta show off:
A UD Form can be generated by a command. I havent used it for things like New-ADUser
or Set-ADUser
but can also be possible. I just used this for my own PS Module this is jsut wrapping PS into a REST request.
But here is my example which is making a US form from the commands Test-CommandForm
parameter:
function Test-CommandForm
{
param
(
[Parameter(ParameterSetName= "Default")]
[String]$String,
[Parameter(ParameterSetName= "Default")]
[ValidateSet('TRACE', 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL')]
[String]$StringValidateSet,
[Parameter(ParameterSetName= "Default")]
[bool]$Bool,
[Parameter(ParameterSetName= "Default")]
[DataBinding(Command='Get-ReferenceObjectData', LabelAttribute = 'Name', ValueAttribute = 'ID')]
$ReferenceObject
)
Show-UDToast -Duration 10000 -Message "do some logic with passed parameter"
}
function Get-ReferenceObjectData
{
@(
[PSCustomObject]@{ID=(New-Guid); Name='test1'}
[PSCustomObject]@{ID=(New-Guid); Name='test2'}
[PSCustomObject]@{ID=(New-Guid); Name='test3'}
[PSCustomObject]@{ID=(New-Guid); Name='test4'}
[PSCustomObject]@{ID=(New-Guid); Name='test5'}
)
}
$Command = 'Test-CommandForm'
New-UDForm -Content {
New-UDGeneratedFormBody -Command $Command
} -OnSubmit {
$Parameters = ConvertFrom-Json $Body
$Parameters = ConvertTo-HashTable -Object $Parameters
& "$Command" @Parameters
}
Currently only the following types of parameters are allowed:
- string > textbox
- string with a ValidationSet > select
- bool > checkbox
- parameter which requires an object from another command (e.g.
Get-ReferenceObjectData
) > select
This can be really helpful in order to minimize the code for a dashboard and automate it.
I used this currently for all ma New-
or Set-
commands for my own API PS Module.
This is how it looks like in my project by just using the following lines of code I can have a create and edit form for all types of objects as soon as there is an existing PS command.
PS: the commands New-UDNewButton
and New-UDEditButton
are not included in this code as it is just a show case how the “generated form by command” can be used.
New-UDNewButton -Command "New-ADWDWProject" -ObjectType "Project" -RedirectUrl '/datawarehouse/project'
New-UDEditButton -Command 'Set-ADWDWProject' -ObjectDisplayName $Item.Name -ObjectID $Item.ID -RedirectUrl '/datawarehouse/project'
This is the full code wrapped into a demo:
Import-Module UniversalDashboard.Community -Force
if(Get-UDDashboard)
{
Get-UDDashboard | Stop-UDDashboard
}
#region helper function
function ConvertTo-HashTable
{
param
(
[Parameter (Mandatory = $true, ParameterSetName = "Default")]
$Object
)
$Object.PSObject.Properties | foreach -begin {$h=@{}} -process {$h."$($_.Name)" = $_.Value} -end {$h}
}
#endregion
$Dashboard = New-UDDashboard -Title 'GenerateCommandForm' -Content {
#region generate function
function New-UDGeneratedFormBody
{
param
(
[Parameter (Mandatory = $true, ParameterSetName = "Default")]
[string]$Command,
[Parameter (Mandatory = $false, ParameterSetName = "Default")]
[string[]]$ExcludedParameters = @()
)
#region custom attribute
Class DataBindingAttribute : Attribute {
[string]$Command
[string]$LabelAttribute
[string]$ValueAttribute
DataBindingAttribute()
{
}
DataBindingAttribute([string]$Command, [string]$LabelAttribute, [string]$ValueAttribute)
{
$this.Command = $Command
$this.LabelAttribute = $LabelAttribute
$this.ValueAttribute = $ValueAttribute
}
}
#endregion
$Parameters = (Get-Command $Command).Parameters.keys| %{(Get-Command $Command).Parameters["$_"]}
$Parameters = $Parameters | ?{!$_.ParameterSets["__AllParameterSets"]}
#exclude parameters
$Parameters = $Parameters | ?{$_.Name -notin $ExcludedParameters}
foreach($Parameter in $Parameters)
{
$ValidateSetAttribute = $Parameter.Attributes | ?{$_.TypeId.Name -eq 'ValidateSetAttribute'}
$DataBindingAttribute = $Parameter.Attributes | ?{$_.TypeId.Name -eq 'DataBindingAttribute'}
if($DataBindingAttribute)
{
$Data = @(& $DataBindingAttribute.Command)
New-UDSelect -Id $Parameter.Name -Label $Parameter.Name -Option {
$Data | Sort $DataBindingAttribute.LabelAttribute | %{New-UDSelectOption -Name $_."$($DataBindingAttribute.LabelAttribute)" -Value $_."$($DataBindingAttribute.ValueAttribute)"}
}
}
elseif($ValidateSetAttribute)
{
New-UDSelect -Id $Parameter.Name -Label $Parameter.Name -Option {
$ValidateSetAttribute.ValidValues | Sort | %{New-UDSelectOption -Name $_ -Value $_}
}
}
elseif($Parameter.ParameterType -in @('string', 'System.String'))
{
New-UDTextbox -Id $Parameter.Name -Label $Parameter.Name
}
elseif($Parameter.ParameterType -in @('bool', 'System.Boolean'))
{
New-UDCheckbox -Id $Parameter.Name -Label $Parameter.Name
}
else
{
throw "unexpected command parameter [$($Parameter.Name)] type [$($Parameter.ParameterType)]"
}
}
}
#endregion
function Get-ReferenceObjectData
{
@(
[PSCustomObject]@{ID=(New-Guid); Name='test1'}
[PSCustomObject]@{ID=(New-Guid); Name='test2'}
[PSCustomObject]@{ID=(New-Guid); Name='test3'}
[PSCustomObject]@{ID=(New-Guid); Name='test4'}
[PSCustomObject]@{ID=(New-Guid); Name='test5'}
)
}
function Test-CommandForm
{
param
(
[Parameter(ParameterSetName= "Default")]
[String]$String,
[Parameter(ParameterSetName= "Default")]
[ValidateSet('TRACE', 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL')]
[String]$StringValidateSet,
[Parameter(ParameterSetName= "Default")]
[bool]$Bool,
[Parameter(ParameterSetName= "Default")]
[DataBinding(Command='Get-ReferenceObjectData', LabelAttribute = 'Name', ValueAttribute = 'ID')]
$ReferenceObject
)
Show-UDToast -Duration 10000 -Message "do some logic with passed parameter"
}
#region main logic
$Command = 'Test-CommandForm'
New-UDForm -Content {
New-UDGeneratedFormBody -Command $Command
} -OnSubmit {
$Parameters = ConvertFrom-Json $Body
$Parameters = ConvertTo-HashTable -Object $Parameters
& "$Command" @Parameters
}
#endregion
}
Start-UDDashboard -Name 'GenerateCommandForm' -Dashboard $Dashboard -Port 1000 -Wait