Add src/ui.ps1
This commit is contained in:
196
src/ui.ps1
Normal file
196
src/ui.ps1
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
function Publish-Checkboxes {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)][string]$Page,
|
||||||
|
[string]$Column,
|
||||||
|
[string]$Group
|
||||||
|
)
|
||||||
|
|
||||||
|
function Escape-HtmlAttr {
|
||||||
|
param([string]$s)
|
||||||
|
if ([string]::IsNullOrEmpty($s)) { return '' }
|
||||||
|
$s = $s -replace "(`r`n|`r|`n)", ' '
|
||||||
|
$s = $s -replace '&','&'
|
||||||
|
$s = $s -replace '"','"'
|
||||||
|
$s = $s -replace "'",'''
|
||||||
|
$s = $s -replace '<','<'
|
||||||
|
$s = $s -replace '>','>'
|
||||||
|
return $s
|
||||||
|
}
|
||||||
|
|
||||||
|
function Escape-HtmlText {
|
||||||
|
param([string]$s)
|
||||||
|
if ([string]::IsNullOrEmpty($s)) { return '' }
|
||||||
|
$s = $s -replace '&','&'
|
||||||
|
$s = $s -replace '<','<'
|
||||||
|
$s = $s -replace '>','>'
|
||||||
|
return $s
|
||||||
|
}
|
||||||
|
|
||||||
|
$tasks = $Global:SamyTasks | Where-Object Page -EQ $Page
|
||||||
|
|
||||||
|
if (-not [string]::IsNullOrEmpty($Column)) {
|
||||||
|
$tasks = $tasks | Where-Object Column -EQ $Column
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not [string]::IsNullOrEmpty($Group)) {
|
||||||
|
if ($Group -eq 'tweaks') {
|
||||||
|
$tasks = $tasks | Where-Object {
|
||||||
|
-not ($_.PSObject.Properties.Name -contains 'Group') -or
|
||||||
|
[string]$_.Group -eq '' -or
|
||||||
|
[string]$_.Group -eq 'tweaks'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$tasks = $tasks | Where-Object {
|
||||||
|
($_.PSObject.Properties.Name -contains 'Group') -and
|
||||||
|
([string]$_.Group -eq $Group)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
$tasks | ForEach-Object {
|
||||||
|
|
||||||
|
$taskId = $_.Id
|
||||||
|
$rawTooltip = if ($_.PSObject.Properties.Name -contains 'Tooltip' -and $_.Tooltip) { [string]$_.Tooltip } else { [string]$_.Label }
|
||||||
|
$tooltipText = Escape-HtmlAttr $rawTooltip
|
||||||
|
$tooltipAttr = if ([string]::IsNullOrWhiteSpace($tooltipText)) { '' } else { " title=`"$tooltipText`"" }
|
||||||
|
|
||||||
|
$labelText = Escape-HtmlText ([string]$_.Label)
|
||||||
|
|
||||||
|
$taskIdAttr = Escape-HtmlAttr ([string]$taskId)
|
||||||
|
$nameAttr = Escape-HtmlAttr ([string]$_.Name)
|
||||||
|
$colAttr = Escape-HtmlAttr ([string]$Column)
|
||||||
|
|
||||||
|
$groupValue = ''
|
||||||
|
if ($_.PSObject.Properties.Name -contains 'Group' -and $_.Group) { $groupValue = [string]$_.Group }
|
||||||
|
$groupAttr = Escape-HtmlAttr $groupValue
|
||||||
|
$groupDataAttr = if ([string]::IsNullOrWhiteSpace($groupAttr)) { '' } else { " data-group=""$groupAttr""" }
|
||||||
|
|
||||||
|
$html = "<label$tooltipAttr><input type=""checkbox"" id=""$taskIdAttr"" name=""$nameAttr"" data-column=""$colAttr""$groupDataAttr> $labelText</label>"
|
||||||
|
|
||||||
|
if ($_.SubOptions) {
|
||||||
|
|
||||||
|
$subHtml = (
|
||||||
|
$_.SubOptions | ForEach-Object {
|
||||||
|
|
||||||
|
$type = if ($_.PSObject.Properties.Name -contains 'Type' -and $_.Type) { [string]$_.Type } else { 'checkbox' }
|
||||||
|
|
||||||
|
if ($type -eq 'text') {
|
||||||
|
$subId = Escape-HtmlAttr ([string]$_.Id)
|
||||||
|
$subLabel = Escape-HtmlText ([string]$_.Label)
|
||||||
|
$ph = if ($_.PSObject.Properties.Name -contains 'Placeholder') { Escape-HtmlAttr ([string]$_.Placeholder) } else { '' }
|
||||||
|
$help = if ($_.PSObject.Properties.Name -contains 'Help') { Escape-HtmlText ([string]$_.Help) } else { '' }
|
||||||
|
|
||||||
|
@"
|
||||||
|
<div style="margin-left:20px; margin-top:6px;">
|
||||||
|
<label for="$subId">$subLabel</label>
|
||||||
|
<input type="text" id="$subId" placeholder="$ph" />
|
||||||
|
<small style="display:block; margin-top:4px;">$help</small>
|
||||||
|
</div>
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$subLabel = Escape-HtmlText ([string]$_.Label)
|
||||||
|
$subTaskIdClass = Escape-HtmlAttr ([string]$taskId)
|
||||||
|
$subValueAttr = Escape-HtmlAttr ([string]$_.Value)
|
||||||
|
|
||||||
|
"<label style=""margin-left:20px; display:block;"">
|
||||||
|
<input type=""checkbox"" class=""sub-option-$subTaskIdClass"" name=""$subValueAttr"" value=""$subValueAttr""> $subLabel
|
||||||
|
</label>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) -join "`n"
|
||||||
|
|
||||||
|
$html += @"
|
||||||
|
<div id="$(Escape-HtmlAttr ([string]$taskId))OptionsContainer" style="display:none; margin-top:4px;">
|
||||||
|
$subHtml
|
||||||
|
</div>
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
$html
|
||||||
|
}
|
||||||
|
) -join "`n"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-ModuleVersionHtml {
|
||||||
|
$mod = Get-Module -ListAvailable -Name SVSMSP | Sort-Object Version -Descending | Select-Object -First 1
|
||||||
|
|
||||||
|
$branchDisplay = switch ($Script:SamyBranch.ToLower()) {
|
||||||
|
'main' { 'Main / Stable' }
|
||||||
|
'beta' { 'Beta' }
|
||||||
|
default { $Script:SamyBranch }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($mod) {
|
||||||
|
return "<div style='color:#bbb; font-size:0.9em; margin-top:1em;'>
|
||||||
|
Module Version: $($mod.Version)<br>
|
||||||
|
UI Branch: $branchDisplay
|
||||||
|
</div>"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "<div style='color:#f66;'>SVSMSP_Module not found</div>"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-UIHtml {
|
||||||
|
param([string]$Page = 'onboard')
|
||||||
|
if (-not $Page) { $Page = 'onboard' }
|
||||||
|
|
||||||
|
$onboardLeft = Publish-Checkboxes -Page 'onboard' -Column 'left'
|
||||||
|
$onboardRightApps = Publish-Checkboxes -Page 'onboard' -Column 'right' -Group 'apps'
|
||||||
|
$onboardRightTweaks = Publish-Checkboxes -Page 'onboard' -Column 'right' -Group 'tweaks'
|
||||||
|
$offboard = Publish-Checkboxes -Page 'offboard' -Column ''
|
||||||
|
$devices = Publish-Checkboxes -Page 'devices' -Column ''
|
||||||
|
|
||||||
|
$tasksJson = @(
|
||||||
|
$Global:SamyTasks | ForEach-Object {
|
||||||
|
[pscustomobject]@{
|
||||||
|
id = [string]$_.Id
|
||||||
|
handler = "/$([string]$_.Name)"
|
||||||
|
label = [string]$_.Label
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) | ConvertTo-Json -Depth 4
|
||||||
|
|
||||||
|
$tasksJsAll = $tasksJson
|
||||||
|
|
||||||
|
$cssContent = Get-RemoteText -Url $Script:SamyCssUrl
|
||||||
|
$jsContent = Get-RemoteText -Url $Script:SamyJsUrl
|
||||||
|
$htmlTemplate = Get-RemoteText -Url $Script:SamyHtmlUrl
|
||||||
|
|
||||||
|
if (-not $htmlTemplate) {
|
||||||
|
Write-LogHybrid "UI template download failed. Returning minimal error page." Error UI -LogToEvent
|
||||||
|
return "<html><body style='font-family:Segoe UI; padding:20px; background:#111; color:#ddd;'>
|
||||||
|
<h2>SAMY UI template unavailable</h2>
|
||||||
|
<p>Could not download samy.html from repo.</p>
|
||||||
|
</body></html>"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($cssContent) {
|
||||||
|
$cssContent += @"
|
||||||
|
/* SAMY background override injected by script */
|
||||||
|
.sidebar::after {
|
||||||
|
background-image: url('$Script:SamyBgLogoUrl') !important;
|
||||||
|
}
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = $htmlTemplate
|
||||||
|
$html = $html.Replace('{{CssContent}}', $cssContent)
|
||||||
|
$html = $html.Replace('{{JsContent}}', $jsContent)
|
||||||
|
$html = $html.Replace('{{SamyFaviconUrl}}', $Script:SamyFaviconUrl)
|
||||||
|
$html = $html.Replace('{{SamyTopLogoUrl}}', $Script:SamyTopLogoUrl)
|
||||||
|
$html = $html.Replace('{{SamyHintText}}', $Script:SamyHintText)
|
||||||
|
|
||||||
|
$html = $html.Replace('{{moduleVersion}}', (Get-ModuleVersionHtml))
|
||||||
|
$html = $html.Replace('{{onboardLeftColumn}}', $onboardLeft)
|
||||||
|
$html = $html.Replace('{{onboardRightApps}}', $onboardRightApps)
|
||||||
|
$html = $html.Replace('{{onboardRightTweaks}}', $onboardRightTweaks)
|
||||||
|
$html = $html.Replace('{{offboardCheckboxes}}', $offboard)
|
||||||
|
$html = $html.Replace('{{devicesCheckboxes}}', $devices)
|
||||||
|
$html = $html.Replace('{{tasksJsAll}}', $tasksJsAll)
|
||||||
|
$html = $html.Replace('{{defaultPage}}', $Page)
|
||||||
|
|
||||||
|
return $html
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user