Update StackMonkey-test.ps1

This commit is contained in:
2025-06-12 15:44:23 -04:00
parent 4d214e16a5
commit aba1c019af

View File

@@ -41,130 +41,17 @@ $Global:Tasks = @(
# On-Boarding, right column (optional bits) # On-Boarding, right column (optional bits)
@{ Id='enableBitLocker'; Name='EnableBitLocker'; Label='Enable BitLocker'; HandlerFn='Set-SVSBitLocker'; Page='onboard'; Column='right' }, @{ Id='enableBitLocker'; Name='EnableBitLocker'; Label='Enable BitLocker'; HandlerFn='Set-SVSBitLocker'; Page='onboard'; Column='right' },
# @{ Id='setEdgeDefaultSearch';Name='setedgedefaultsearch';Label='Set Edge Default Search'; Tooltip='Will configure Edge to use Google as default search provider'; HandlerFn='set-EdgeDefaultSearchProvider';Page='onboard'; Column='right' }, @{ Id='setEdgeDefaultSearch';Name='setedgedefaultsearch';Label='Set Edge Default Search'; Tooltip='Will configure Edge to use Google as default search provider'; HandlerFn='set-EdgeDefaultSearchProvider';Page='onboard'; Column='right' },
# Off-Boarding # Off-Boarding
@{ Id='uninstallCyberQP'; Name='uninstallCyberQP'; Label='Uninstall CyberQP'; HandlerFn='Uninstall-CyberQP'; Page='offboard' }, @{ Id='uninstallCyberQP'; Name='uninstallCyberQP'; Label='Uninstall CyberQP'; HandlerFn='Uninstall-CyberQP'; Page='offboard' },
@{ Id='uninstallSVSMSPModule'; Name='uninstallSVSMSPModule'; Label='Uninstall SVSMSP Module'; HandlerFn='Cleanup-SVSMSP'; Page='offboard' }, @{ Id='uninstallSVSMSPModule'; Name='uninstallSVSMSPModule'; Label='Uninstall SVSMSP Module'; HandlerFn='Cleanup-SVSMSP'; Page='offboard' },
# ───────────────────────────────────────────────────────────────────────────── # Tweaks
# Tweaks: one entry per PS1 file, with hidden <div> of radiobuttons for params @{ Id='disableAnimations'; Name='disableAnimations'; Label='Disable Animations'; HandlerFn='Disable-Animations'; Page='tweaks' },
# ─────────────────────────────────────────────────────────────────────────────
@{
Id = 'setEdgeDefaultSearch';
Name = 'setEdgeDefaultSearch';
Label = 'Set Edge Default Search';
Tooltip = 'Choose which search engine Edge should use (or Reset to defaults)';
HandlerFn = 'Handle-SetEdgeDefaultSearch';
Page = 'tweaks';
Column = '';
SubOptions = @(
@{
ParamName = 'SearchProviderName';
Type = 'radio';
Options = @('Google', 'Bing', 'DuckDuckGo');
Default = 'Google'
},
@{
ParamName = 'Reset';
Type = 'radio';
Options = @('No', 'Yes');
Default = 'No'
}
)
},
@{
Id = 'setTextEditor';
Name = 'setTextEditor';
Label = 'Set Default Text Editor';
Tooltip = 'Pick your preferred default text editor for .txt and .ps1 files.';
HandlerFn = 'Handle-SetTextEditor';
Page = 'tweaks';
Column = '';
SubOptions = @(
@{
ParamName = 'Editor';
Type = 'radio';
Options = @('Notepad', 'Notepad++', 'VSCode');
Default = 'Notepad'
}
)
},
@{
Id = 'setWindowsPerformance';
Name = 'setWindowsPerformance';
Label = 'Optimize Windows Performance';
Tooltip = 'Choose performance mode or restore defaults.';
HandlerFn = 'Handle-SetWindowsPerformance';
Page = 'tweaks';
Column = '';
SubOptions = @(
@{
ParamName = 'Mode';
Type = 'radio';
Options = @('Gaming', 'Balanced', 'PowerSaver');
Default = 'Balanced'
},
@{
ParamName = 'RestoreDefaults';
Type = 'radio';
Options = @('No', 'Yes');
Default = 'No'
}
)
},
@{
Id = 'stopUnnecessaryServices';
Name = 'stopUnnecessaryServices';
Label = 'Stop Unnecessary Services';
Tooltip = 'Log actions to file or just run silently.';
HandlerFn = 'Handle-StopUnnecessaryServices';
Page = 'tweaks';
Column = '';
SubOptions = @(
@{
ParamName = 'LogFilePathChoice';
Type = 'radio';
Options = @('NoLogging', 'DefaultPath', 'CustomPath');
Default = 'NoLogging'
}
# If you want to allow a “custom path” textbox, you can detect when "CustomPath" is selected
# on the frontend and show an <input type="text">. (See note below.)
)
},
@{
Id = 'setBrowserPwdPolicy';
Name = 'setBrowserPwdPolicy';
Label = 'Enforce Browser Password Policy';
Tooltip = 'Enable or disable saving passwords and set expiration days.';
HandlerFn = 'Handle-SetBrowserPwdPolicy';
Page = 'tweaks';
Column = '';
SubOptions = @(
@{
ParamName = 'DisableSavePasswords';
Type = 'radio';
Options = @('No', 'Yes');
Default = 'No'
},
@{
ParamName = 'PasswordExpirationDays';
Type = 'radio';
Options = @('30', '60', '90', 'Never');
Default = '90'
}
)
},
# SVS Apps # SVS Apps
@{ Id='wingetLastpass'; Name='wingetLastpass'; Label='LastPass Desktop App'; HandlerFn='Install-WingetLastPass'; Page='SVSApps' } @{ Id='wingetLastpass'; Name='wingetLastpass'; Label='LastPass Desktop App'; HandlerFn='Install-WingetLastPass'; Page='SVSApps' }
) )
#endregion #endregion
@@ -613,52 +500,6 @@ function Handle-InstallDattoRMM {
} }
#--------------------------------------------------------------------------
# Handle function for the Tweaks tab
#--------------------------------------------------------------------------
function Handle-SetEdgeDefaultSearch {
param($Context)
# Read which radio was chosen:
# Youll receive a GET or POST? In the existing pattern, “tweaks” is GETonly,
# so you cant get the radio values over GET. Youll probably want to change
# those “fetch(t.handler, { method: 'GET' })” calls in JS to send a POST
# with JSON containing all the checkedplusradio values.
# Heres a simple stub:
Write-LogHybrid "Handle-SetEdgeDefaultSearch called" "Info" "Tweaks"
# Response back:
Respond-Text $Context "Applied SetEdgeDefaultSearch with whatever was selected."
}
function Handle-SetTextEditor {
param($Context)
Write-LogHybrid "Handle-SetTextEditor called" "Info" "Tweaks"
Respond-Text $Context "Text editor preference applied."
}
function Handle-SetWindowsPerformance {
param($Context)
Write-LogHybrid "Handle-SetWindowsPerformance called" "Info" "Tweaks"
Respond-Text $Context "WindowsPerformance tweak applied."
}
function Handle-StopUnnecessaryServices {
param($Context)
Write-LogHybrid "Handle-StopUnnecessaryServices called" "Info" "Tweaks"
Respond-Text $Context "Stop-UnnecessaryServices tweak applied."
}
function Handle-SetBrowserPwdPolicy {
param($Context)
Write-LogHybrid "Handle-SetBrowserPwdPolicy called" "Info" "Tweaks"
Respond-Text $Context "Browser password policy tweak applied."
}
# Off-boarding handlers # Off-boarding handlers
function Handle-UninstallCyberQP { function Handle-UninstallCyberQP {
param($Context) param($Context)
@@ -695,93 +536,45 @@ function Install-WingetLastPass {
#region UI Generation #region UI Generation
function Build-Checkboxes { function Build-Checkboxes {
param( param($Page, $Column)
[string] $Page,
[string] $Column
)
# For each task in the given Page & Column, build a <label><input type='checkbox'> and, (
# if it has SubOptions of Type='radio', build a hidden <div> with all the radio buttons. $Global:Tasks |
$htmlList = $Global:Tasks | Where-Object Page -EQ $Page |
Where-Object Page -EQ $Page | Where-Object Column -EQ $Column |
Where-Object Column -EQ $Column | ForEach-Object {
ForEach-Object { $taskId = $_.Id
$taskId = $_.Id $tooltip = if ($_.PSObject.Properties.Name -contains 'Tooltip' -and $_.Tooltip) {
$name = $_.Name " title='$($_.Tooltip)'"
$label = $_.Label } else { '' }
# If a Tooltip property exists, render title='…'
$titleAttr = '' $html = "<label$tooltip><input type='checkbox' id='$taskId' name='$($_.Name)' data-column='$Column'> $($_.Label)</label>"
if ($_.PSObject.Properties.Name -contains 'Tooltip' -and $_.Tooltip) {
# Singlequoted so any apostrophes in tooltip won't break if ($_.SubOptions) {
$titleAttr = " title='$($_.Tooltip)'" # join inside the code block is fine
$subHtml = (
$_.SubOptions |
ForEach-Object {
"<label style='margin-left:20px; display:block;'>
<input type='checkbox' class='sub-option-$taskId' name='$($_.Value)' value='$($_.Value)'> $($_.Label)
</label>"
} }
) -join "`n"
# 1) Render the main checkbox + label: $html += @"
$line = "<label$titleAttr><input type='checkbox' id='$taskId' name='$name' data-column='$Column'> $label</label>" <div id='${taskId}OptionsContainer' style='display:none; margin-top:4px;'>
$subHtml
# 2) If SubOptions exist, render a hidden <div> that contains either checkboxes or radio buttons
if ($_.PSObject.Properties.Name -contains 'SubOptions' -and $_.SubOptions) {
# Build a container whose id ends with “OptionsContainer”
$subContainerId = "${taskId}OptionsContainer"
# We will collect all suboption HTML lines into an array
$subHtmlLines = @()
foreach ($opt in $_.SubOptions) {
$paramName = $opt.ParamName
$type = $opt.Type
$default = $opt.Default
switch ($type) {
'radio' {
# build one <fieldset> per ParamName
# Each radio's “name” attribute needs to be the same (so only one choice).
$fieldsetName = "${taskId}__$paramName"
$subHtmlLines += "<fieldset style='margin-left:20px; border:none; padding:0;'>"
$subHtmlLines += " <legend style='font-size:0.9em; color:#ccc;'>$paramName</legend>"
foreach ($choice in $opt.Options) {
# Mark the default one as checked
$isChecked = if ($choice -eq $default) { " checked" } else { "" }
$radioId = "${taskId}__${paramName}__${choice}"
$subHtmlLines += " <label for='$radioId' style='display:block; margin-bottom:4px;'>"
$subHtmlLines += " <input type='radio' id='$radioId' name='$fieldsetName' value='$choice'$isChecked> $choice"
$subHtmlLines += " </label>"
}
$subHtmlLines += "</fieldset>"
}
default {
# (In case you want other types later, but for now we only handle 'radio')
}
}
}
# Join all lines with newlines
$subHtmlBlock = ($subHtmlLines -join "`n")
# Wrap the suboptions in a div that is hidden by default
$line += @"
<div id='$subContainerId' style='display:none; margin-top:4px;'>
$subHtmlBlock
</div> </div>
"@ "@
}
# Return each chunk of HTML
$line
} }
# Finally, join everything into one string $html
return ($htmlList -join "`n") }
) -join "`n"
} }
### Get SVSMSP module version to display in the UI ### Get SVSMSP module version to display in the UI
function Get-ModuleVersionHtml { function Get-ModuleVersionHtml {
$mod = Get-Module -ListAvailable -Name SVSMSP | Sort-Object Version -Descending | Select-Object -First 1 $mod = Get-Module -ListAvailable -Name SVSMSP | Sort-Object Version -Descending | Select-Object -First 1
@@ -1158,13 +951,6 @@ $style = @'
container.style.display = checked ? 'block' : 'none'; container.style.display = checked ? 'block' : 'none';
container.querySelectorAll('input[type="checkbox"]').forEach(cb => cb.checked = checked); container.querySelectorAll('input[type="checkbox"]').forEach(cb => cb.checked = checked);
// ↓ ADD THIS: whenever we just turned the sub-options on, re-check each radio back to its default
if (checked) {
container.querySelectorAll('input[type="radio"]').forEach(r => {
r.checked = r.defaultChecked;
});
}
// Show/hide Password and RMM only if it's installDattoRMM // Show/hide Password and RMM only if it's installDattoRMM
if (taskId === 'installDattoRMM') { if (taskId === 'installDattoRMM') {
const pwdBox = document.getElementById('PasswordContainer'); const pwdBox = document.getElementById('PasswordContainer');
@@ -1266,7 +1052,6 @@ $htmlTemplate = @"
{{onboardRightColumn}} {{onboardRightColumn}}
</div> </div>
</div> </div>
@@ -1286,9 +1071,9 @@ $htmlTemplate = @"
<select id="dattoDropdown" style="width:100%;"> <select id="dattoDropdown" style="width:100%;">
<option disabled selected>Fetching sites...</option> <option disabled selected>Fetching sites...</option>
</select> </select>
</div> <!-- end of dattoRmmContainer --> </div>
</div> <!-- end of #onboardTab -->
<div id="offboardTab" class="tab-content"> <div id="offboardTab" class="tab-content">
<h2>Off-Boarding</h2> <h2>Off-Boarding</h2>
<div class="columns-container"> <div class="columns-container">