How to load dashboards into pages?

Product: PowerShell Universal
Version: 2.0.2

Hey everyone, apologies if this is a noob question.

I’ve built out 3 stand-alone dashboards, which all work just fine. Now, I need to turn them into pages. The idea is to have a landing page (home page) with navigation to the other pages, and then load those script files (dashboards) in as the pages. Creating something like a portal. This is for a demo I’m building out to sell management on UD, and the first time I’ve tried to work with pages.

I’ve tried using the below, taken from the Pages Component of the UD documentation. I get a dashboard with the 3 pages, and I get navigation, but all the pages are blank. Also, the log file is clean.

$UDScriptRoot = $PSScriptRoot
$Pages = @()
$Pages += New-UDPage -Name 'AD Information' -Content {
    . "$UDScriptRoot\ADInfo.ps1"
}

$Pages += New-UDPage -Name 'Scripting Metrics' -Content {
    . "$UDScriptRoot\ScriptingMetrics.ps1"
}

$Pages += New-UDPage -Name 'Server Health Check' -Content {
    . "$UDScriptRoot\Server_HealthCheck.ps1"
}

New-UDDashboard -Title 'Pages' -Pages $Pages

How can I get this to work? Do I need to edit the stand-alone dashboards in some way, so they can be loaded as pages? Is there some other way I need to load them?

Thanks,
Rob

This should work.

Can you try this?

$Pages += New-UDPage -Name 'AD Information' -Content {
     New-UDTypography $UDScriptRoot
    . "$UDScriptRoot\ADInfo.ps1"
}

Also, can you share a snippet of what is in one of your pages?

Hey Adam,

I’ve updated to what you’ve shown. The page now shows the value of $UDScriptRoot at the top of the page, but otherwise it’s still blank. I’ve verified the scripts are located at the value: C:\ProgramData\UniversalAutomation\Repository

Took it down to:

$UDScriptRoot = $PSScriptRoot
$Pages = @()
$Pages += New-UDPage -Name 'AD Information' -Content {
    New-UDTypography $UDScriptRoot
    . "$UDScriptRoot\ADInfo.ps1"
}
New-UDDashboard -Title 'Pages' -Pages $Pages

Below is a dump of my ADInfo.ps1 script file (dashboard)…couple of things changed to protect the innocent :wink:

function ErrorMessage ($errorMessage) {
    New-UDTypography -Variant h5 -Text "We have encountered an error!" -Style @{color='Red' } -Paragraph
    New-UDParagraph -Content {
        New-UDHtml -Markup ("$errorMessage<br><br>")
        New-UDHtml -Markup ("<b>The latest error in the pipeline:</b><br>")
        New-UDHtml -Markup ("$($error)<br><br>")
        New-UDHtml -Markup ("<b>You can refresh the page and try again.  If you continue to have this problem, contact an administrator.</b><br>")
        }# New-UDParagraph
    break
}# function ErrorMessage

