893376dc14
Issues fixed:
1. Web Worker localStorage error - Remove localStorage calls from worker
- Worker cannot access localStorage (browser context only)
- Worker now sends data to main thread via postMessage
- Main thread handles all localStorage operations
2. Add favicon to avoid 404 error
- Use inline SVG favicon (llama emoji)
- No external file request
3. Optimize Tailwind CSS for production
- Add tailwind.config.js for content scanning
- Add app/web/static/css/input.css (Tailwind directives)
- Update package.json with tailwind build commands
- Update Dockerfile multi-stage build:
* Stage 1: Node.js - compile Tailwind CSS
* Stage 2: Python - install dependencies
* Stage 3: Runtime - use compiled CSS
- Update index.html to use compiled output.css
- Add fallback to CDN for development
4. Add DEVELOPMENT.md documentation
- Setup instructions for local development
- Tailwind CSS workflow (watch mode)
- Docker build explanation
- Development tips and best practices
Benefits:
- No more localStorage errors in console
- No more 404 favicon requests
- Optimized CSS for production (~30KB minified)
- Clear development workflow
- Multi-stage Docker build is efficient (~300MB image)
110 lines
5.5 KiB
HTML
110 lines
5.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="it">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>LLM Monitor - Dashboard Ollama</title>
|
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🦙</text></svg>">
|
|
<!-- Tailwind CSS (compiled for production) -->
|
|
<link rel="stylesheet" href="/static/css/output.css">
|
|
<!-- Fallback CDN for development (if output.css not available) -->
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<style>
|
|
@keyframes spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
.animate-spin {
|
|
animation: spin 1s linear infinite;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="bg-gray-900 text-white">
|
|
<div class="min-h-screen flex flex-col">
|
|
<!-- Header -->
|
|
<header class="bg-gray-800 border-b border-gray-700 sticky top-0 z-50">
|
|
<div class="max-w-7xl mx-auto px-4 py-6">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<div class="w-10 h-10 bg-gradient-to-br from-purple-500 to-pink-500 rounded-lg flex items-center justify-center font-bold text-lg">
|
|
🦙
|
|
</div>
|
|
<h1 class="text-2xl font-bold">LLM Monitor</h1>
|
|
</div>
|
|
<div class="flex items-center gap-4">
|
|
<div id="health-status" class="flex items-center gap-2">
|
|
<div id="status-indicator" class="w-3 h-3 bg-gray-500 rounded-full"></div>
|
|
<span id="status-text" class="text-sm text-gray-400">Controllo...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<main class="flex-1">
|
|
<div class="max-w-7xl mx-auto px-4 py-8">
|
|
<!-- Stats Cards -->
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
|
|
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
|
|
<div class="text-gray-400 text-sm font-medium">Modelli Caricati</div>
|
|
<div id="models-count" class="text-4xl font-bold mt-2">-</div>
|
|
</div>
|
|
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
|
|
<div class="text-gray-400 text-sm font-medium">Spazio Totale</div>
|
|
<div id="total-size" class="text-4xl font-bold mt-2">-</div>
|
|
</div>
|
|
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
|
|
<div class="text-gray-400 text-sm font-medium">Status Ollama</div>
|
|
<div id="ollama-status" class="text-4xl font-bold mt-2">-</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Models Section -->
|
|
<div class="bg-gray-800 rounded-lg border border-gray-700 p-6">
|
|
<div class="flex items-center justify-between mb-6">
|
|
<h2 class="text-xl font-bold">Modelli Disponibili</h2>
|
|
<button id="refresh-btn" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded-lg text-sm font-medium transition">
|
|
🔄 Aggiorna
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Models List -->
|
|
<div id="models-container" class="space-y-4">
|
|
<div class="text-center py-8">
|
|
<div class="animate-spin inline-block w-8 h-8 border-4 border-gray-600 border-t-purple-500 rounded-full"></div>
|
|
<p class="text-gray-400 mt-4">Caricamento modelli...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- API Documentation Section -->
|
|
<div class="mt-8 bg-blue-900 bg-opacity-20 border border-blue-700 rounded-lg p-6">
|
|
<h3 class="text-lg font-bold mb-4">📚 Documentazione API</h3>
|
|
<p class="text-gray-300 mb-4">La API è documentata e testabile direttamente da:</p>
|
|
<div class="flex gap-3 flex-wrap">
|
|
<a href="/docs" target="_blank" class="inline-block bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded-lg text-sm font-medium transition">
|
|
Swagger UI
|
|
</a>
|
|
<a href="/redoc" target="_blank" class="inline-block bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded-lg text-sm font-medium transition">
|
|
ReDoc
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Footer -->
|
|
<footer class="bg-gray-800 border-t border-gray-700 mt-12">
|
|
<div class="max-w-7xl mx-auto px-4 py-6 text-center text-gray-400 text-sm">
|
|
<p>LLM Monitor v1.0.0 • Fatto con ❤️ da <a href="https://lucasacchi.net" target="_blank" class="text-purple-400 hover:text-purple-300">LucaSacchi.Net</a></p>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
|
|
<!-- LLM Monitor Application -->
|
|
<!-- Web Worker for background data sync -->
|
|
<!-- localStorage for client-side persistence -->
|
|
<script src="/static/js/app.js"></script>
|
|
</body>
|
|
</html>
|