Pages/Dynamic/FilesPage.ps1

$FilesPageContent = {
    param($RemoteHost)

    $PUDRSSyncHT = $global:PUDRSSyncHT

    # Load PUDAdminCenter Module Functions Within ScriptBlock
    $ThisModuleFunctionsStringArray | Where-Object {$_ -ne $null} | foreach {Invoke-Expression $_ -ErrorAction SilentlyContinue}

    # For some reason, scriptblocks defined earlier can't be used directly here. They need to be a different objects before
    # they actually behave as expected. Not sure why.
    #$RecreatedDisconnectedPageContent = [scriptblock]::Create($DisconnectedPageContentString)

    $RHostIP = $($PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $RemoteHost}).IPAddressList[0]

    #region >> Ensure $RemoteHost is Valid

    if ($PUDRSSyncHT.RemoteHostList.HostName -notcontains $RemoteHost) {
        $ErrorText = "The Remote Host $($RemoteHost.ToUpper()) is not a valid Host Name!"
    }

    if ($ErrorText) {
        New-UDRow -Columns {
            New-UDColumn -Size 4 -Content {
                New-UDHeading -Text ""
            }
            New-UDColumn -Size 4 -Content {
                New-UDHeading -Text $ErrorText -Size 6
            }
            New-UDColumn -Size 4 -Content {
                New-UDHeading -Text ""
            }
        }
    }

    # If $RemoteHost isn't valid, don't load anything else
    if ($ErrorText) {
        return
    }

    #endregion >> Ensure $RemoteHost is Valid

    #region >> Loading Indicator

    New-UDRow -Columns {
        New-UDColumn -Endpoint {
            $Session:FilesPageLoadingTracker = [System.Collections.ArrayList]::new()
        }
        New-UDColumn -AutoRefresh -RefreshInterval 5 -Endpoint {
            if ($Session:FilesPageLoadingTracker -notcontains "FinishedLoading") {
                New-UDHeading -Text "Loading...Please wait..." -Size 5
                New-UDPreloader -Size small
            }
        }
    }

    #endregion >> Loading Indicator

    # Master Endpoint - All content will be within this Endpoint so that we can reference $Cache: and $Session: scope variables
    New-UDColumn -Size 12 -Endpoint {
        #region >> Ensure We Are Connected / Can Connect to $RemoteHost

        $PUDRSSyncHT = $global:PUDRSSyncHT

        # Load PUDAdminCenter Module Functions Within ScriptBlock
        $Cache:ThisModuleFunctionsStringArray | Where-Object {$_ -ne $null} | foreach {Invoke-Expression $_ -ErrorAction SilentlyContinue}

        # For some reason, scriptblocks defined earlier can't be used directly here. They need to be a different objects before
        # they actually behave as expected. Not sure why.
        #$RecreatedDisconnectedPageContent = [scriptblock]::Create($DisconnectedPageContentString)

        $RHostIP = $($PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $RemoteHost}).IPAddressList[0]

        if ($Session:CredentialHT.$RemoteHost.PSRemotingCreds -eq $null) {
            Invoke-UDRedirect -Url "/Disconnected/$RemoteHost"
        }

        try {
            $ConnectionStatus = Invoke-Command -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds -ScriptBlock {"Connected"}
        }
        catch {
            $ConnectionStatus = "Disconnected"
        }

        # If we're not connected to $RemoteHost, don't load anything else
        if ($ConnectionStatus -ne "Connected") {
            #Invoke-Command -ScriptBlock $RecreatedDisconnectedPageContent -ArgumentList $RemoteHost
            Invoke-UDRedirect -Url "/Disconnected/$RemoteHost"
        }
        else {
            New-UDRow -EndPoint {
                New-UDColumn -Size 3 -Content {
                    New-UDHeading -Text ""
                }
                New-UDColumn -Size 6 -Endpoint {
                    New-UDTable -Id "TrackingTable" -Headers @("RemoteHost","Status","DateTime") -AutoRefresh -RefreshInterval 2 -Endpoint {
                        $PUDRSSyncHT = $global:PUDRSSyncHT

                        # Load PUDAdminCenter Module Functions Within ScriptBlock
                        $Cache:ThisModuleFunctionsStringArray | Where-Object {$_ -ne $null} | foreach {Invoke-Expression $_ -ErrorAction SilentlyContinue}
                        
                        $RHostIP = $($PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $RemoteHost}).IPAddressList[0]

                        #$WSMan5985Available = $(TestPort -HostName $RHostIP -Port 5985).Open
                        #$WSMan5986Available = $(TestPort -HostName $RHostIP -Port 5986).Open

                        $ConnectionStatus = Invoke-Command -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds -ScriptBlock {"Connected"}

                        if ($ConnectionStatus -eq "Connected") {
                            $TableData = @{
                                RemoteHost      = $RemoteHost.ToUpper()
                                Status          = "Connected"
                            }
                        }
                        else {
                            <#
                            $TableData = @{
                                RemoteHost = $RemoteHost.ToUpper()
                                Status = "Disconnected"
                            }
                            #>

                            Invoke-UDRedirect -Url "/Disconnected/$RemoteHost"
                        }

                        # SUPER IMPORTANT NOTE: ALL Real-Time Enpoints on the Page reference LiveOutputClone!
                        if ($PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo.LiveOutput.Count -gt 0) {
                            if ($PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataTracker.Previous -eq $null) {
                                $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataTracker.Previous = $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo.LiveOutput.Clone()
                            }
                            if ($PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataTracker.Current.Count -gt 0) {
                                $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataTracker.Previous = $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataTracker.Current.Clone()
                            }
                            $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataTracker.Current = $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo.LiveOutput.Clone()
                        }

                        $TableData.Add("DateTime",$(Get-Date -Format MM-dd-yy_hh:mm:sstt))

                        [PSCustomObject]$TableData | Out-UDTableData -Property @("RemoteHost","Status","DateTime")
                    }
                }
                New-UDColumn -Size 3 -Content {
                    New-UDHeading -Text ""
                }
            }
        }

        #endregion >> Ensure We Are Connected / Can Connect to $RemoteHost

        #region >> Gather Some Initial Info From $RemoteHost

        if (!$Session:RootDirChildItems) {
            $StaticInfo = Invoke-Command -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds -ScriptBlock {
                $RootDirChildItems = Get-ChildItem -Path "$env:SystemDrive\"
                $RootDirItem = Get-Item -Path "$env:SystemDrive\"

                [pscustomobject]@{
                    RootDirItem             = $RootDirItem
                    RootDirChildItems      = $RootDirChildItems
                }
            }
            $Session:RootDirChildItems = $StaticInfo.RootDirChildItems
            $Session:RootDirItem = $StaticInfo.RootDirItem
            if ($PUDRSSyncHT."$RemoteHost`Info".Files.Keys -notcontains "RootDirChildItems") {
                $PUDRSSyncHT."$RemoteHost`Info".Files.Add("RootDirChildItems",$StaticInfo.RootDirChildItems)
            }
            else {
                $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirChildItems = $StaticInfo.RootDirChildItems
            }
            if ($PUDRSSyncHT."$RemoteHost`Info".Files.Keys -notcontains "RootDirItem") {
                $PUDRSSyncHT."$RemoteHost`Info".Files.Add("RootDirItem",$StaticInfo.RootDirItem)
            }
            else {
                $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirItem = $StaticInfo.RootDirItem
            }
        }

        #endregion >> Gather Some Initial Info From $RemoteHost

        #region >> Page Name and Horizontal Nav

        New-UDRow -Endpoint {
            New-UDColumn -Content {
                New-UDHeading -Text "Files (In Progress)" -Size 3
                New-UDHeading -Text "NOTE: Domain Group Policy trumps controls with an asterisk (*)" -Size 6
            }
        }
        New-UDRow -Endpoint {
            New-UDColumn -Size 12 -Content {
                New-UDCollapsible -Items {
                    New-UDCollapsibleItem -Title "More Tools" -Icon laptop -Active -Endpoint {
                        New-UDRow -Endpoint {
                            foreach ($ToolName in $($Cache:DynamicPages | Where-Object {$_ -notmatch "PSRemotingCreds|ToolSelect"})) {
                                New-UDColumn -Endpoint {
                                    $ToolNameNoSpaces = $ToolName -replace "[\s]",""
                                    New-UDLink -Text $ToolName -Url "/$ToolNameNoSpaces/$RemoteHost" -Icon dashboard
                                }
                            }
                            #New-UDCard -Links $Links
                        }
                    }
                }
            }
        }

        #endregion >> Page Name and Horizontal Nav

        #region >> Setup LiveData

        <#
        New-UDColumn -Endpoint {
            $PUDRSSyncHT = $global:PUDRSSyncHT

            $Cache:ThisModuleFunctionsStringArray | Where-Object {$_ -ne $null} | foreach {Invoke-Expression $_ -ErrorAction SilentlyContinue}

            $RHostIP = $($PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $RemoteHost}).IPAddressList[0]

            # Remove Existing Runspace for LiveDataRSInfo if it exists as well as the PSSession Runspace within
            if ($PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo -ne $null) {
                $PSSessionRunspacePrep = @(
                    Get-Runspace | Where-Object {
                        $_.RunspaceIsRemote -and
                        $_.Id -gt $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo.ThisRunspace.Id -and
                        $_.OriginalConnectionInfo.ComputerName -eq $RemoteHost
                    }
                )
                if ($PSSessionRunspacePrep.Count -gt 0) {
                    $PSSessionRunspace = $($PSSessionRunspacePrep | Sort-Object -Property Id)[0]
                }
                $PSSessionRunspace.Dispose()
                $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo.ThisRunspace.Dispose()
            }

            # Create a Runspace that creates a PSSession to $RemoteHost that is used once every second to re-gather data from $RemoteHost

            # The New-Runspace function handles scope for you behind the scenes, so just pretend that everything within -ScriptBlock {} is in the current scope
            New-Runspace -RunspaceName "Files$RemoteHost`LiveData" -ScriptBlock {
                $PUDRSSyncHT = $global:PUDRSSyncHT
            
                $LiveDataPSSession = New-PSSession -Name "Files$RemoteHost`LiveData" -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds

                # Load needed functions in the PSSession
                Invoke-Command -Session $LiveDataPSSession -ScriptBlock {
                    $using:LiveDataFunctionsToLoad | foreach {Invoke-Expression $_}
                }

                $RSLoopCounter = 0

                while ($PUDRSSyncHT) {
                    # $LiveOutput is a special ArrayList created and used by the New-Runspace function that collects output as it occurs
                    # We need to limit the number of elements this ArrayList holds so we don't exhaust memory
                    if ($LiveOutput.Count -gt 1000) {
                        $LiveOutput.RemoveRange(0,800)
                    }

                    # Stream Results to $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo.LiveOutput
                    Invoke-Command -Session $LiveDataPSSession -ScriptBlock {
                        # Place most resource intensive operations first

                        # Operations that you only want running once every 30 seconds go within this 'if; block
                        # Adjust the timing as needed with deference to $RemoteHost resource efficiency.
                        if ($using:RSLoopCounter -eq 0 -or $($using:RSLoopCounter % 30) -eq 0) {
                            #@{RootFiles = Get-ChildItem -Path "$env:SystemDrive\" }
                        }

                        # Operations that you want to run once every second go here
                        @{RootFiles = Get-ChildItem -Path "$env:SystemDrive\"}

                    } | foreach {$null = $LiveOutput.Add($_)}

                    $RSLoopCounter++

                    [GC]::Collect()

                    Start-Sleep -Seconds 1
                }
            }
            # The New-Runspace function outputs / continually updates a Global Scope variable called $global:RSSyncHash. The results of
            # the Runspace we just created can be found in $global:RSSyncHash's "Files$RemoteHost`LiveDataResult" Property - which is just
            # the -RunspaceName value plus the word 'Info'. By setting $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo equal to
            # $RSSyncHash."Files$RemoteHost`LiveDataResult", we can now reference $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo.LiveOutput
            # to get the latest data from $RemoteHost.
            $PUDRSSyncHT."$RemoteHost`Info".Files.LiveDataRSInfo = $RSSyncHash."Files$RemoteHost`LiveDataResult"
        }
        #>


        #endregion >> Setup LiveData

        #region >> Controls


        # Static Data Element Example

        New-UDCollapsible -Items {
            New-UDCollapsibleItem -Title "File System" -Icon laptop -Active -Endpoint {
                <#
                New-UDRow -Endpoint {
                    New-UDColumn -Size 3 -Endpoint {}
                    New-UDColumn -Size 6 -Endpoint {
                        New-UDTextbox -Label "Full Path to Directory to Explore" -Id "NewRootDirTB" -Placeholder "Directory to Explore"
                        New-UDButton -Text "Explore" -Id "Button" -OnClick {
                            $NewRootDirTextBox = Get-UDElement -Id "NewRootDirTB"
                            $FullPathToExplore = $NewRootDirTextBox.Attributes['value']

                            $NewPathInfo = Invoke-Command -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds -ScriptBlock {
                                $RootDirChildItems = Get-ChildItem -Path $using:FullPathToExplore
                    
                                [pscustomobject]@{
                                    RootDirChildItems = $RootDirChildItems
                                }
                            }
                            $Session:RootDirChildItems = $NewPathInfo.RootDirChildItems
                            $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirChildItems = $Session:RootDirChildItems
                            Sync-UDElement -Id "RootDirChildItemsUDGrid"
                        }
                    }
                    New-UDColumn -Size 3 -Endpoint {}
                }
                #>


                New-UDRow -Endpoint {
                    New-UDColumn -Size 3 -Endpoint {}
                    New-UDColumn -Size 6 -Endpoint {
                        New-UDElement -Id "CurrentRootDirTB" -Tag div -EndPoint {
                            #New-UDTextbox -Label "Current Directory" -Placeholder "Directory to Explore" -Value $Session:RootDirItem.FullName
                            New-UDHeading -Text "Current Directory: $($Session:RootDirItem.FullName)" -Size 5
                        }
                        New-UDElement -Id "NewRootDirTB" -Tag div -EndPoint {
                            New-UDTextbox -Id "NewRootDirTBProper" -Label "New Directory"
                        }
                        New-UDButton -Text "Explore" -OnClick {
                            $NewRootDirTextBox = Get-UDElement -Id "NewRootDirTBProper"
                            $FullPathToExplore = $NewRootDirTextBox.Attributes['value']

                            $NewPathInfo = Invoke-Command -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds -ScriptBlock {
                                $RootDirChildItems = Get-ChildItem -Path $args[0]
                                $RootDirItem = Get-Item -Path $args[0]

                                [pscustomobject]@{
                                    RootDirItem            = $RootDirItem
                                    RootDirChildItems      = $RootDirChildItems
                                }
                            } -ArgumentList $FullPathToExplore
                            $Session:RootDirChildItems = $NewPathInfo.RootDirChildItems
                            $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirChildItems = $NewPathInfo.RootDirChildItems
                            $Session:RootDirItem = $NewPathInfo.RootDirItem
                            $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirItem = $NewPathInfo.RootDirItem
                            Sync-UDElement -Id "RootDirChildItemsUDGrid"
                            Sync-UDElement -Id "NewRootDirTB"
                            Sync-UDElement -Id "CurrentRootDirTB"
                        }

                        New-UDButton -Text "Parent Directory" -OnClick {
                            $FullPathToExplore = if ($($Session:RootDirItem.FullName | Split-Path -Parent) -eq "") {$Session:RootDirItem.FullName} else {$Session:RootDirItem.FullName | Split-Path -Parent}

                            $NewPathInfo = Invoke-Command -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds -ScriptBlock {
                                $RootDirChildItems = Get-ChildItem -Path $args[0]
                                $RootDirItem = Get-Item -Path $args[0]

                                [pscustomobject]@{
                                    RootDirItem            = $RootDirItem
                                    RootDirChildItems      = $RootDirChildItems
                                }
                            } -ArgumentList $FullPathToExplore
                            $Session:RootDirChildItems = $NewPathInfo.RootDirChildItems
                            $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirChildItems = $NewPathInfo.RootDirChildItems
                            $Session:RootDirItem = $NewPathInfo.RootDirItem
                            $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirItem = $NewPathInfo.RootDirItem
                            Sync-UDElement -Id "RootDirChildItemsUDGrid"
                            Sync-UDElement -Id "NewRootDirTB"
                            Sync-UDElement -Id "CurrentRootDirTB"
                        }
                    }
                    New-UDColumn -Size 3 -Endpoint {}
                }
                New-UDRow -Endpoint {
                    New-UDColumn -Size 12 -Endpoint {
                        $RootFilesProperties = @("Name","FullPath","DateModified","Type","Size","Explore")
                        $RootFilesUDGridSplatParams = @{
                            Id              = "RootDirChildItemsUDGrid"
                            Headers         = $RootFilesProperties
                            Properties      = $RootFilesProperties
                            PageSize        = 20
                        }
                        New-UDGrid @RootFilesUDGridSplatParams -Endpoint {
                            $PUDRSSyncHT = $global:PUDRSSyncHT

                            $RHostIP = $($PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $RemoteHost}).IPAddressList[0]

                            $Session:RootDirChildItems | foreach {
                                [pscustomobject]@{
                                    Name            = $_.Name
                                    FullPath        = $_.FullName
                                    DateModified    = Get-Date $_.LastWriteTime -Format MM/dd/yy_hh:mm:ss
                                    Type            = if ($_.PSIsContainer) {"Folder"} else {"File"}
                                    Size            = if ($_.PSIsContainer) {'-'} else {[Math]::Round($($_.Length / 1KB),2).toString() + 'KB'}
                                    Explore         = if (!$_.PSIsContainer) {'-'} else {
                                        New-UDButton -Text "Explore" -OnClick {
                                            #$NewRootDirTextBox = Get-UDElement -Id "NewRootDirTB"
                                            $FullPathToExplore = $_.FullName
                
                                            $NewPathInfo = Invoke-Command -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds -ScriptBlock {
                                                $RootDirChildItems = Get-ChildItem -Path $args[0]
                                                $RootDirItem = Get-Item -Path $args[0]

                                                [pscustomobject]@{
                                                    RootDirItem            = $RootDirItem
                                                    RootDirChildItems      = $RootDirChildItems
                                                }
                                            } -ArgumentList $FullPathToExplore
                                            $Session:RootDirChildItems = $NewPathInfo.RootDirChildItems
                                            $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirChildItems = $NewPathInfo.RootDirChildItems
                                            $Session:RootDirItem = $NewPathInfo.RootDirItem
                                            $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirItem = $NewPathInfo.RootDirItem
                                            Sync-UDElement -Id "RootDirChildItemsUDGrid"
                                            Sync-UDElement -Id "NewRootDirTB"
                                            Sync-UDElement -Id "CurrentRootDirTB"
                                        }
                                    }
                                }
                            } | Out-UDGridData
                        }
                    }
                }
            }
        }

        <#
        New-UDInput -Title "Explore Path" -SubmitText "Explore" -Content {
            New-UDInputField -Name "FullPathToExplore" -Type textbox
        } -Endpoint {
            param($FullPathToExplore)

            #region >> Check Connection

            $PUDRSSyncHT = $global:PUDRSSyncHT

            $RHostIP = $($PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $RemoteHost}).IPAddressList[0]

            #endregion >> Check Connection

            #region >> SubMain

            if (!$FullPathToExplore) {
                New-UDInputAction -Toast "You must fill out the 'FullPathToExplore' field!" -Duration 10000
                return
            }

            try {
                $NewPathInfo = Invoke-Command -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds -ScriptBlock {
                    $RootDirChildItems = Get-ChildItem -Path $using:FullPathToExplore
        
                    [pscustomobject]@{
                        RootDirChildItems = $RootDirChildItems
                    }
                }
                $Session:RootDirChildItems = $NewPathInfo.RootDirChildItems
                $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirChildItems = $Session:RootDirChildItems

                Sync-UDElement -Id "RootDirChildItemsUDGrid"

                #Invoke-UDRedirect -Url "/Files/$RemoteHost"
            }
            catch {
                New-UDInputAction -Toast $_.Exception.Message -Duration 2000
            
                #Invoke-UDRedirect -Url "/Overview/$RemoteHost"
            }
        }
        #>


        <#
        # Static Data Element Example
        New-UDCollapsible -Id $CollapsibleId -Items {
            New-UDCollapsibleItem -Title "File System" -Icon laptop -Active -Endpoint {
                #region >> Main

                New-UDRow -Endpoint {
                    New-UDColumn -Size 12 -Endpoint {
                        $RootFilesProperties = @("Name","FullPath","DateModified","Type","Size")
                        $RootFilesUDGridSplatParams = @{
                            Id = "RootDirChildItemsUDGrid"
                            Headers = $RootFilesProperties
                            Properties = $RootFilesProperties
                            PageSize = 20
                        }
                        New-UDGrid @RootFilesUDGridSplatParams -Endpoint {
                            $PUDRSSyncHT = $global:PUDRSSyncHT

                            $RHostIP = $($PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $RemoteHost}).IPAddressList[0]

                            $Session:RootDirChildItems | foreach {
                                [pscustomobject]@{
                                    Name = $_.Name
                                    FullPath = $_.FullName
                                    DateModified = Get-Date $_.LastWriteTime -Format MM/dd/yy_hh:mm:ss
                                    Type = if ($_.PSIsContainer) {"Folder"} else {"File"}
                                    Size = if ($_.PSIsContainer) {'-'} else {[Math]::Round($($_.Length / 1KB),2).toString() + 'KB'}
                                    #Inspect = $Cache:InspectCell
                                }
                            } | Out-UDGridData
                        }
                    }
                }
                
                New-UDRow -Endpoint {
                    New-UDColumn -Size 4 -Endpoint {
                        New-UDInput -Title "Explore Path" -SubmitText "Explore" -Content {
                            New-UDInputField -Name "FullPathToExplore" -Type textbox
                        } -Endpoint {
                            param($FullPathToExplore)

                            #region >> Check Connection

                            $PUDRSSyncHT = $global:PUDRSSyncHT

                            $RHostIP = $($PUDRSSyncHT.RemoteHostList | Where-Object {$_.HostName -eq $RemoteHost}).IPAddressList[0]

                            #endregion >> Check Connection

                            #region >> SubMain

                            if (!$FullPathToExplore) {
                                New-UDInputAction -Toast "You must fill out the 'FullPathToExplore' field!" -Duration 10000
                                return
                            }

                            try {
                                $NewPathInfo = Invoke-Command -ComputerName $RemoteHost -Credential $Session:CredentialHT.$RemoteHost.PSRemotingCreds -ScriptBlock {
                                    $RootDirChildItems = Get-ChildItem -Path $using:FullPathToExplore
                        
                                    [pscustomobject]@{
                                        RootDirChildItems = $RootDirChildItems
                                    }
                                }
                                $Session:RootDirChildItems = $NewPathInfo.RootDirChildItems
                                $PUDRSSyncHT."$RemoteHost`Info".Files.RootDirChildItems = $Session:RootDirChildItems

                                Sync-UDElement -Id "RootDirChildItemsUDGrid"

                                #Invoke-UDRedirect -Url "/Files/$RemoteHost"
                            }
                            catch {
                                New-UDInputAction -Toast $_.Exception.Message -Duration 2000
                            
                                #Invoke-UDRedirect -Url "/Overview/$RemoteHost"
                            }

                            #endregion >> SubMain
                        }
                    }
                }

                New-UDButton -Text "SyncFileGrid" -Id "Button" -OnClick {
                    Sync-UDElement -Id "RootDirChildItemsUDGrid"
                }

                #endregion >> Main
            }
        }
        #>


        # Live Data Element Example

        # Remove the Loading Indicator
        $null = $Session:FilesPageLoadingTracker.Add("FinishedLoading")

        #endregion >> Controls
    }
}
$Page = New-UDPage -Url "/Files/:RemoteHost" -Endpoint $FilesPageContent
$null = $Pages.Add($Page)