opaolilo/sqlite-data-viz-delight
0
1<!DOCTYPE html>2<html lang="pt-br" class="dark">3<head>4 <meta charset="UTF-8" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0">6 <title>Dashboard SQLite - Alarms</title>7 <script src="https://cdn.tailwindcss.com"></script>8 <script src="https://unpkg.com/feather-icons"></script>9 <script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.js"></script>10 <link rel="stylesheet" href="style.css">11<script>12 tailwind.config = {13 darkMode: 'class',14 theme: {15 extend: {16 colors: {17 primary: {18 500: '#6366f1',19 600: '#4f46e5',20 },21 secondary: {22 500: '#ec4899',23 600: '#db2777',24 }25 }26 }27 }28 }29 </script>30</head>31<body class="bg-gray-900 text-gray-100 min-h-screen">32 <custom-header></custom-header>33 <div class="container mx-auto px-4 py-8">34 <h1 class="text-3xl font-bold mb-8">Alarms Monitoring</h1>35 <!-- File Upload Card -->36 <div class="bg-gray-800 rounded-xl p-6 shadow-lg mb-8">37 <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">38 <div class="flex-1">39 <label class="block text-sm font-medium text-gray-300 mb-1">Upload SQLite Database</label>40 <div class="flex flex-wrap items-center gap-2">41 <label class="cursor-pointer">42 <span class="inline-flex items-center px-4 py-2 bg-primary-500 border border-transparent rounded-md font-semibold text-white hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 transition-colors">43 <i data-feather="upload" class="mr-2"></i>44 Select File45 <input type="file" id="fileInput" class="hidden" accept=".db" />46 </span>47 </label>48 <button id="btnReload" disabled class="px-4 py-2 bg-gray-700 border border-transparent rounded-md font-semibold text-gray-300 hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition-colors">49 <i data-feather="refresh-cw" class="mr-2"></i>50 Refresh51 </button>52 </div>53 <p id="filename" class="mt-2 text-sm text-gray-400">No file selected</p>54 </div>55 <div class="bg-gray-700 p-3 rounded-lg flex items-center gap-3">56 <i data-feather="info" class="text-secondary-500"></i>57 <p class="text-sm text-gray-300">Supported formats: SQLite database (.db)</p>58 </div>59 </div>60 </div>61 62 <!-- Time Range Selector -->63 <div class="bg-gray-800 rounded-xl p-6 shadow-lg mb-8">64 <h3 class="text-lg font-semibold text-gray-200 mb-4">Monitoring Time Range</h3>65 <div class="flex flex-wrap items-center gap-4">66 <div class="flex-1">67 <label class="block text-sm font-medium text-gray-300 mb-2">Time Range</label>68 <select id="timeRangeSelect" class="w-full bg-gray-700 border border-gray-600 rounded-md px-4 py-2 text-gray-200 focus:ring-primary-500 focus:border-primary-500">69 <option value="5">Last 5 minutes</option>70 <option value="15">Last 15 minutes</option>71 <option value="30" selected>Last 30 minutes</option>72 <option value="60">Last 1 hour</option>73 <option value="120">Last 2 hours</option>74 <option value="240">Last 4 hours</option>75 <option value="720">Last 12 hours</option>76 <option value="1440">Last 24 hours</option>77 <option value="2880">Last 48 hours</option>78 <option value="4320">Last 72 hours</option>79 <option value="7200">Last 5 days</option>80 <option value="14400">Last 10 days</option>81 <option value="21600">Last 15 days</option>82 <option value="43200">Last 30 days</option>83 <option value="86400">Last 60 days</option>84 <option value="129600">Last 90 days</option>85 </select>86 </div>87 <div>88 <button id="refreshAlarms" class="mt-7 px-4 py-2 bg-primary-500 border border-transparent rounded-md font-semibold text-white hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 transition-colors">89 <i data-feather="refresh-cw" class="mr-2"></i>90 Refresh91 </button>92 </div>93 </div>94 </div>95 <!-- Stats Overview -->96 <div id="statsContainer" class="mt-8 fade-in hovered-element">97 <h2 class="text-xl font-semibold text-gray-200 mb-4 hovered-element">Overview</h2>98 <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">99 <div class="stat-card bg-gray-800 rounded-xl p-6 shadow-lg flex items-center gap-4 hovered-element">100 <div class="p-3 rounded-lg bg-indigo-500 text-white">101 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-database w-5 h-5">102 <ellipse cx="12" cy="5" rx="9" ry="3"></ellipse>103 <path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path>104 <path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path>105 </svg>106 </div>107 <div class="flex-1">108 <p class="text-sm text-gray-400">Total Events</p>109 <p class="text-2xl font-bold text-white">0</p>110 </div>111 </div>112 <div class="stat-card bg-gray-800 rounded-xl p-6 shadow-lg flex items-center gap-4">113 <div class="p-3 rounded-lg bg-blue-500 text-white">114 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clock w-5 h-5">115 <circle cx="12" cy="12" r="10"></circle>116 <polyline points="12 6 12 12 16 14"></polyline>117 </svg>118 </div>119 <div class="flex-1">120 <p class="text-sm text-gray-400">PENDENTE</p>121 <p class="text-2xl font-bold text-white">0</p>122 </div>123 </div>124 <div class="stat-card bg-gray-800 rounded-xl p-6 shadow-lg flex items-center gap-4">125 <div class="p-3 rounded-lg bg-red-500 text-white">126 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-alert-circle w-5 h-5">127 <circle cx="12" cy="12" r="10"></circle>128 <line x1="12" y1="8" x2="12" y2="12"></line>129 <line x1="12" y1="16" x2="12.01" y2="16"></line>130 </svg>131 </div>132 <div class="flex-1">133 <p class="text-sm text-gray-400">ERRO</p>134 <p class="text-2xl font-bold text-white">0</p>135 </div>136 </div>137 <div class="stat-card bg-gray-800 rounded-xl p-6 shadow-lg flex items-center gap-4">138 <div class="p-3 rounded-lg bg-green-500 text-white">139 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-send w-5 h-5">140 <line x1="22" y1="2" x2="11" y2="13"></line>141 <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>142 </svg>143 </div>144 <div class="flex-1">145 <p class="text-sm text-gray-400">ENVIADO</p>146 <p class="text-2xl font-bold text-white">0</p>147 </div>148 </div>149 <div class="stat-card bg-gray-800 rounded-xl p-6 shadow-lg flex items-center gap-4">150 <div class="p-3 rounded-lg bg-yellow-500 text-white">151 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-loader w-5 h-5">152 <line x1="12" y1="2" x2="12" y2="6"></line>153 <line x1="12" y1="18" x2="12" y2="22"></line>154 <line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line>155 <line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line>156 <line x1="2" y1="12" x2="6" y2="12"></line>157 <line x1="18" y1="12" x2="22" y2="12"></line>158 <line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line>159 <line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line>160 </svg>161 </div>162 <div class="flex-1">163 <p class="text-sm text-gray-400">PROCESSANDO</p>164 <p class="text-2xl font-bold text-white">0</p>165 </div>166 </div>167 <div class="stat-card bg-gray-800 rounded-xl p-6 shadow-lg flex items-center gap-4">168 <div class="p-3 rounded-lg bg-orange-500 text-white">169 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-rotate-cw w-5 h-5">170 <polyline points="23 4 23 10 17 10"></polyline>171 <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path>172 </svg>173 </div>174 <div class="flex-1">175 <p class="text-sm text-gray-400">AGUARDANDO_RETRY</p>176 <p class="text-2xl font-bold text-white">0</p>177 </div>178 </div>179 <div class="stat-card bg-gray-800 rounded-xl p-6 shadow-lg flex items-center gap-4">180 <div class="p-3 rounded-lg bg-purple-500 text-white">181 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-alert-triangle w-5 h-5">182 <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>183 <line x1="12" y1="9" x2="12" y2="13"></line>184 <line x1="12" y1="17" x2="12.01" y2="17"></line>185 </svg>186 </div>187 <div class="flex-1">188 <p class="text-sm text-gray-400">ERRO_DETECTOR_INFO</p>189 <p class="text-2xl font-bold text-white">0</p>190 </div>191 </div>192 <div class="stat-card bg-gray-800 rounded-xl p-6 shadow-lg flex items-center gap-4">193 <div class="p-3 rounded-lg bg-cyan-500 text-white">194 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-cpu w-5 h-5">195 <rect x="4" y="4" width="16" height="16" rx="2" ry="2"></rect>196 <rect x="9" y="9" width="6" height="6"></rect>197 <line x1="9" y1="1" x2="9" y2="4"></line>198 <line x1="15" y1="1" x2="15" y2="4"></line>199 <line x1="9" y1="20" x2="9" y2="23"></line>200 <line x1="15" y1="20" x2="15" y2="23"></line>201 <line x1="20" y1="9" x2="23" y2="9"></line>202 <line x1="20" y1="14" x2="23" y2="14"></line>203 <line x1="1" y1="9" x2="4" y2="9"></line>204 <line x1="1" y1="14" x2="4" y2="14"></line>205 </svg>206 </div>207 <div class="flex-1">208 <p class="text-sm text-gray-400">PROCESSANDO_DETECTOR_INFO</p>209 <p class="text-2xl font-bold text-white">0</p>210 </div>211 </div>212 <div class="stat-card bg-gray-800 rounded-xl p-6 shadow-lg flex items-center gap-4">213 <div class="p-3 rounded-lg bg-pink-500 text-white">214 <i data-feather="x-octagon" class="w-5 h-5"></i>215 </div>216 <div class="flex-1">217 <p class="text-sm text-gray-400">VALE_ERROR</p>218 <p class="text-2xl font-bold text-white">0</p>219 </div>220 </div>221 </div>222 </div>223 224 <!-- Live Monitoring Dashboard -->225 <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">226<!-- Alarm Status Count -->227 <div class="bg-gray-800 rounded-xl p-6 shadow-lg">228 <h3 class="text-lg font-semibold text-gray-200 mb-4">Alarm Status Count</h3>229 <div class="h-80">230 <canvas id="alarmStatusChart"></canvas>231 </div>232 </div>233 234 <!-- Alarm Stats -->235 <div class="bg-gray-800 rounded-xl p-6 shadow-lg">236 <h3 class="text-lg font-semibold text-gray-200 mb-4">Alarm Statistics</h3>237 <div id="alarmStats" class="grid grid-cols-1 gap-4">238 <!-- Stats will be dynamically inserted here -->239 </div>240 </div>241 </div>242 243 <!-- Alarm Log Table -->244 <div class="bg-gray-800 rounded-xl p-6 shadow-lg">245 <h3 class="text-lg font-semibold text-gray-200 mb-4">Recent Alarms</h3>246 <div class="overflow-x-auto">247 <table class="min-w-full divide-y divide-gray-700">248 <thead>249 <tr>250 <th class="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">ID</th>251 <th class="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Status</th>252 <th class="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Timestamp</th>253 <th class="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Source</th>254 </tr>255 </thead>256 <tbody id="alarmTableBody" class="divide-y divide-gray-700">257 <!-- Alarm data will be inserted here -->258 </tbody>259 </table>260 </div>261 </div>262 </div>263 <script src="components/header.js"></script>264 <script src="components/alarms.js"></script>265 <script>266 feather.replace();267 268 // File upload and database loading functionality269 const fileInput = document.getElementById('fileInput');270 const btnReload = document.getElementById('btnReload');271 let dbFileUint8 = null;272 273 fileInput.addEventListener('change', e => {274 const file = e.target.files[0];275 if (!file) {276 document.getElementById('filename').textContent = 'No file selected';277 btnReload.disabled = true;278 dbFileUint8 = null;279 return;280 }281 282 const reader = new FileReader();283 reader.onload = () => {284 dbFileUint8 = new Uint8Array(reader.result);285 document.getElementById('filename').textContent = `Selected: ${file.name}`;286 btnReload.disabled = false;287 288 // Initialize alarm monitor with the new database289 if (window.alarmMonitor) {290 window.alarmMonitor.loadAlarmData();291 }292 };293 reader.onerror = () => {294 document.getElementById('filename').textContent = 'Error reading file';295 btnReload.disabled = true;296 dbFileUint8 = null;297 };298 reader.readAsArrayBuffer(file);299 });300 301 btnReload.addEventListener('click', () => {302 if (dbFileUint8 && window.alarmMonitor) {303 window.alarmMonitor.loadAlarmData();304 }305 });306 </script>307</body>308</html>