Private/UI/New-PIMActiveRolesPanel.ps1
|
function New-PIMActiveRolesPanel { <# .SYNOPSIS Creates a panel displaying currently active PIM roles with a modern UI design. .DESCRIPTION Creates a Windows Forms panel containing a ListView for displaying active PIM roles. The panel includes a header with title and role count, and a custom-styled ListView with columns for role details. Features owner-drawn headers and hover effects. .EXAMPLE $activeRolesPanel = New-PIMActiveRolesPanel $form.Controls.Add($activeRolesPanel) Creates and adds the active roles panel to a form. .OUTPUTS System.Windows.Forms.Panel Returns a panel containing the active roles ListView with header. .NOTES The ListView uses owner-drawn headers for custom styling and includes double buffering for smooth rendering performance. #> [CmdletBinding()] param() # Create main container panel $panel = New-Object System.Windows.Forms.Panel -Property @{ Name = 'pnlActive' BackColor = [System.Drawing.Color]::White BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle Dock = [System.Windows.Forms.DockStyle]::Fill Padding = New-Object System.Windows.Forms.Padding(0) } # Create header panel with Microsoft blue background $headerPanel = New-Object System.Windows.Forms.Panel -Property @{ Height = 70 BackColor = [System.Drawing.Color]::FromArgb(0, 120, 212) Dock = [System.Windows.Forms.DockStyle]::Top } $panel.Controls.Add($headerPanel) # Create title label $lblTitle = New-Object System.Windows.Forms.Label -Property @{ Text = 'Active Roles' Location = [System.Drawing.Point]::new(15, 12) Size = [System.Drawing.Size]::new(200, 25) Font = [System.Drawing.Font]::new("Segoe UI", 12, [System.Drawing.FontStyle]::Bold) ForeColor = [System.Drawing.Color]::White BackColor = [System.Drawing.Color]::Transparent Anchor = ([System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left) } $headerPanel.Controls.Add($lblTitle) # Create role count label (right-aligned) $lblCount = New-Object System.Windows.Forms.Label -Property @{ Name = 'lblActiveCount' Text = '0 roles active' Location = [System.Drawing.Point]::new(0, 27) Size = [System.Drawing.Size]::new(150, 15) Font = [System.Drawing.Font]::new("Segoe UI", 8) ForeColor = [System.Drawing.Color]::White BackColor = [System.Drawing.Color]::Transparent TextAlign = 'MiddleRight' Anchor = ([System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right) } $headerPanel.Controls.Add($lblCount) # Handle header panel resize to reposition count label $headerPanel.Add_Resize({ $lblCount = $this.Controls | Where-Object { $_.Name -eq 'lblActiveCount' } if ($lblCount) { $lblCount.Location = [System.Drawing.Point]::new($this.Width - 170, 27) } }) # Create ListView for active roles $listView = New-Object System.Windows.Forms.ListView -Property @{ Name = 'lstActive' View = [System.Windows.Forms.View]::Details FullRowSelect = $true GridLines = $false CheckBoxes = $true MultiSelect = $true Scrollable = $true Dock = [System.Windows.Forms.DockStyle]::Fill Font = [System.Drawing.Font]::new("Segoe UI", 9) BorderStyle = [System.Windows.Forms.BorderStyle]::None BackColor = [System.Drawing.Color]::White } # Add ListView columns (include a small first column for selection) [void]$listView.Columns.Add("", 30) [void]$listView.Columns.Add("Type", 90) [void]$listView.Columns.Add("Role Name", 220) [void]$listView.Columns.Add("Resource", 180) [void]$listView.Columns.Add("Scope", 120) [void]$listView.Columns.Add("Member Type", 110) [void]$listView.Columns.Add("Expires", 120) # Prevent checking permanent roles (no EndDateTime) $listView.Add_ItemCheck({ param($sender, $e) if ($e.Index -ge 0 -and $e.Index -lt $sender.Items.Count) { $item = $sender.Items[$e.Index] if ($item -is [System.Windows.Forms.ListViewItem]) { $role = $item.Tag $isPermanent = -not ($role -and $role.PSObject.Properties['EndDateTime'] -and $role.EndDateTime) if ($isPermanent) { # Block checking permanent items $e.NewValue = [System.Windows.Forms.CheckState]::Unchecked } } } }) # Use default header drawing (no owner-draw) # Handle column header clicks for select all functionality $listView.Add_ColumnClick({ param($sender, $e) if ($e.Column -eq 0) { # Toggle all checkboxes for deactivatable (non-permanent) items only $allChecked = $true $hasDeactivatable = $false if ($sender.Items.Count -gt 0) { foreach ($item in $sender.Items) { if ($item -is [System.Windows.Forms.ListViewItem]) { $role = $item.Tag $deactivatable = ($role -and $role.PSObject.Properties['EndDateTime'] -and $role.EndDateTime) if ($deactivatable) { $hasDeactivatable = $true if (-not $item.Checked) { $allChecked = $false break } } } } if ($hasDeactivatable) { $newState = -not $allChecked foreach ($item in $sender.Items) { if ($item -is [System.Windows.Forms.ListViewItem]) { $role = $item.Tag $deactivatable = ($role -and $role.PSObject.Properties['EndDateTime'] -and $role.EndDateTime) if ($deactivatable) { $item.Checked = $newState } } } } } } }) # Create Select All button (after ListView is created) $btnSelectAll = New-Object System.Windows.Forms.Button -Property @{ Text = "☐ Select All" Size = New-Object System.Drawing.Size(100, 25) Location = New-Object System.Drawing.Point(10, 10) FlatStyle = [System.Windows.Forms.FlatStyle]::Flat BackColor = [System.Drawing.Color]::FromArgb(240, 240, 240) ForeColor = [System.Drawing.Color]::FromArgb(32, 31, 30) Font = New-Object System.Drawing.Font("Segoe UI", 9) Name = "btnActiveSelectAll" } # Keep a direct reference to the ListView to avoid closure scope issues $btnSelectAll.Tag = $listView # Add Select All click handler (use the ListView stored in Tag) $btnSelectAll.Add_Click({ param($sender, $e) $lv = [System.Windows.Forms.ListView]$sender.Tag $allChecked = $true $hasDeactivatable = $false if ($lv -and $lv.Items.Count -gt 0) { foreach ($item in $lv.Items) { if ($item -is [System.Windows.Forms.ListViewItem]) { $role = $item.Tag $deactivatable = ($role -and $role.PSObject.Properties['EndDateTime'] -and $role.EndDateTime) if ($deactivatable) { $hasDeactivatable = $true if (-not $item.Checked) { $allChecked = $false break } } } } if ($hasDeactivatable) { $newState = -not $allChecked foreach ($item in $lv.Items) { if ($item -is [System.Windows.Forms.ListViewItem]) { $role = $item.Tag $deactivatable = ($role -and $role.PSObject.Properties['EndDateTime'] -and $role.EndDateTime) if ($deactivatable) { $item.Checked = $newState } } } # Update button text directly after change $btn = $lv.Parent.Parent.Controls['btnActiveSelectAll'] if ($btn) { $btn.Text = if ($newState) { "☑ Select All" } else { "☐ Select All" } } } } }) # Update Select All button text based on selection state (resolve button by name to avoid scope issues) $listView.Add_ItemChecked({ param($sender, $e) if ($sender.Items.Count -gt 0) { $allSelected = $true $anySelected = $false $hasDeactivatable = $false foreach ($item in $sender.Items) { if ($item -is [System.Windows.Forms.ListViewItem]) { $role = $item.Tag $deactivatable = ($role -and $role.PSObject.Properties['EndDateTime'] -and $role.EndDateTime) if ($deactivatable) { $hasDeactivatable = $true if ($item.Checked) { $anySelected = $true } else { $allSelected = $false } } } } $panelCtrl = $sender.Parent.Parent $btn = $panelCtrl.Controls['btnActiveSelectAll'] if ($btn) { if ($hasDeactivatable -and $allSelected) { $btn.Text = "☑ Select All" } elseif ($anySelected) { $btn.Text = "☑ Select All" } else { $btn.Text = "☐ Select All" } } } }) # Add the Select All button to the panel $panel.Controls.Add($btnSelectAll) # Create ListView container $listViewContainer = New-Object System.Windows.Forms.Panel -Property @{ Dock = [System.Windows.Forms.DockStyle]::Fill Padding = New-Object System.Windows.Forms.Padding(0, 75, 0, 0) } $listViewContainer.Controls.Add($listView) $panel.Controls.Add($listViewContainer) return $panel } |