Public/AssetViews.ps1

## TM AssetViewConfigurations
Function New-TMAssetViewConfiguration {
    <#
    .SYNOPSIS
        Creates or updates an AssetViewConfiguration in TransitionManager.
 
    .DESCRIPTION
        Sends the supplied AssetViewConfiguration object to TM. When `-Update`
        is provided, an existing configuration can be updated instead of creating
        a new one.
 
    .PARAMETER TMSession
        A TMSession object or session name to use for the request. Defaults to
        `'Default'`.
 
    .PARAMETER AssetViewConfiguration
        The AssetViewConfiguration object to create or update.
 
    .PARAMETER PassThru
        Switch indicating that the created or updated configuration should be
        returned.
 
    .PARAMETER Update
        Switch indicating that an existing configuration should be updated.
 
    .EXAMPLE
        $config = Get-TMAssetViewConfiguration -Name 'Default View'
        $config.description = 'The default view for your assets'
        New-TMAssetViewConfiguration -AssetViewConfiguration $config -Update -PassThru
 
        Updates an existing AssetViewConfiguration and returns the result.
 
    .NOTES
        This function resolves the session by calling `Get-TMSession`.
    #>

    param(
        [Parameter(Mandatory = $false)][PSObject]$TMSession = 'Default',
        [Parameter(Mandatory = $true, Position = 0)][PSObject]$AssetViewConfiguration,
        [Parameter(Mandatory = $false)][Switch]$PassThru,
        [Parameter(Mandatory = $false)][Switch]$Update
    )

    ## Get Session Configuration
    $TMSession = Get-TMSession $TMSession

    #Honor SSL Settings
    $TMCertSettings = @{SkipCertificateCheck = $TMSession.AllowInsecureSSL }
    $Instance = $TMSession.TMServer.Replace('/tdstm', '')
    $instance = $instance.Replace('https://', '')
    $instance = $instance.Replace('http://', '')

    ## Action 1, Confirm the name is unique
    $ExistingAssetView = Get-TMAssetViewConfiguration -Name $AssetViewConfiguration.name -TMSession $TMSession

    if ($ExistingAssetView -and -not $Update) {
        if ($PassThru) {
            return $ExistingAssetView
        }
        return
    }

    ## Get the Current AssetView and make updates to it
    if ($ExistingAssetView -and $Update) {

        ## Update the Schema and other details from the provided data
        $ExistingAssetView.schema = $AssetViewConfiguration.schema
        $ExistingAssetView.description = $AssetViewConfiguration.description

        ## REPLACE the incoming data with the Updated copy of the existing
        $AssetViewConfiguration = $ExistingAssetView

    }

    ## Ensure that the AssetViewConfiguration has proper custom columnN replacement
    $FieldToLabelMap = Get-TMFieldToLabelMap -TMSession $TMSession
    if ($AssetViewConfiguration.schema.sort.property -match 'customN\|.*\|') {

        ## Look up the column fieldname from the TemplateKey label lookup
        # $LookupKey = "customN|$($AssetViewConfiguration.schema.sort.domain.ToUpper())|$($AssetViewConfiguration.schema.sort.property)|"
        $LookupKey = $AssetViewConfiguration.schema.sort.property
        if ($FieldToLabelMap.TemplateKeys[$LookupKey]) {
            $AssetViewConfiguration.schema.sort.property = $FieldToLabelMap.TemplateKeys[$LookupKey]
        } else {
            Write-Host "Sort Field is missing: $LookupKey, this view will have to be edited to correct this." -ForegroundColor Red
        }
    }

    ## Update the Columns
    foreach ($column in $AssetViewConfiguration.schema.columns) {
        if ($column.property -eq 'customN') {
            $DomainClass = $column.domain -eq 'common' ? 'APPLICATION' : $column.domain.ToUpper()
            $LookupKey = "customN|$DomainClass|$($column.label)|"
            $column.property = $FieldToLabelMap.TemplateKeys[$LookupKey]
        }
    }

    # Step 2, Create the AssetViewConfiguration
    $uri = 'https://'
    $uri += $instance
    $uri += '/tdstm/ws/assetExplorer/view'
    Set-TMHeaderContentType -ContentType JSON -TMSession $TMSession

    ## If the AssetView is not in the format to create a new one, transform it
    if ($Update -and $ExistingAssetView) {
        $uri += "/$($ExistingAssetView.id)"

        ## Create the Put Body
        $PutBody = $AssetViewConfiguration | ConvertTo-Json -Depth 100

        ## Post a New AssetViewConfiguration
        try {
            $response = Invoke-WebRequest -Method Put -Uri $uri -WebSession $TMSession.TMWebSession -Body $PutBody @TMCertSettings
            if ($response.StatusCode -eq 200) {
                $responseContent = $response.Content | ConvertFrom-Json
                if ($responseContent.status -eq 'success') {
                    if ($PassThru) { return $responseContent.data.AssetViewConfiguration } else { return }
                }
            }
        } catch {
            Write-Host 'Unable to create AssetViewConfiguration.'
            return $_
        }

    } else {
        ## This is a New AssetView
        ## Ensure the body is formatted properly
        if ($AssetViewConfiguration.PSObject.Properties.name -notcontains 'saveOptions') {

            $PostBody = [PSCustomObject]@{
                saveOptions  = [PSCustomObject]@{
                    canoverride   = $false
                    canShare      = $true
                    save          = $false
                    saveAsOptions = @('MY_VIEW')
                }
                isFavorite   = $AssetViewConfiguration.isFavorite
                isOwner      = $AssetViewConfiguration.isOwner
                isShared     = $AssetViewConfiguration.isShared
                isSystem     = $AssetViewConfiguration.isSystem
                schema       = $AssetViewConfiguration.schema
                description  = $AssetViewConfiguration.description
                queryString  = [PSCustomObject]@{}
                saveAsOption = 'MY_VIEW'
                name         = $AssetViewConfiguration.name
            } | ConvertTo-Json -Depth 100
        } else {
            $PostBody = $AssetViewConfiguration | ConvertTo-Json -Depth 100
        }

        ## Post a New AssetViewConfiguration
        try {
            $response = Invoke-WebRequest -Method Post -Uri $uri -WebSession $TMSession.TMWebSession -Body $PostBody @TMCertSettings
            if ($response.StatusCode -eq 200) {
                $responseContent = $response.Content | ConvertFrom-Json
                if ($responseContent.status -eq 'success') {
                    if ($PassThru) { return $responseContent.data.AssetViewConfiguration } else { return }
                }
            }
        } catch {
            Write-Host 'Unable to create AssetViewConfiguration.'
            return $_
        }
    }
}
Function Get-TMAssetView {
    <#
    .SYNOPSIS
        Gets AssetViews from TransitionManager.
 
    .DESCRIPTION
        Retrieves AssetView data from TM and optionally filters them by name,
        identifier, or a filter object. Pagination can be controlled with
        `-Limit` and `-Offset`.
 
    .PARAMETER Name
        The AssetView name to retrieve.
 
    .PARAMETER Id
        The AssetView identifier to retrieve.
 
    .PARAMETER Filter
        An optional filter object used to narrow the returned AssetViews.
 
    .PARAMETER TMSession
        A TMSession object or session name to use for the request. Defaults to
        `'Default'`.
 
    .PARAMETER Limit
        The maximum number of rows to return. A value of `0` uses the function's
        default behavior.
 
    .PARAMETER Offset
        The starting offset to use when paging through results.
 
    .EXAMPLE
        Get-TMAssetView -Name 'Production Devices'
 
        Retrieves the data in the AssetView named `Production Devices`.
 
    .NOTES
        Use `-Filter`, `-Limit`, and `-Offset` to page through larger result sets.
    #>

    param(
        [Parameter(Mandatory = $false)][String]$Name,
        [Parameter(Mandatory = $false)][String]$Id,
        [Parameter(Mandatory = $false)][PSObject]$Filter,
        [Parameter(Mandatory = $false)][PSObject]$TMSession = 'Default',
        [Parameter(Mandatory = $false)][Int]$Limit = 0,
        [Parameter(Mandatory = $false)][Int]$Offset = 0

    )
    # Get Session Configuration
    $TMSession = Get-TMSession $TMSession

    #Honor SSL Settings
    $TMCertSettings = @{SkipCertificateCheck = $TMSession.AllowInsecureSSL }

    ## Make sure we have a view to use
    if (-not $Id -and $Name) {
        $AssetViewId = (Get-TMAssetViewConfiguration -Name $Name).id
    } else {
        $AssetViewId = $Id
    }


    ## Get the Field Schema for the AssetView
    $Instance = $TMSession.TMServer.Replace('/tdstm', '')
    $instance = $instance.Replace('https://', '')
    $instance = $instance.Replace('http://', '')

    $uri = 'https://'
    $uri += $instance
    $uri += '/tdstm/ws/assetExplorer/view/'
    $uri += $AssetViewId

    ## Request the data
    $response = Invoke-WebRequest -Method Get -Uri $uri -WebSession $TMSession.TMWebSession @TMCertSettings

    ## Ensure Success
    if ($response.StatusCode -eq 200) {
        $responseContent = $response.Content | ConvertFrom-Json
        if ($responseContent.status -eq 'success') {

            ## Assign the results to a Variable
            $AssetView = $responseContent.data.dataView

        }
    }

    ## Return an error if there is no AssetView
    if (-not $AssetView) {
        throw 'Unable to Get AssetView, check name and try again'
    }

    ## Construct a query of the view endpoint using the schema from the Provided AssetView
    $uri = 'https://'
    $uri += $instance
    $uri += '/tdstm/ws/assetExplorer/query/'
    $uri += $AssetView.id

    ## Create a Query Post
    $Body = @{
        filters      = @{
            columns = $AssetView.schema.columns
            domains = $AssetView.schema.domains
        }
        limit        = $Limit
        offset       = $Offset
        sortDomain   = $AssetView.schema.sort.domain
        sortOrder    = $AssetView.schema.sort.order
        sortProperty = $AssetView.schema.sort.property
    }

    ## Update the Asset Class Filtering
    if ($Filter) {
        $Body.filters = $Filter
    }

    $PostBody = $Body | ConvertTo-Json -Depth 10 -Compress

    ## Request the data
    $response = Invoke-WebRequest -Method Post -Uri $uri -Body $PostBody -WebSession $TMSession.TMWebSession @TMCertSettings

    ## Ensure Success
    if ($response.StatusCode -eq 200) {
        $responseContent = $response.Content | ConvertFrom-Json
        if ($responseContent.status -eq 'success') {

            ## Assign the results to a Variable
            $Assets = $responseContent.data.assets

        }
    } elseif ($response.StatusCode -eq 204) {
        return
    }

    ## Return located assets
    if ($Assets) { return $Assets }

}
Function Get-TMAssetViewConfiguration {
    <#
    .SYNOPSIS
        Gets AssetViewConfigurations from TransitionManager.
 
    .DESCRIPTION
        Retrieves AssetViewConfigurations from TM and optionally filters
        by name. Additional switches can exclude system entries, reset identifiers,
        and return the configuration objects directly.
 
    .PARAMETER Name
        The AssetViewConfiguration name to retrieve.
 
    .PARAMETER TMSession
        A TMSession object or session name to use for the request. Defaults to
        `'Default'`.
 
    .PARAMETER ResetIDs
        Switch indicating that identifiers on the returned objects should be
        refreshed or normalized during retrieval.
 
    .PARAMETER ExcludeSystem
        Switch indicating that system-defined configurations should be excluded.
 
    .PARAMETER PassThru
        Switch indicating that the retrieved configuration objects should be
        returned directly.
 
    .EXAMPLE
        Get-TMAssetViewConfiguration -ExcludeSystem -PassThru
 
        Retrieves non-system AssetView configurations and returns them as objects.
 
    .NOTES
        This function is useful when preparing configuration objects for reuse.
    #>

    param(
        [Parameter(Mandatory = $false)][String]$Name,
        [Parameter(Mandatory = $false)][PSObject]$TMSession = 'Default',
        [Parameter(Mandatory = $false)][Switch]$ResetIDs,
        [Parameter(Mandatory = $false)][Switch]$ExcludeSystem,
        [Parameter(Mandatory = $false)][Switch]$PassThru

    )
    ## Get Session Configuration
    $TMSession = Get-TMSession $TMSession

    #Honor SSL Settings
    $TMCertSettings = @{SkipCertificateCheck = $TMSession.AllowInsecureSSL }

    $Instance = $TMSession.TMServer.Replace('/tdstm', '')
    $instance = $instance.Replace('https://', '')
    $instance = $instance.Replace('http://', '')

    $uri = 'https://'
    $uri += $instance
    $uri += '/tdstm/ws/assetExplorer/views'
    try {
        $response = Invoke-WebRequest -Method Get -Uri $uri -WebSession $TMSession.TMWebSession @TMCertSettings
    } catch {
        return $_
    }

    if ($response.StatusCode -eq 200) {
        $Result = ($response.Content | ConvertFrom-Json).data
    } else {
        return 'Unable to get AssetViews.'
    }

    ## Remove System Views
    if ($ExcludeSystem) {
        $Result = $Result | Where-Object { $_.isSystem -eq $false }
    }
    if ($Name) {
        $Result = $Result | Where-Object { $_.name -eq $Name }
    }

    ## Sort the AssetViews by Name
    $Result = $Result | Sort-Object -Property 'Name'

    if ($ResetIDs) {
        $FieldToLabelMap = Get-TMFieldToLabelMap -TMSession $TMSession
        for ($i = 0; $i -lt $Result.Count; $i++) {

            ## Clear the ID
            $Result[$i].id = $null

            ## Update Sort property if it is a custom field
            if ($Result[$i].schema.sort.property -match 'custom\d+') {
                $FieldClass = $Result[$i].schema.sort.domain -eq 'common' ? 'APPLICATION' : $Result[$i].schema.sort.domain
                $FieldLabel = $FieldToLabelMap.$FieldClass.($Result[$i].schema.sort.property)

                if ($FieldLabel) {
                    $Result[$i].schema.sort.property = "customN|$FieldClass|$FieldLabel|"
                } else {
                    Write-Host "This AssetView seems to be missing a Field in the configuration: $($Result[$i].schema.sort | ConvertTo-Json )"
                }
            }

            ## Update the Columns
            foreach ($column in $Result[$i].schema.columns) {
                if ($column.property -match 'custom\d+') {
                    $column.property = 'customN'

                }
            }
        }
    }
    return $Result

}