# Start the dashbaord
New-UDDashboard -Title "Active Directory Information" -Content {
    # Wrap everything in New-UDDynamic, so we can use New-UDProgress with -LoadingComponent
    New-UDDynamic -Content {
        # Set Domain Controller
        $DC = "<name of DC>"

#region Domain and Forest Info
        # Get Domain and Forest Info
        Try {$domainInfo = Get-ADDomain -Server $DC -ErrorAction Stop}

        Catch
            {
            $errorMessage = "There was a problem with Get-ADDomain; which populates `$domainInfo<br />`$DC = `"$DC`""
            ErrorMessage $errorMessage
            }# Catch

        Try {$forestInfo = Get-ADForest -Server $DC -ErrorAction Stop}

        Catch
            {
            $errorMessage = "There was a problem with Get-ADForest; which populates `$forestInfo<br />`$DC = `"$DC`""
            ErrorMessage $errorMessage
            }# Catch

        # Compile objects of FSMO Roles data, then load into a table
        $FSMORoles = @(
            [PSCustomObject]@{
                Name = 'PDC Emulator'
                Value = $domainInfo.PDCEmulator
                }    
            [PSCustomObject]@{
                Name = 'RID Master'
                Value = $domainInfo.RIDMaster
                }
            [PSCustomObject]@{
                Name = 'Infrastructure Master'
                Value = $domainInfo.InfrastructureMaster
                }
            [PSCustomObject]@{
                Name = 'Schema Master'
                Value = $forestInfo.SchemaMaster
                }
            )# $FSMORoles

        $columns_FSMORoles = @(
            New-UDTableColumn -Property Name -Title "Role"
            New-UDTableColumn -Property Value -Title "Domain Controller"
            )# $columns_FSMORoles

        $table_FSMORoles = New-UDTable -Data $FSMORoles -Columns $columns_FSMORoles

        # Load the table into a card
        $card_FSMORoles = New-UDCard -Title "FSMO Roles" -Content {$table_FSMORoles}

        # Compile objects of AD Functional Level data, then load into a table
        $functionalLevels = @(
            [PSCustomObject]@{
                Name = 'Forest Mode'
                Value = $forestInfo.ForestMode.ToString()
                }
            [PSCustomObject]@{
                Name = 'Domain Mode'
                Value = $domainInfo.DomainMode.ToString()
                }
            )# $functionalLevels

        $columns_functionalLevels = @(
            New-UDTableColumn -Property Name -Title "Mode"
            New-UDTableColumn -Property Value -Title "Level"
            )# $columns_functionalLevels

        $table_functionalLevels = New-UDTable -Data $functionalLevels -Columns $columns_functionalLevels

        # Load the table into a card
        $card_FunctionalLevels = New-UDCard -Title "AD Functional Levels" -Content {$table_functionalLevels}
#endregion Domain and Forest Info

#region computers
        # Load dynamically updating data of AD Computers into a card
        $card_Computers = New-UDDynamic -Id 'computers' -Content {

            # Get all AD Computers
            Try
                {
                $OSTypes = Get-ADComputer -Filter * -Properties OperatingSystem -Server $DC -ErrorAction Stop |
                    Select-Object Name,OperatingSystem | Sort-Object OperatingSystem
                }# Try

            Catch
                {
                $errorMessage = "There was a problem with Get-ADComputer; which populates `$OSTypes<br />`$DC = `"$DC`""
                ErrorMessage $errorMessage
                }# Catch

            # Split computers into various Operating Systems
            $winOSs = $OSTypes | Where-Object {$_.OperatingSystem -like "Windows *"}
            $unknownOSs = $OSTypes | Where-Object {$_.OperatingSystem -eq "unknown"}
            $macOSs = $OSTypes | Where-Object {$_.OperatingSystem -like "Mac *"}
            $nixOSs = $OSTypes | Where-Object {$_.OperatingSystem -notlike "Windows *" -and $_.OperatingSystem -ne "unknown" -and $_.OperatingSystem -notlike "Mac *"}
        
            # Set the Computers pie chart colors.  Note; colors are applied in order of the collection of objects ($OSCounts)
            $pieColors_Computers = "Green","Red","Blue","Yellow"

            New-UDCard -Title "Active Directory Computers:  $($OSTypes.count)"-Content {
                # Create array of objects, for our OS counts
                $OSCounts = @(
                    [PSCustomObject]@{
                        Name = 'Windows'
                        Value = $winOSs.count
                        }
                    [PSCustomObject]@{
                        Name = 'Linux'
                        Value = $nixOSs.count
                        }
                    [PSCustomObject]@{
                        Name = 'Mac'
                        Value = $macOSs.count
                        }
                    [PSCustomObject]@{
                        Name = 'Unknown'
                        Value = $unknownOSs.count
                        }
                    )# $OSCounts

                # Create the Computers pie chart options
                $options_Pie_Computers = @{
                    Type = 'pie'
                    Data = $OSCounts
                    BackgroundColor = $pieColors_Computers
                    BorderColor = '#c61d4a'
                    HoverBackgroundColor = 'Cyan'
                    HoverBorderColor = '#451dc6'
                    DataProperty = 'Value'
                    LabelProperty = 'Name'
                    }# $options_Pie_Computers

                New-UDChartJS @options_Pie_Computers
                }# New-UDCard
            }<# $card_Computers -Content #> -LoadingComponent {New-UDTypography -Text "Refreshing AD Computer Data ..." -Paragraph
            New-UDProgress} -AutoRefresh -AutoRefreshInterval 120
#endregion computers


#region users
        # Load dynamically updating data of AD Users into a card
        $card_Users = New-UDDynamic -Id 'users' -Content {
            # Get all AD Users, only returning <attribute> for account type
            Try
                {
                $users = (Get-ADUser -Filter * -Properties <attribute> -Server $DC -ErrorAction Stop |
                    Select-Object <attribute>).<attribute>
                }# Try

            Catch
                {
                $errorMessage = "There was a problem with Get-ADUser; which populates `$users<br />`$DC = `"$DC`""
                ErrorMessage $errorMessage
                }# Catch

            # Group by account types
            $group_AccountTypes = $users | Group-Object | Sort-Object Count -Descending

            # Set the Users pie chart colors.  To note; $pieColors are applied in order of the collection of objects ($userCounts)
            $pieColors_Users = "Red","Green","Blue","Yellow","Purple","Orange","Black","Gold","Silver","Pink","Cyan","Magenta","Brown","Maroon"

            New-UDCard -Title "Active Directory Users:  $($users.count)"-Content {
                # Create empty array, loop through $group_AccountTypes, create Custom Objects for each, and add them to the array
                $userCounts = @()
                foreach ($g in $group_AccountTypes)
                    {
                    $userCounts += [PSCustomObject][Ordered]@{
                        AccountType = $g.Name
                        Total = $g.Count
                        }# $userCounts
                    }# foreach ($g in $group_AccountTypes)

                # Create the Users pie chart options
                $options_Pie_Users = @{
                Type = 'pie'
                Data = $userCounts
                BackgroundColor = $pieColors_Users
                BorderColor = '#c61d4a'
                HoverBackgroundColor = 'Cyan'
                HoverBorderColor = '#451dc6'
                DataProperty = 'Total'
                LabelProperty = 'AccountType'
                }# $options_Pie_Computers

                New-UDChartJS @options_Pie_Users
                }# New-UDCard
            }<# $card_Users -Content #> -LoadingComponent {New-UDTypography -Text "Refreshing AD User Data ..." -Paragraph
            New-UDProgress} -AutoRefresh -AutoRefreshInterval 120
#endregion users

        # Create the grid
        New-UDGrid -Container -Content {
            New-UDGrid -Item -LargeSize 4 -Content {$card_FSMORoles}
            New-UDGrid -Item -LargeSize 4 -Content {$card_functionalLevels}
            New-UDGrid -Item -LargeSize 4 -Content {}
            New-UDGrid -Item -LargeSize 4 -Content {$card_Computers}
            New-UDGrid -Item -LargeSize 4 -Content {$card_Users}
            }# New-UDGrid
    } <# New-UDDynamic -Content#> -LoadingComponent {New-UDTypography -Text "Gathering Data ..." -Paragraph; New-UDProgress}
}# New-UDDashboard

