Skip to content

Control New-DiagramLink arrow width #328

Closed

Description

@PatrickOnGit

Dear Przemyslaw

Is it possible to control the width of an arrow between two nodes?
I have written a little function that visualizes AD Site configuration and would like to have different arrow sizes based on site costs.
Later I also want to add also option to click on a site / site link to get additional information. But that is a different topic;-)

The code currently looks like this:

`Import-Module PSWriteHTML -Force

New-HTML -TitleText 'AD Sites' -Online -FilePath $PSScriptRoot\ADSites.html {

New-HTMLSection {

    New-HTMLDiagram -Height 800 {
        New-DiagramOptionsPhysics -StabilizationEnabled $true -Solver repulsion 
        Get-ADReplicationSite -filter * |
            ForEach-Object {
                $Site = $_
                Switch -Regex ($_.Name) {
                    "^Default-First-Site-Name$" { New-DiagramNode -Label "$($Site.Name)" -Id "$($Site.DistinguishedName)" -ColorBackground Amber }
                    "^(MainSite-0|MainSite-2)$" { New-DiagramNode -Label "$($Site.Name)" -Id "$($Site.DistinguishedName)" -ColorBackground Amber }
                    Default {New-DiagramNode -Label "$($Site.Name)" -Id "$($Site.DistinguishedName)" }
                }

            }
        Get-ADReplicationSiteLink -filter * |
            ForEach-Object {
                 If ( $_.SitesIncluded.count -lt 2 ) {
                     Write-Warning $( "Sitelink {0} has {1} sites included." -f $_.Name, $_.SitesIncluded.Count )
                 }
                 # Create all possible links
                 for ($i = 0; $i -lt $_.SitesIncluded.count; $i++) {
                    for ($n = ($i + 1); $n -lt $_.SitesIncluded.count; $n++) {
                        New-DiagramLink -From $_.SitesIncluded[$i] -To $_.SitesIncluded[$n] -Label $_.Name
                        
                    }
                 }
                 
            }
    } #-DisableLoadingBar

}

} -ShowHTML`

Thank you for your support.
Patrick

