diff --git a/restart_backend.bat b/restart_backend.bat new file mode 100644 index 00000000..fbe6380e --- /dev/null +++ b/restart_backend.bat @@ -0,0 +1,14 @@ +@echo off +echo Killing processes on port 8001... +for /f "tokens=5" %%a in ('netstat -ano ^| findstr ":8001.*LISTENING"') do ( + echo Killing PID %%a + taskkill /F /PID %%a 2>nul +) + +echo Waiting for port to free up... +ping 127.0.0.1 -n 3 >nul + +echo Starting backend... +cd /d C:\Users\antoi\Atomizer\atomizer-dashboard\backend +call C:\Users\antoi\anaconda3\Scripts\activate.bat atomizer +python -m uvicorn api.main:app --port 8001 diff --git a/start_backend_8002.bat b/start_backend_8002.bat new file mode 100644 index 00000000..b25fd61e --- /dev/null +++ b/start_backend_8002.bat @@ -0,0 +1,6 @@ +@echo off +title Atomizer Backend (Port 8002) +echo Starting Atomizer Backend on port 8002... +cd /d C:\Users\antoi\Atomizer\atomizer-dashboard\backend +call C:\Users\antoi\anaconda3\Scripts\activate.bat atomizer +python -m uvicorn api.main:app --port 8002 --reload diff --git a/tools/atomizer.ico b/tools/atomizer.ico new file mode 100644 index 00000000..0fcb6787 Binary files /dev/null and b/tools/atomizer.ico differ diff --git a/tools/create_desktop_shortcut.ps1 b/tools/create_desktop_shortcut.ps1 new file mode 100644 index 00000000..5eb002c1 --- /dev/null +++ b/tools/create_desktop_shortcut.ps1 @@ -0,0 +1,209 @@ +# ============================================================ +# Atomizer Desktop Shortcut Creator +# Creates a desktop shortcut with custom "A" icon +# ============================================================ + +$ErrorActionPreference = "Stop" + +# Paths +$AtomizerRoot = Split-Path -Parent $PSScriptRoot +$ToolsDir = $PSScriptRoot +$IconPath = Join-Path $ToolsDir "atomizer.ico" +$LauncherPath = Join-Path $ToolsDir "launch_atomizer.bat" +$DesktopPath = [Environment]::GetFolderPath("Desktop") +$ShortcutPath = Join-Path $DesktopPath "Atomizer.lnk" + +Write-Host "" +Write-Host " Atomizer Desktop Shortcut Creator" -ForegroundColor Cyan +Write-Host " ===================================" -ForegroundColor Cyan +Write-Host "" + +# Step 1: Create ICO file with "A" letter +Write-Host "[1/3] Creating icon file..." -ForegroundColor Yellow + +# Generate a simple ICO file using .NET +Add-Type -AssemblyName System.Drawing + +function Create-AtomizerIcon { + param([string]$OutputPath) + + # Create multiple icon sizes for best quality + $sizes = @(256, 48, 32, 16) + $bitmaps = @() + + foreach ($size in $sizes) { + $bitmap = New-Object System.Drawing.Bitmap($size, $size) + $graphics = [System.Drawing.Graphics]::FromImage($bitmap) + + # High quality rendering + $graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality + $graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic + $graphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::AntiAliasGridFit + + # Background - gradient blue (Atomizer brand color) + $brush = New-Object System.Drawing.Drawing2D.LinearGradientBrush( + (New-Object System.Drawing.Point(0, 0)), + (New-Object System.Drawing.Point($size, $size)), + [System.Drawing.Color]::FromArgb(255, 59, 130, 246), # Blue-500 + [System.Drawing.Color]::FromArgb(255, 37, 99, 235) # Blue-600 + ) + + # Rounded rectangle background + $path = New-Object System.Drawing.Drawing2D.GraphicsPath + $radius = [int]($size * 0.15) + $rect = New-Object System.Drawing.Rectangle(0, 0, $size, $size) + $path.AddArc($rect.X, $rect.Y, $radius * 2, $radius * 2, 180, 90) + $path.AddArc($rect.Right - $radius * 2, $rect.Y, $radius * 2, $radius * 2, 270, 90) + $path.AddArc($rect.Right - $radius * 2, $rect.Bottom - $radius * 2, $radius * 2, $radius * 2, 0, 90) + $path.AddArc($rect.X, $rect.Bottom - $radius * 2, $radius * 2, $radius * 2, 90, 90) + $path.CloseFigure() + + $graphics.FillPath($brush, $path) + + # Draw "A" letter + $fontSize = [int]($size * 0.65) + $font = New-Object System.Drawing.Font("Segoe UI", $fontSize, [System.Drawing.FontStyle]::Bold) + $textBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::White) + + $format = New-Object System.Drawing.StringFormat + $format.Alignment = [System.Drawing.StringAlignment]::Center + $format.LineAlignment = [System.Drawing.StringAlignment]::Center + + $textRect = New-Object System.Drawing.RectangleF(0, 0, $size, $size) + $graphics.DrawString("A", $font, $textBrush, $textRect, $format) + + # Cleanup + $graphics.Dispose() + $font.Dispose() + $textBrush.Dispose() + $brush.Dispose() + $path.Dispose() + + $bitmaps += $bitmap + } + + # Save as ICO (using the largest bitmap, Windows will auto-select appropriate size) + # For proper multi-size ICO, we'll save the 256x256 and let Windows handle it + $icon = [System.Drawing.Icon]::FromHandle($bitmaps[0].GetHicon()) + + # Write ICO file manually with all sizes + $fs = [System.IO.File]::Create($OutputPath) + $bw = New-Object System.IO.BinaryWriter($fs) + + # ICO Header + $bw.Write([UInt16]0) # Reserved + $bw.Write([UInt16]1) # Type (1 = ICO) + $bw.Write([UInt16]$sizes.Count) # Number of images + + # Calculate offsets + $headerSize = 6 + ($sizes.Count * 16) # Main header + directory entries + $currentOffset = $headerSize + $imageData = @() + + # Prepare image data and write directory entries + for ($i = 0; $i -lt $sizes.Count; $i++) { + $bmp = $bitmaps[$i] + $ms = New-Object System.IO.MemoryStream + $bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png) + $pngBytes = $ms.ToArray() + $ms.Dispose() + $imageData += ,$pngBytes + + # Directory entry + $width = if ($sizes[$i] -ge 256) { 0 } else { $sizes[$i] } + $height = if ($sizes[$i] -ge 256) { 0 } else { $sizes[$i] } + + $bw.Write([byte]$width) # Width + $bw.Write([byte]$height) # Height + $bw.Write([byte]0) # Color palette + $bw.Write([byte]0) # Reserved + $bw.Write([UInt16]1) # Color planes + $bw.Write([UInt16]32) # Bits per pixel + $bw.Write([UInt32]$pngBytes.Length) # Image size + $bw.Write([UInt32]$currentOffset) # Offset + + $currentOffset += $pngBytes.Length + } + + # Write image data + foreach ($data in $imageData) { + $bw.Write($data) + } + + $bw.Close() + $fs.Close() + + # Cleanup bitmaps + foreach ($bmp in $bitmaps) { + $bmp.Dispose() + } + + return $true +} + +try { + Create-AtomizerIcon -OutputPath $IconPath + Write-Host " Created: $IconPath" -ForegroundColor Green +} +catch { + Write-Host " Warning: Could not create custom icon. Using default." -ForegroundColor Yellow + Write-Host " Error: $_" -ForegroundColor DarkGray + $IconPath = $null +} + +# Step 2: Create desktop shortcut +Write-Host "[2/3] Creating desktop shortcut..." -ForegroundColor Yellow + +$WshShell = New-Object -ComObject WScript.Shell +$Shortcut = $WshShell.CreateShortcut($ShortcutPath) +$Shortcut.TargetPath = $LauncherPath +$Shortcut.WorkingDirectory = $AtomizerRoot +$Shortcut.Description = "Launch Atomizer Optimization Dashboard" +$Shortcut.WindowStyle = 1 # Normal window + +if ($IconPath -and (Test-Path $IconPath)) { + $Shortcut.IconLocation = "$IconPath,0" +} + +$Shortcut.Save() + +Write-Host " Created: $ShortcutPath" -ForegroundColor Green + +# Step 3: Verify +Write-Host "[3/3] Verifying installation..." -ForegroundColor Yellow + +$success = $true +if (-not (Test-Path $ShortcutPath)) { + Write-Host " ERROR: Shortcut not created!" -ForegroundColor Red + $success = $false +} +if (-not (Test-Path $LauncherPath)) { + Write-Host " ERROR: Launcher script missing!" -ForegroundColor Red + $success = $false +} + +if ($success) { + Write-Host "" + Write-Host "============================================================" -ForegroundColor Green + Write-Host " SUCCESS! Atomizer shortcut created on your desktop." -ForegroundColor Green + Write-Host "============================================================" -ForegroundColor Green + Write-Host "" + Write-Host " Double-click 'Atomizer' on your desktop to launch!" -ForegroundColor White + Write-Host "" + Write-Host " What happens when you click:" -ForegroundColor Cyan + Write-Host " 1. Backend server starts (FastAPI on port 8000)" -ForegroundColor Gray + Write-Host " 2. Frontend server starts (Vite on port 5173)" -ForegroundColor Gray + Write-Host " 3. Browser opens to http://localhost:5173" -ForegroundColor Gray + Write-Host "" + Write-Host " To stop: Close the 'Atomizer Backend' and 'Atomizer Frontend'" -ForegroundColor Cyan + Write-Host " terminal windows." -ForegroundColor Cyan + Write-Host "" +} +else { + Write-Host "" + Write-Host "Installation had errors. Please check the messages above." -ForegroundColor Red + Write-Host "" +} + +# Keep window open +Read-Host "Press Enter to close" diff --git a/tools/launch_atomizer.bat b/tools/launch_atomizer.bat new file mode 100644 index 00000000..2cb87e72 --- /dev/null +++ b/tools/launch_atomizer.bat @@ -0,0 +1,65 @@ +@echo off +REM ============================================================ +REM Atomizer Dashboard Launcher +REM One-click: starts servers and opens dashboard in browser +REM ============================================================ + +title Atomizer +cd /d "%~dp0\.." + +REM Ports (match vite.config.ts) +set BACKEND_PORT=8001 +set FRONTEND_PORT=3003 +set URL=http://localhost:%FRONTEND_PORT% + +REM Check if already running +set BACKEND_RUNNING=0 +set FRONTEND_RUNNING=0 + +netstat -ano | findstr "LISTENING" | findstr ":%BACKEND_PORT% " > nul 2>&1 +if %errorlevel% equ 0 set BACKEND_RUNNING=1 + +netstat -ano | findstr "LISTENING" | findstr ":%FRONTEND_PORT% " > nul 2>&1 +if %errorlevel% equ 0 set FRONTEND_RUNNING=1 + +REM If both running, just open browser and exit immediately +if %BACKEND_RUNNING% equ 1 ( + if %FRONTEND_RUNNING% equ 1 ( + start "" %URL% + exit + ) +) + +REM Show brief splash while starting +echo. +echo Starting Atomizer Dashboard... +echo. + +REM Start backend (hidden window) +if %BACKEND_RUNNING% equ 0 ( + echo [1/2] Backend... + start /min "Atomizer Backend" cmd /c "cd /d %~dp0\..\atomizer-dashboard\backend && C:\Users\antoi\anaconda3\envs\atomizer\python.exe -m uvicorn api.main:app --host 0.0.0.0 --port %BACKEND_PORT%" +) + +REM Start frontend (hidden window) +if %FRONTEND_RUNNING% equ 0 ( + echo [2/2] Frontend... + start /min "Atomizer Frontend" cmd /c "cd /d %~dp0\..\atomizer-dashboard\frontend && npm run dev" +) + +REM Wait for frontend to be ready (poll until port responds) +echo. +echo Waiting for servers to start... +:WAIT_LOOP +timeout /t 1 /nobreak > nul +netstat -ano | findstr "LISTENING" | findstr ":%FRONTEND_PORT% " > nul 2>&1 +if %errorlevel% neq 0 goto WAIT_LOOP + +REM Small extra delay to ensure Vite is fully ready +timeout /t 2 /nobreak > nul + +REM Open browser +start "" %URL% + +REM Close this launcher window +exit