chore: Add Atomizer launcher and utility scripts
- atomizer.ico: Application icon - launch_atomizer.bat: One-click launcher for dashboard - create_desktop_shortcut.ps1: Desktop shortcut creator - restart_backend.bat, start_backend_8002.bat: Dev utilities
This commit is contained in:
14
restart_backend.bat
Normal file
14
restart_backend.bat
Normal file
@@ -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
|
||||
6
start_backend_8002.bat
Normal file
6
start_backend_8002.bat
Normal file
@@ -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
|
||||
BIN
tools/atomizer.ico
Normal file
BIN
tools/atomizer.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
209
tools/create_desktop_shortcut.ps1
Normal file
209
tools/create_desktop_shortcut.ps1
Normal file
@@ -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"
|
||||
65
tools/launch_atomizer.bat
Normal file
65
tools/launch_atomizer.bat
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user