Activity

  1. PrzemyslawKlys commented on Jul 8, 2022

    @PrzemyslawKlys
    Member

    Cool you could improve my Show-WinADSites

    image

    The way I usually deal with "costs" is to use hierarchical diagram. You then tell it the Level you want it on. 0,1,2,3,4,5,6 and so on. This way its much more readable. You could probably control width on non-hierarchical diagram but I am afraid things would get ugly.

  2. PatrickOnGit commented on Jul 8, 2022

    @PatrickOnGit
    Author

    I had a quick look into your new function. Think it gathers too much information when using it in large environments. It takes a long time. Of course it shows quite valuable information. But I would be first intersted in the connections:

    image

    Then, when selecting a site, the table could show me all subnets related to the site or all DCs responsible for this site.
    The reason I would like to have different line weights is to quickly show if one link is more costly than another. I could do this also by color I guess. First get all costs, see how many different costs there are and then assign a color to each. From Green with low costs to red with high costs. Bad for color blind people, but at least some indicator.

    Is it possible to hide / unhide information in the graphic on click?

  3. PatrickOnGit commented on Jul 8, 2022

    @PatrickOnGit
    Author

    I did a quick rewrite of my version of the script to include your data table. It^s not ideal yet, like schedules is not resovled etc, and missing Subnets, but it took few seconds to build instead of, well, your version is still trying to show something ;-)
    Its a decission between speed and informations. I will look later in your version.
    I know you have example where you hide or show table information based on clicking the graphic. Would you mind pointing me to one?

    Import-Module PSWriteHTML -Force
    $Sites = Get-ADReplicationSite -filter *
    $SiteLinks = Get-ADReplicationSiteLink -filter *
    
    New-HTML -TitleText 'AD Sites' -Online -FilePath $PSScriptRoot\ADSites.html  {
        New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow
        New-HTMLTableOption -DataStore HTML
        New-HTMLTabStyle -BorderRadius 0px -TextTransform capitalize -BackgroundColorActive SlateGrey
        New-HTMLTabPanel {
            New-HTMLTab -TabName 'Standard' {
                New-HTMLSection -HeaderText 'Organization Diagram' {
    
                    New-HTMLDiagram -Height 800 {
                        New-DiagramOptionsPhysics -StabilizationEnabled $true -Solver repulsion 
                        $Sites |
                            ForEach-Object {
                                $Site = $_
                                Switch -Regex ($_.Name) {
                                    "^Default-First-Site-Name$" { New-DiagramNode -Label "$($Site.Name)" -Id "$($Site.DistinguishedName)" -ColorBackground Amber }
                                    "^(MainSite-0|MainSite-2)$" { New-DiagramNode -Label "$($Site.Name)" -Id "$($Site.DistinguishedName)" -ColorBackground Amber }
                                    Default {New-DiagramNode -Label "$($Site.Name)" -Id "$($Site.DistinguishedName)" }
                                }
    
                            }
                        $SiteLinks |
                            ForEach-Object {
                                 If ( $_.SitesIncluded.count -lt 2 ) {
                                     Write-Warning $( "Sitelink {0} has {1} sites included." -f $_.Name, $_.SitesIncluded.Count )
                                 }
                                 # Create all possible links
                                 for ($i = 0; $i -lt $_.SitesIncluded.count; $i++) {
                                    for ($n = ($i + 1); $n -lt $_.SitesIncluded.count; $n++) {
                                        New-DiagramLink -From $_.SitesIncluded[$i] -To $_.SitesIncluded[$n] -Label $_.Name
                                
                                    }
                                 }
                         
                            }
                    } 
                }
            }
        }
        New-HTMLSection -Title "Information about Sites" {
            New-HTMLTable -DataTable $Sites -Filtering {
                if (-not $DisableBuiltinConditions) {
                    New-TableCondition -BackgroundColor MediumSeaGreen -ComparisonType number -Value 0 -Name SubnetsCount -Operator gt
                    New-TableCondition -BackgroundColor CoralRed -ComparisonType number -Value 0 -Name SubnetsCount -Operator eq
                }
                if ($Conditions) {
                    & $Conditions
                }
            } -DataTableID 'DT-StandardSites' -DataStore JavaScript
    
    
        }
        New-HTMLTable -DataTable $Replication -Filtering {
            if (-not $DisableBuiltinConditions) {
                New-TableCondition -BackgroundColor MediumSeaGreen -ComparisonType number -Value 0 -Name SubnetsCount -Operator gt
                New-TableCondition -BackgroundColor CoralRed -ComparisonType number -Value 0 -Name SubnetsCount -Operator eq
            }
            if ($Conditions) {
                & $Conditions
            }
        } -DataTableID 'DT-StandardSites1' -DataStore JavaScript
      #  }
    } -ShowHTML
    
  4. PrzemyslawKlys commented on Jul 8, 2022

    @PrzemyslawKlys
    Member

    You should read this:

    Import-Module .\PSWriteHTML.psd1 -Force
    
    $Processes = Get-Process | Select-Object -First 3 -Property Name, ProcessName, Id, FileVersion, WorkingSet
    
    New-HTML -TitleText 'My Title' -Online -FilePath $PSScriptRoot\Example30-LinkedTableToTable02.html -ShowHTML {
        New-HTMLTableOption -DataStore Javascript
        New-HTMLSection -Invisible {
            New-HTMLPanel {
                New-HTMLTable -DataTable $Processes -DataTableID 'RandomID1' {
                    New-TableEvent -ID 'RandomID2' -SourceColumnID 0 -TargetColumnId 0
                    New-TableEvent -ID 'RandomID3' -SourceColumnID 0 -TargetColumnId 0
                }
            }
            New-HTMLPanel {
                New-HTMLTable -DataTable $Processes -DataTableID 'RandomID2'
            }
        }
        New-HTMLPanel {
            New-HTMLTable -DataTable $Processes -DataTableID 'RandomID3'
        }
    }
  5. PatrickOnGit commented on Jul 8, 2022

    @PatrickOnGit
    Author

    I played a little bit more around and it now looks quite good. Still I would be happy to be able to have different arrow weights ;-)

    It is not yet ideal and it doesn't yet fit into your ADEssentials module, but let me know what you think.
    If possible I would like to hide the DNs, but I need them as unique reference.
    Sometimes the filter from last created HTML file is also used on a freshly opened document.
    The comparison of the \A0DEL to verify if a deleted object is referenced breaks the first table.

    Import-Module PSWriteHTML -Force
    $Subnets = Get-ADReplicationSubnet -Filter * | Select @{n='Site';e={ $_.Site  -replace 'CN=(.*?),.*','$1' }}, @{n='Subnet';e={ $_.Name}}, Location, @{ n='SiteDN';e={$_.Site}}
    $SubnetsHash =  @{}
    $Subnets | %{ if ( $SubnetsHash.ContainsKey($_.SiteDN) ) {  $SubnetsHash[$_.SiteDN] += $_.Subnet  } else { $SubnetsHash.Add( $_.SiteDN,@(,$_.Subnet) ) } }
    $Sites = Get-ADReplicationSite -filter * | 
            Select-Object Name, Description,
                @{ n="InterSiteTopologyGenerator";e={ 
                    if ( $_.InterSiteTopologyGenerator -match "\\0ADEL" ) {
                        $_.InterSiteTopologyGenerator } else {
                        try { Get-ADObject -searchbase "$($_.InterSiteTopologyGenerator -replace '.*?,(.*)$','$1' )" -SearchScope Base  -Filter * -Properties dnsHostName  | Select-Object -ExpandProperty dnsHostName } catch {  }  }
                 }},
                 @{ n='SubnetCount';e={ $SubnetsHash[$_.DistinguishedName].count } },
                 ManagedBy,  
                @{ n='hasSchedule';e={ if( $_.ReplicationSchedule ) {$true} else {$false} }},UniversalGroupCachingRefreshSite, 
                DistinguishedName
    $SiteLinks = Get-ADReplicationSiteLink -filter * | Select-Object Name, Cost, ReplicationFrequencyInMinutes, SitesIncluded, DistinguishedName
    
    $CostGroup = $SiteLinks | Group Cost -NoElement
    $Script:LinkToSite = @()
    New-HTML -TitleText 'AD Sites' -Online -FilePath $PSScriptRoot\ADSites.html  {
        New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow
        New-HTMLTableOption -DataStore HTML
        New-HTMLTabStyle -BorderRadius 0px -TextTransform capitalize -BackgroundColorActive SlateGrey
        New-HTMLTabPanel {
            New-HTMLTab -TabName 'Standard' {
                New-HTMLSection -HeaderText 'Organization Diagram' {
    
                    New-HTMLDiagram -Height 800 {
                        New-DiagramOptionsPhysics -StabilizationEnabled $true -Solver repulsion 
                        $Sites |
                            ForEach-Object {
                                $Site = $_
                                Switch -Regex ($_.Name) {
                                    "^Default-First-Site-Name$" { New-DiagramNode -Label "$($Site.Name)" -Id "$($Site.DistinguishedName)" -ColorBackground Amber }
                                    "^(CHBS-0|USEH-0|INKL-0|SGSG-0)$" { New-DiagramNode -Label "$($Site.Name)" -Id "$($Site.DistinguishedName)" -ColorBackground Amber }
                                    Default {New-DiagramNode -Label "$($Site.Name)" -Id "$($Site.DistinguishedName)" }
                                }
    
                            }
                        New-DiagramEvent -ID 'DT-Sites' -ColumnID 7
                        New-DiagramEvent -ID 'DT-Subnets' -ColumnID 3
                        New-DiagramEvent -ID 'DT-SiteLinks' -ColumnID 5
    
                        $SiteLinks |
                            ForEach-Object {
                                 $SiteLink = $_
                                 If ( $_.SitesIncluded.count -lt 2 ) {
                                     Write-Warning $( "Sitelink {0} has {1} sites included." -f $_.Name, $_.SitesIncluded.Count )
                                     $Script:LinkToSite += New-Object PSObject -Property  ( [ordered] @{
                                        linkedFrom = $_.SitesIncluded[0] -replace 'CN=(.*?),.*','$1'
                                        linkedTo = ''
                                        linkName = $_.Name
                                        Cost = $_.Cost
                                        ReplicationFrequencyInMinutes =  $_.ReplicationFrequencyInMinutes
                                        linkDN = $_.SitesIncluded[0]
                                    } )
                                 }
                                 # Create all possible links
                                 for ($i = 0; $i -lt $_.SitesIncluded.count; $i++) {
                                    for ($n = ($i + 1); $n -lt $_.SitesIncluded.count; $n++) {
                                        New-DiagramLink -From $_.SitesIncluded[$i] -To $_.SitesIncluded[$n] -Label $_.Name
                                        $Script:LinkToSite += New-Object PSObject -Property  ( [ordered] @{
                                            linkedFrom = $_.SitesIncluded[$i] -replace 'CN=(.*?),.*','$1'
                                            linkedTo = $_.SitesIncluded[$n] -replace 'CN=(.*?),.*','$1'
                                            linkName = $_.Name
                                            Cost = $_.Cost
                                            ReplicationFrequencyInMinutes =  $_.ReplicationFrequencyInMinutes
                                            linkDN = $_.SitesIncluded[$i]
                                        } )
                                        # To be able to select either site, the link information needs to be added twice
                                        $Script:LinkToSite += New-Object PSObject -Property  ( [ordered] @{
                                            linkedFrom = $_.SitesIncluded[$i] -replace 'CN=(.*?),.*','$1'
                                            linkedTo = $_.SitesIncluded[$n] -replace 'CN=(.*?),.*','$1'
                                            linkName = $_.Name
                                            Cost = $_.Cost
                                            ReplicationFrequencyInMinutes =  $_.ReplicationFrequencyInMinutes
                                            linkDN = $_.SitesIncluded[$n]
                                        } )
                                    }
                                 }
                         
                            }
                    } 
                }
            }
        }
        New-HTMLSection -Title "Information about Sites" {
            New-HTMLTable -DataTable $Sites -Filtering {
                New-TableColumnOption -Hidden $true -ColumnIndex 1
                if (-not $DisableBuiltinConditions) {
                    New-TableCondition -BackgroundColor MediumSeaGreen -ComparisonType number -Value 0 -Name SubnetCount -Operator gt
                    New-TableCondition -BackgroundColor CoralRed -ComparisonType number -Value 0 -Name SubnetCount -Operator eq
                   # New-TableCondition -BackgroundColor MediumSeaGreen -ComparisonType string -Value '*\0ADEL*' -Name InterSiteTopologyGenerator -Operator notlike
                   # New-TableCondition -BackgroundColor CoralRed -ComparisonType string -Value '*\0ADEL*' -Name InterSiteTopologyGenerator -Operator like
                }
                if ($Conditions) {
                    & $Conditions
                }
            } -DataTableID 'DT-Sites' -DataStore JavaScript
    
            New-HTMLTable -DataTable $Subnets -Filtering {
               #  New-TableColumnOption -Hidden $true -ColumnIndex 0
            } -DataTableID 'DT-Subnets' -DataStore JavaScript
        
            New-HTMLTable -DataTable $Script:LinkToSite -Filtering {
              #  New-TableColumnOption -Hidden $true -ColumnIndex 2
    
            } -DataTableID 'DT-SiteLinks' -DataStore JavaScript 
      }
    } -ShowHTML
    
  6. PrzemyslawKlys commented on Jun 23, 2026

    @PrzemyslawKlys
    Member

    Closed by PR #525, which added diagram link width/value support for controlling edge/arrow weight, with examples and tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions