Files
Logo/testTaskGate.ps1
2025-05-17 14:45:45 -04:00

339 lines
12 KiB
PowerShell

###-----------------------------------------------------------------------------###
### SVS TaskGate Launcher
###-----------------------------------------------------------------------------###
# 1) GLOBAL LOG CACHE
if (-not $Global:LogCache -or -not ($Global:LogCache -is [System.Collections.ArrayList])) {
$Global:LogCache = New-Object System.Collections.ArrayList
}
#region Write-LogHybrid
if (-not (Get-Command Write-Log -ErrorAction SilentlyContinue)) {
function Write-LogHelper {
param(
[string]$Message,
[ValidateSet("Info","Warning","Error","Success","General")]
[string]$Level = "Info",
[string]$TaskCategory = "GeneralTask",
[switch]$LogToEvent,
[string]$EventSource = "SVSMSP_Module",
[string]$EventLog = "Application"
)
$EventID = switch($Level){
"Info" {1000}; "Warning"{2000}; "Error"{3000}; "Success"{4000}; default{1000}
}
$Icon = switch($Level){
"Info" { [char]0x1F4CB }
"Warning" { [char]0x26A0 }
"Error" { [char]0x274C }
"Success" { [char]0x2705 }
default { [char]0x1F4E6 }
}
$entry = [PSCustomObject]@{
Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
Level = $Level
Message = "$Icon [$Level] [$TaskCategory] $Message (Event ID: $EventID)"
}
[void]$Global:LogCache.Add($entry)
if ($LogToEvent) {
try {
if (-not (Get-EventLog -LogName $EventLog -Source $EventSource -ErrorAction SilentlyContinue)) {
New-EventLog -LogName $EventLog -Source $EventSource -ErrorAction SilentlyContinue
}
Write-EventLog -LogName $EventLog -Source $EventSource `
-EntryType $Level -EventId $EventID -Message $Message
} catch {
Write-Host "⚠ Failed writing to EventLog: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
}
function Write-LogHybrid { param($Message,$Level,$TaskCategory,$LogToEvent)
Write-LogHelper -Message $Message -Level $Level -TaskCategory $TaskCategory -LogToEvent:$LogToEvent
}
} else {
function Write-LogHybrid { param($Message,$Level,$TaskCategory,$LogToEvent)
Write-Log -Message $Message -Level $Level -TaskCategory $TaskCategory -LogToEvent:$LogToEvent
}
}
Write-LogHybrid -Message "Starting SVS TaskGate" -Level Info -TaskCategory Startup -LogToEvent
#region Helpers for DattoRMM, LastPass, SVS Module…
# (Insert your existing Install-DattoRMM-Helper, LastPass and Install-SVSMSP functions here.)
#endregion
#region HTTP Listener Setup
$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add("http://localhost:8081/")
$listener.Start()
Write-LogHybrid -Message "Listener started on http://localhost:8081/" -Level Info -TaskCategory Listener
#endregion
#region HTML UI & CSS
function GetHtmlContent {
@"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVS TaskGate</title>
<link rel="icon" href="https://git.svstools.com/syelle/Logo/raw/branch/main/SVS_Favicon.ico">
<style>
:root {
--background-color: rgba(18,18,18,1);
--border-color: rgba(255,127,0,0.25);
--white-color: rgba(255,255,255,1);
--gray-color: rgba(102,102,102,1);
--btn-success: rgba(40,167,69,1);
--btn-success-disabled: rgba(108,117,125,1);
--btn-danger: rgba(220,53,69,1);
--btn-sidebar-light-gray: rgba(68,68,68,1);
--btn-sidebar-blue: rgba(30,144,255,1);
--btn-hover: rgba(0,86,179,1);
--btn-hover-scale: 1.05;
}
body {
margin:0; padding:0;
background:var(--background-color);
color:var(--white-color);
font-family:Arial,sans-serif;
height:100vh; overflow:hidden;
}
.logo-container {
padding:20px; background:var(--background-color);
}
.logo-container img { max-width:200px; }
.container { display:flex; height:calc(100% - 60px); }
.sidebar {
width:200px; padding:10px;
background:var(--background-color);
}
.sidebar button {
width:100%; margin-bottom:10px; padding:10px;
background:var(--btn-sidebar-light-gray);
border:none; border-radius:4px;
color:var(--white-color);
text-align:left; cursor:pointer;
transition:background 0.2s,transform 0.2s;
}
.sidebar button.active {
background:var(--btn-sidebar-blue);
}
.sidebar button:hover {
background:var(--btn-hover);
transform:scale(var(--btn-hover-scale));
}
.content {
flex:1; padding:20px; overflow-y:auto;
}
.tab-content { display:none; }
.tab-content.active { display:block; }
.button-group {
margin-top:20px; text-align:right;
}
.button-group button {
margin-left:10px; padding:0.75rem 1.5rem;
border:none; border-radius:4px; cursor:pointer;
font-size:1rem;
transition:opacity 0.1s;
}
.button-group button:hover:not(:disabled) { opacity:0.9; }
.install-button {
background:var(--btn-success); color:#fff;
}
.install-button:disabled {
background:var(--btn-success-disabled); cursor:not-allowed;
}
.exit-button {
background:var(--btn-danger); color:#fff;
}
/* HIDE the old log pane */
.log { display:none !important; }
</style>
</head>
<body>
<div class="logo-container">
<img src="https://git.svstools.com/syelle/Logo/raw/branch/main/SVS_logo.svg" alt="SVS Logo">
</div>
<div class="container">
<div class="sidebar">
<button class="tab-button active" data-tab="onboardTab" aria-expanded="true">On-Boarding</button>
<button class="tab-button" data-tab="tweaksTab">Apply Tweaks</button>
<button class="tab-button" data-tab="SVSAppsTab">Install SVS Apps</button>
</div>
<div class="content">
<!-- On-Boarding (just placeholder for context) -->
<div id="onboardTab" class="tab-content active">
<h2>On-Boarding</h2>
<p>your original onboarding controls</p>
</div>
<!-- Tweaks Tab -->
<div id="tweaksTab" class="tab-content">
<h2>Apply Tweaks</h2>
<div id="tweaksGroup" class="checkbox-group">
<label><input type="checkbox" id="disableAnimations"> Disable Animations</label><br>
<label><input type="checkbox" id="optimizePerformance"> Optimize Performance</label><br>
<label><input type="checkbox" id="increaseFontSize"> Increase Font Size</label>
</div>
<div class="button-group">
<button class="install-button" onclick="triggerTweaks()">Apply Tweaks</button>
</div>
</div>
<!-- SVS Apps Tab -->
<div id="SVSAppsTab" class="tab-content">
<h2>Install SVS Apps</h2>
<div id="wingetGroup" class="checkbox-group">
<h4>Winget Apps</h4>
<label><input class="winget-checkbox" name="wingetLastpass" type="checkbox"> LastPass</label><br>
<label><input class="winget-checkbox" name="wingetBitwarden" type="checkbox"> Bitwarden</label>
</div>
<div id="extensionsGroup" class="checkbox-group">
<h4>Browser Extensions</h4>
<label><input class="extension-checkbox" name="installLastPassChrome" type="checkbox"> LastPass Chrome</label><br>
<label><input class="extension-checkbox" name="installLastPassEdge" type="checkbox"> LastPass Edge</label>
</div>
<div class="button-group">
<button class="install-button" onclick="triggerSVSApps()">Install SVS Apps</button>
</div>
</div>
</div>
</div>
<script>
// 1) TAB NAVIGATION
const tabButtons = document.querySelectorAll('.tab-button');
const tabContents = document.querySelectorAll('.tab-content');
tabButtons.forEach(btn => {
btn.addEventListener('click', () => {
tabButtons.forEach(b=>{ b.classList.remove('active'); b.setAttribute('aria-expanded','false') });
tabContents.forEach(c=>c.classList.remove('active'));
btn.classList.add('active');
btn.setAttribute('aria-expanded','true');
document.getElementById(btn.dataset.tab).classList.add('active');
});
});
// 2) TRIGGER APPLY TWEAKS
function triggerTweaks() {
const tweaks = Array.from(
document.querySelectorAll('#tweaksGroup input[type="checkbox"]')
)
.filter(cb=>cb.checked)
.map(cb=>cb.id);
if (tweaks.length === 0) {
alert("Select at least one tweak.");
return;
}
fetch('/runTweaks', {
method: 'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({ tweaks })
})
.then(r=>r.ok ? alert("Tweaks applied!") : alert("Error applying tweaks"))
.catch(e=>alert("Network error: "+e));
}
// 3) TRIGGER INSTALL SVS APPS
function triggerSVSApps() {
const wingetSel = Array.from(
document.querySelectorAll('.winget-checkbox')
).filter(cb=>cb.checked).map(cb=>cb.name);
const extSel = Array.from(
document.querySelectorAll('.extension-checkbox')
).filter(cb=>cb.checked).map(cb=>cb.name);
if (wingetSel.length+extSel.length === 0) {
alert("Select at least one app or extension.");
return;
}
fetch('/installSVSApps', {
method: 'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({ winget: wingetSel, extensions: extSel })
})
.then(r=>r.ok ? alert("Installation triggered!") : alert("Error triggering install"))
.catch(e=>alert("Network error: "+e));
}
</script>
</body>
</html>
"@
}
#endregion
# 3) LAUNCH THE UI
Start-Process "msedge.exe" -ArgumentList "--app=http://localhost:8081/"
#region 4) ROUTE HANDLING
try {
while ($listener.IsListening) {
$ctx = $listener.GetContext()
$req = $ctx.Request
$res = $ctx.Response
switch ($req.Url.AbsolutePath) {
"/" {
$html = GetHtmlContent
$bytes = [Text.Encoding]::UTF8.GetBytes($html)
$res.ContentType = "text/html"
$res.ContentLength64 = $bytes.Length
$res.OutputStream.Write($bytes,0,$bytes.Length)
$res.OutputStream.Close()
}
"/runTweaks" {
if ($req.HttpMethod -eq "POST") {
$body = (New-Object IO.StreamReader $req.InputStream).ReadToEnd() | ConvertFrom-Json
Write-LogHybrid -Message "Tweaks: $($body.tweaks -join ', ')" -Level Info -TaskCategory Tweaks
# TODO: call your actual tweak functions here...
$res.StatusCode = 200
$res.OutputStream.Write(([Text.Encoding]::UTF8.GetBytes("OK")),0,2)
}
}
"/installSVSApps" {
if ($req.HttpMethod -eq "POST") {
$data = (New-Object IO.StreamReader $req.InputStream).ReadToEnd() | ConvertFrom-Json
Write-LogHybrid -Message "Winget: $($data.winget -join ', ')" -Level Info -TaskCategory "SVSApps"
Write-LogHybrid -Message "Extensions: $($data.extensions -join ', ')" -Level Info -TaskCategory "SVSApps"
# TODO: invoke your winget & extension helpers here...
$res.StatusCode = 200
$res.OutputStream.Write(([Text.Encoding]::UTF8.GetBytes("OK")),0,2)
}
}
"/quit" {
$res.StatusCode = 200
$res.OutputStream.Write(([Text.Encoding]::UTF8.GetBytes("bye")),0,3)
$listener.Stop()
break
}
default {
$res.StatusCode = 404
$res.OutputStream.Write(([Text.Encoding]::UTF8.GetBytes("Not Found")),0,9)
}
}
}
}
finally {
if ($listener) {
Write-LogHybrid -Message "Stopping listener" -Level Info -TaskCategory Listener
$listener.Stop(); $listener.Close()
}
}