Augustin 4dde6d6853 Feature: add web dashboard and NPU-powered AI classification
Backend:
- Add web server module with Axum (localhost:2759 by default)
- Create REST API endpoints (/api/stats, /api/dashboard, /api/health)
- Add AI module with NPU support via ONNX Runtime + DirectML
- Support Intel AI Boost NPU on Intel Core Ultra processors
- Add 'serve' command to CLI for dashboard server

Frontend:
- Modern dashboard with Tailwind CSS and Chart.js
- Real-time activity statistics and visualizations
- Category distribution pie chart
- Daily activity trend line chart
- Recent activities table with filtering

AI/ML:
- NPU device detection and DirectML configuration
- ONNX Runtime integration for model inference
- Fallback to rule-based classification when no model loaded
- Support for future AI model integration

Dependencies:
- axum 0.7 (web framework)
- tower + tower-http (middleware and static files)
- ort 2.0.0-rc.10 (ONNX Runtime with DirectML)
- ndarray 0.16 + tokenizers 0.20 (ML utilities)

All tests passing (27/27)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 14:23:56 +02:00

144 lines
7.1 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Activity Tracker Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<style>
@keyframes pulse-glow {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.pulse-glow {
animation: pulse-glow 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
</style>
</head>
<body class="bg-gray-900 text-gray-100">
<!-- Header -->
<nav class="bg-gray-800 border-b border-gray-700">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<div class="flex items-center">
<h1 class="text-2xl font-bold text-blue-400">Activity Tracker</h1>
<span class="ml-4 px-3 py-1 text-xs font-semibold text-green-400 bg-green-900 rounded-full pulse-glow">
NPU Enabled
</span>
</div>
<div class="flex items-center space-x-4">
<span class="text-sm text-gray-400" id="last-update">Last update: --</span>
<button onclick="loadDashboard()" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded-lg text-sm font-medium transition">
Refresh
</button>
</div>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Stats Cards -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-400">Total Captures</p>
<p class="text-3xl font-bold text-white mt-2" id="total-captures">--</p>
</div>
<div class="bg-blue-900 p-3 rounded-full">
<svg class="w-8 h-8 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
</div>
</div>
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-400">Storage Used</p>
<p class="text-3xl font-bold text-white mt-2" id="storage-size">--</p>
</div>
<div class="bg-purple-900 p-3 rounded-full">
<svg class="w-8 h-8 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4"></path>
</svg>
</div>
</div>
</div>
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-400">First Capture</p>
<p class="text-lg font-bold text-white mt-2" id="oldest-capture">--</p>
</div>
<div class="bg-green-900 p-3 rounded-full">
<svg class="w-8 h-8 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
</div>
</div>
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-400">Last Capture</p>
<p class="text-lg font-bold text-white mt-2" id="newest-capture">--</p>
</div>
<div class="bg-yellow-900 p-3 rounded-full">
<svg class="w-8 h-8 text-yellow-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>
</div>
</div>
</div>
</div>
<!-- Charts Row -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<!-- Category Distribution -->
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
<h2 class="text-xl font-bold mb-4">Activity Categories</h2>
<canvas id="category-chart"></canvas>
</div>
<!-- Time Trend -->
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
<h2 class="text-xl font-bold mb-4">Daily Activity (Last 7 Days)</h2>
<canvas id="time-chart"></canvas>
</div>
</div>
<!-- Recent Activities -->
<div class="bg-gray-800 rounded-lg p-6 border border-gray-700">
<h2 class="text-xl font-bold mb-4">Recent Activities</h2>
<div id="recent-activities" class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-700">
<thead>
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Date</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Total Time</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Development</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Meeting</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Research</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Other</th>
</tr>
</thead>
<tbody id="activities-tbody" class="divide-y divide-gray-700">
<tr>
<td colspan="6" class="px-6 py-4 text-center text-gray-400">Loading...</td>
</tr>
</tbody>
</table>
</div>
</div>
</main>
<script src="app.js"></script>
</body>
</html>