Thanks for taking the time to look into this!
Rob

1 Like

I figured it out!

All my stand-alone dashboard script files have the command New-UDDashboard in them, for creating the dashboards. It doesn’t like New-UDDashboard inside of the pages, because pages load into New-UDDashboard already. If I remove the New-UDDashboard line, and the closing line for it, they load as pages :slight_smile:

To have both the stand-alone and page versions of the scripts, I copied them to the Pages directory (then remove the New-UDDashboard lines). Afterwards I, created a basic Homepage and setup my page dashboard as such …

$navigation = @(
    New-UDListItem -Label "IT Portal"
    New-UDListItem -Label "Pages" -Children {
        New-UDListItem -Label "Home" -OnClick {Invoke-UDRedirect '/Home'}
        New-UDListItem -Label "AD Information" -OnClick {Invoke-UDRedirect '/ADInfo'}
        New-UDListItem -Label "Scripting Metrics" -OnClick {Invoke-UDRedirect '/ScriptingMetrics'}
        New-UDListItem -Label "Server Health Check" -OnClick {Invoke-UDRedirect '/ServerHealthCheck'}
        }# New-UDListItem
    )# New-UDListItem

$UDPageRoot = "$PSScriptRoot\Pages"
$pages = @()
$pages += New-UDPage -Name 'Home' -Content {. "$UDPageRoot\IT_Home.ps1"} -NavigationLayout Temporary -Navigation $navigation
$pages += New-UDPage -Name 'ADInfo' -Content {. "$UDPageRoot\ADInfo.ps1"} -NavigationLayout Temporary -Navigation $navigation
$pages += New-UDPage -Name 'ScriptingMetrics' -Content {. "$UDPageRoot\ScriptingMetrics.ps1"} -NavigationLayout Temporary -Navigation $navigation
$pages += New-UDPage -Name 'ServerHealthCheck' -Content {. "$UDPageRoot\Server_HealthCheck.ps1"} -NavigationLayout Temporary -Navigation $navigation
New-UDDashboard -Title 'IT Portal' -Pages $pages

I need to flush out the homepage, fix some issue with a couple of dynamic charts that are not working right as pages, and test out error handling in the new scope of all the pages loaded into one dashboard, then I’ll be ready to setup my demo!

Thanks and have a good one!
Rob

1 Like