Files
IntuneManagement/UI/Avalonia/Extensions/IntuneManagerPolicySearchUI.ps1
T

120 lines
4.6 KiB
PowerShell

# Scoped policy picker (Avalonia).
#
# Avalonia port of UI/WPF/Extensions/IntuneManagerPolicySearchUIWPF.ps1. Thin
# wrapper over Show-ObjectPickerDialog: it supplies the scope list and a search
# handler, so the dialog queries Graph for the typed name inside the selected
# policy group / policy type instead of enumerating the whole tenant up front.
# The search itself lives in Internal/PolicySearch.ps1 and is shared with WPF
# (R10 - this file only collects input and renders).
function Show-PolicySearchDialog
{
param(
[string] $Title = "Select policy",
# Preselects this policy type in the "Search in" dropdown.
[string] $DefaultPolicyTypeId,
# Ids to keep out of the results (e.g. the policy being compared).
[string[]] $ExcludeIds,
# Rows to show before the first search. The compare flows seed this
# from the main view's already-loaded list so the dialog opens with
# something useful in it.
[object[]] $InitialItems
)
$scopes = Get-PolicySearchScopes -DefaultPolicyTypeId $DefaultPolicyTypeId
if (@($scopes).Count -eq 0) {
Show-MessageBox "No policy types are available to search." "Select policy" "OK" "Warning" | Out-Null
return $null
}
$defaultKey = Get-PolicySearchDefaultScopeKey -Scopes $scopes -PolicyTypeId $DefaultPolicyTypeId
# Empty unless more than one tenant is signed in; the dialog hides the combo
# in that case and every search runs against the default token.
$tenants = Get-PolicySearchTenants
$defaultTenantKey = Get-PolicySearchDefaultTenantKey -Tenants $tenants
$cols = @(
[PSCustomObject]@{ Header = "Name"; Binding = "Name" }
[PSCustomObject]@{ Header = "Type"; Binding = "PolicyType.Title" }
)
# Handler inputs go on module scope, not into a closure: the handlers are
# rebound to the module, which strips captured locals (see the note in
# Show-ObjectPickerDialog).
$script:_policySearchState = @{
ExcludeIds = $ExcludeIds
MinLength = Get-PolicySearchMinLength
}
$searchHandler = (ConvertTo-AvaloniaEventScriptBlock {
param($SearchText, $Scope)
$st = $script:_policySearchState
if (-not $Scope) { return @() }
if ([String]::IsNullOrWhiteSpace($SearchText) -or $SearchText.Trim().Length -lt $st.MinLength) {
Set-PickerStatusText "Type at least $($st.MinLength) characters, or use 'Load all in scope'."
return @()
}
# $null when the dialog is single-tenant, in which case the default
# token is used.
$tenant = Get-PickerSelectedTenant
$tokenId = if ($tenant) { [int]$tenant.TokenId } else { Get-DefaultTokenId }
$where = if ($tenant) { " in $($tenant.Title)" } else { "" }
Write-Status "Searching $($Scope.Title.Trim())$where..."
try {
$found = @(Search-IntunePolicies -Scope $Scope -SearchText $SearchText.Trim() -ExcludeIds $st.ExcludeIds -TokenId $tokenId)
if ($found.Count -eq 0) {
Set-PickerStatusText "No object in $($Scope.Title.Trim())$where matches '$($SearchText.Trim())'."
}
else {
Set-PickerStatusText "$($found.Count) object(s) found$where."
}
return $found
}
finally {
Write-Status ""
}
})
$loadHandler = (ConvertTo-AvaloniaEventScriptBlock {
$st = $script:_policySearchState
$scope = Get-PickerSelectedScope
if (-not $scope) { return @() }
$tenant = Get-PickerSelectedTenant
$tokenId = if ($tenant) { [int]$tenant.TokenId } else { Get-DefaultTokenId }
$where = if ($tenant) { " in $($tenant.Title)" } else { "" }
Write-Status "Loading all objects in $($scope.Title.Trim())$where..."
try {
$loaded = @(Search-IntunePolicies -Scope $scope -ExcludeIds $st.ExcludeIds -TokenId $tokenId)
Set-PickerStatusText "$($loaded.Count) object(s) in $($scope.Title.Trim())$where."
return $loaded
}
finally {
Write-Status ""
}
})
try {
return Show-ObjectPickerDialog `
-Title $Title `
-Items $InitialItems `
-DisplayColumns $cols `
-Scopes $scopes `
-SelectedScopeKey $defaultKey `
-Tenants $tenants `
-SelectedTenantKey $defaultTenantKey `
-SearchHandler $searchHandler `
-LoadHandler $loadHandler `
-LoadLabel "Load all in scope"
}
finally {
$script:_policySearchState = $null
}
}