Spaces:
Running
Running
Fill the thing with random data
Browse files- README.md +8 -4
- index.html +284 -18
README.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
|
| 4 |
-
colorFrom: red
|
| 5 |
colorTo: pink
|
|
|
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: GridPulse PulseMaster ⚡
|
| 3 |
+
colorFrom: yellow
|
|
|
|
| 4 |
colorTo: pink
|
| 5 |
+
emoji: 🐳
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite-v3
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Welcome to your new DeepSite project!
|
| 13 |
+
This project was created with [DeepSite](https://deepsite.hf.co).
|
| 14 |
+
|
index.html
CHANGED
|
@@ -1,19 +1,285 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en" class="dark">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8"/>
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
| 6 |
+
<title>GridPulse Edge – Energy-Efficient Grid Monitor</title>
|
| 7 |
+
|
| 8 |
+
<!-- Tailwind + Feather + Chart.js + date-fns -->
|
| 9 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 10 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 11 |
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
| 12 |
+
<script src="https://cdn.jsdelivr.net/npm/date-fns@2.29.3/index.min.js"></script>
|
| 13 |
+
|
| 14 |
+
<style>
|
| 15 |
+
:root {
|
| 16 |
+
--primary: #14b8a6;
|
| 17 |
+
--secondary: #f59e0b;
|
| 18 |
+
--dark: #111827;
|
| 19 |
+
--light: #fdfdfd;
|
| 20 |
+
}
|
| 21 |
+
.theme-light { --bg: var(--light); --text: var(--dark); }
|
| 22 |
+
.theme-dark { --bg: var(--dark); --text: var(--light); }
|
| 23 |
+
body { background: var(--bg); color: var(--text); transition: background .3s, color .3s; }
|
| 24 |
+
.toast-enter { opacity:0; transform:translateY(-20px); }
|
| 25 |
+
.toast-enter-active { opacity:1; transform:translateY(0); transition:all .4s; }
|
| 26 |
+
.blink { animation:blink 1s infinite; }
|
| 27 |
+
@keyframes blink{ 50%{ filter:brightness(1.4) drop-shadow(0 0 8px var(--secondary));} }
|
| 28 |
+
</style>
|
| 29 |
+
</head>
|
| 30 |
+
<body class="theme-dark font-sans">
|
| 31 |
+
<!-- TOAST -->
|
| 32 |
+
<div id="toast" class="fixed top-4 right-4 z-50 max-w-sm"></div>
|
| 33 |
+
|
| 34 |
+
<!-- HEADER -->
|
| 35 |
+
<header class="flex flex-col sm:flex-row justify-between items-center p-4 md:p-6 bg-slate-900">
|
| 36 |
+
<h1 class="text-xl md:text-3xl font-extrabold flex items-center gap-3">
|
| 37 |
+
<i data-feather="bar-chart-2" class="text-emerald-500"></i>
|
| 38 |
+
GridPulse Edge
|
| 39 |
+
</h1>
|
| 40 |
+
<div class="flex items-center gap-3 mt-2 sm:mt-0">
|
| 41 |
+
<button id="themeBtn" class="p-2 rounded-full bg-slate-700 hover:bg-slate-600">
|
| 42 |
+
<i data-feather="sun"></i>
|
| 43 |
+
</button>
|
| 44 |
+
<select id="rangeSelect" class="bg-slate-700 text-sm rounded p-2">
|
| 45 |
+
<option value="15m">Last 15 min</option>
|
| 46 |
+
<option value="1h">1 hour</option>
|
| 47 |
+
<option value="24h">24 hours</option>
|
| 48 |
+
</select>
|
| 49 |
+
</div>
|
| 50 |
+
</header>
|
| 51 |
+
|
| 52 |
+
<!-- KPI ROW -->
|
| 53 |
+
<section class="grid grid-cols-2 lg:grid-cols-5 gap-4 p-4 md:p-6">
|
| 54 |
+
<div id="kpiHealth"
|
| 55 |
+
class="col-span-2 lg:col-span-1 flex flex-col justify-center items-center bg-slate-800 rounded-2xl p-4 min-h-[140px]">
|
| 56 |
+
<h3 class="text-sm opacity-60 mb-1">Health</h3>
|
| 57 |
+
<div id="gauge" class="w-16 h-16 rounded-full border-8 border-emerald-500" style="--tw-border-opacity:.7;"></div>
|
| 58 |
+
<span id="healthText" class="mt-2 font-bold text-xl">0.94</span>
|
| 59 |
+
</div>
|
| 60 |
+
<div id="kpiEta"
|
| 61 |
+
class="flex justify-center items-center text-center bg-slate-800 rounded-2xl p-4">
|
| 62 |
+
<div>
|
| 63 |
+
<h3 class="text-sm opacity-60">Next Fault ETA</h3>
|
| 64 |
+
<span id="etaVal" class="font-bold text-2xl">27 s</span>
|
| 65 |
+
</div>
|
| 66 |
+
</div>
|
| 67 |
+
<div id="kpiFault"
|
| 68 |
+
class="flex justify-center items-center text-center bg-slate-800 rounded-2xl p-4">
|
| 69 |
+
<div>
|
| 70 |
+
<h3 class="text-sm opacity-60">Top Fault</h3>
|
| 71 |
+
<span id="faultVal" class="font-bold text-lg">Sag 0.82</span>
|
| 72 |
+
</div>
|
| 73 |
+
</div>
|
| 74 |
+
<div id="kpiLatency"
|
| 75 |
+
class="flex justify-center items-center text-center bg-slate-800 rounded-2xl p-4">
|
| 76 |
+
<h3 class="text-sm opacity-60">Latency / Energy</h3>
|
| 77 |
+
<div class="font-bold text-lg">
|
| 78 |
+
<span id="latencyVal">0.12 ms</span><br/>
|
| 79 |
+
<span id="energyVal">0.004 Wh</span>
|
| 80 |
+
</div>
|
| 81 |
+
</div>
|
| 82 |
+
<div id="kpiCO2"
|
| 83 |
+
class="flex justify-center items-center text-center bg-slate-800 rounded-2xl p-4">
|
| 84 |
+
<div>
|
| 85 |
+
<h3 class="text-sm opacity-60">CO₂ avoided today</h3>
|
| 86 |
+
<span id="co2Val" class="font-bold text-xl">2.1 kg</span>
|
| 87 |
+
</div>
|
| 88 |
+
</div>
|
| 89 |
+
</section>
|
| 90 |
+
|
| 91 |
+
<!-- MAIN GRID -->
|
| 92 |
+
<main class="grid grid-cols-1 xl:grid-cols-2 gap-6 px-4 md:px-6 pb-6">
|
| 93 |
+
<!-- CHART 1: HEALTH -->
|
| 94 |
+
<section class="bg-slate-800 rounded-2xl p-4">
|
| 95 |
+
<h2 class="mb-2 font-bold">Health score – 15 min</h2>
|
| 96 |
+
<canvas id="healthChart" height="120"></canvas>
|
| 97 |
+
</section>
|
| 98 |
+
|
| 99 |
+
<!-- CHART 2: PROBABILITIES -->
|
| 100 |
+
<section class="bg-slate-800 rounded-2xl p-4">
|
| 101 |
+
<h2 class="mb-2 font-bold">Fault probabilities</h2>
|
| 102 |
+
<canvas id="probChart" height="120"></canvas>
|
| 103 |
+
</section>
|
| 104 |
+
|
| 105 |
+
<!-- CHART 3: ENERGY LEDGER -->
|
| 106 |
+
<section class="bg-slate-800 rounded-2xl p-4">
|
| 107 |
+
<h2 class="mb-2 font-bold">Energy ledger – today</h2>
|
| 108 |
+
<canvas id="energyChart" height="120"></canvas>
|
| 109 |
+
</section>
|
| 110 |
+
|
| 111 |
+
<!-- CHART 4: LATENCY / COST -->
|
| 112 |
+
<section class="bg-slate-800 rounded-2xl p-4">
|
| 113 |
+
<h2 class="mb-2 font-bold">Latency & cost</h2>
|
| 114 |
+
<canvas id="latencyChart" height="120"></canvas>
|
| 115 |
+
</section>
|
| 116 |
+
</main>
|
| 117 |
+
|
| 118 |
+
<!-- TABLES -->
|
| 119 |
+
<section class="px-4 md:px-6 pb-6 grid grid-cols-1 xl:grid-cols-2 gap-6">
|
| 120 |
+
<!-- ALERTS -->
|
| 121 |
+
<section class="bg-slate-800 rounded-2xl p-4">
|
| 122 |
+
<h2 class="mb-3 font-bold">Recent alerts (last 24 h)</h2>
|
| 123 |
+
<div class="overflow-x-auto">
|
| 124 |
+
<table id="alertsTable" class="w-full text-sm">
|
| 125 |
+
<thead>
|
| 126 |
+
<tr class="border-b border-slate-600">
|
| 127 |
+
<th class="p-2 text-left">Time</th><th>Feeder</th><th>Fault</th><th>ETA</th><th>Action</th>
|
| 128 |
+
</tr>
|
| 129 |
+
</thead>
|
| 130 |
+
<tbody></tbody>
|
| 131 |
+
</table>
|
| 132 |
+
</div>
|
| 133 |
+
</section>
|
| 134 |
+
|
| 135 |
+
<!-- MODEL COMPARISON -->
|
| 136 |
+
<section class="bg-slate-800 rounded-2xl p-4">
|
| 137 |
+
<h2 class="mb-3 font-bold">Model comparison</h2>
|
| 138 |
+
<div class="overflow-x-auto">
|
| 139 |
+
<table class="w-full text-sm">
|
| 140 |
+
<thead>
|
| 141 |
+
<tr class="border-b border-slate-600">
|
| 142 |
+
<th class="p-2 text-left">Model</th><th>Latency(ms)</th><th>Energy(Wh)</th><th>Cost($)</th>
|
| 143 |
+
</tr>
|
| 144 |
+
</thead>
|
| 145 |
+
<tbody>
|
| 146 |
+
<tr class="bg-emerald-700/30"><td class="p-2 font-bold">LR INT8 *</td><td>0.15</td><td>0.005</td><td>0.000064</td></tr>
|
| 147 |
+
<tr><td class="p-2">RF</td><td>0.8</td><td>0.027</td><td>0.00035</td></tr>
|
| 148 |
+
<tr><td class="p-2">XGBoost INT8</td><td>0.22</td><td>0.0081</td><td>0.00011</td></tr>
|
| 149 |
+
<tr><td class="p-2">LSTM FP16</td><td>2.1</td><td>0.065</td><td>0.00084</td></tr>
|
| 150 |
+
<tr><td class="p-2">GNN INT8</td><td>1.5</td><td>0.042</td><td>0.00055</td></tr>
|
| 151 |
+
</tbody>
|
| 152 |
+
</table>
|
| 153 |
+
</div>
|
| 154 |
+
</section>
|
| 155 |
+
</section>
|
| 156 |
+
|
| 157 |
+
<footer class="text-center text-xs opacity-60 p-4">
|
| 158 |
+
Energy, latency, and cost figures adapted from literature; refined with deployment telemetry.
|
| 159 |
+
</footer>
|
| 160 |
+
|
| 161 |
+
<script>
|
| 162 |
+
/* UTILS */
|
| 163 |
+
const dark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
| 164 |
+
const body = document.body;
|
| 165 |
+
function setTheme(darkMode){
|
| 166 |
+
body.className = darkMode ? 'theme-dark' : 'theme-light';
|
| 167 |
+
document.querySelector('#themeBtn').innerHTML = feather.icons[darkMode?'sun':'moon'].toSvg({class:'inline w-5'});
|
| 168 |
+
}
|
| 169 |
+
setTheme(dark);
|
| 170 |
+
document.getElementById('themeBtn').onclick = ()=>setTheme(!body.classList.contains('theme-dark'));
|
| 171 |
+
|
| 172 |
+
/* DEMO DATA GENERATION */
|
| 173 |
+
let lastHealth=0.85 + Math.random()*0.1, lastEta=30 + Math.random()*120;
|
| 174 |
+
const dataHealth = Array(15*60).fill().map((_,i)=>({x:Date.now()-i*1000, y:0.7 + Math.random()*0.3}));
|
| 175 |
+
const dataSag = [], dataSwell=[], dataOsc=[], dataLatency=[], dataCost=[], dataEnergy=[];
|
| 176 |
+
for(let i=0;i<60*24;i++){
|
| 177 |
+
const spike = Math.random() > 0.95 ? 0.9 + Math.random()*0.1 : Math.random();
|
| 178 |
+
dataSag.unshift({x:Date.now()-i*60000, y:spike});
|
| 179 |
+
dataSwell.unshift({x:Date.now()-i*60000, y:0.3 + Math.random()*0.5});
|
| 180 |
+
dataOsc.unshift({x:Date.now()-i*60000, y:0.4 + Math.random()*0.4});
|
| 181 |
+
dataLatency.unshift({x:Date.now()-i*60000, y:0.05 + Math.random()*0.1});
|
| 182 |
+
dataCost.unshift({x:Date.now()-i*60000, y:(0.05 + Math.random()*0.15)/1000});
|
| 183 |
+
dataEnergy.unshift({x:Date.now()-i*60000, y:0.005 + Math.random()*0.005});
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
const feeders = ["F01", "F02", "F03", "F04", "F05", "F06"];
|
| 187 |
+
const faultTypes = ["Sag", "Swell", "Oscillation", "Harmonic", "Outage", "Spike"];
|
| 188 |
+
const actions = ["Notify crew", "Adjust set-point", "Reroute power", "Check sensors", "Dispatch team", "Monitor"];
|
| 189 |
+
const alerts = Array(5).fill().map(() => {
|
| 190 |
+
const timeOffset = Math.random() * 24 * 60 * 60 * 1000;
|
| 191 |
+
return {
|
| 192 |
+
time: new Date(Date.now() - timeOffset),
|
| 193 |
+
feeder: feeders[Math.floor(Math.random() * feeders.length)],
|
| 194 |
+
fault: `${faultTypes[Math.floor(Math.random() * faultTypes.length)]} ${(0.7 + Math.random()*0.3).toFixed(2)}`,
|
| 195 |
+
eta: timeOffset < 60000 ? `${Math.floor(timeOffset/1000)} s` : `${Math.floor(timeOffset/60000)} m`,
|
| 196 |
+
action: actions[Math.floor(Math.random() * actions.length)]
|
| 197 |
+
};
|
| 198 |
+
}).sort((a,b) => b.time - a.time);
|
| 199 |
+
/* CHARTS */
|
| 200 |
+
function lineConfig(data,label,color,fill=false){
|
| 201 |
+
return {
|
| 202 |
+
type:"line", data:{datasets:[{label,data,backgroundColor:fill?color+'33':'transparent',borderColor:color,fill}]},
|
| 203 |
+
options:{animation:false, plugins:{legend:{display:false}}, scales:{x:{type:'time',ticks:{maxTicksLimit:5}}}}
|
| 204 |
+
};
|
| 205 |
+
}
|
| 206 |
+
window.onload = ()=>{
|
| 207 |
+
new Chart(document.getElementById('healthChart'), lineConfig(dataHealth.slice(-900),'Health','#10b981',true));
|
| 208 |
+
new Chart(document.getElementById('probChart'), {
|
| 209 |
+
type:'line',
|
| 210 |
+
data:{datasets:[
|
| 211 |
+
{label:'Sag',data:dataSag,backgroundColor:'transparent',borderColor:'#ef4444',pointRadius:0},
|
| 212 |
+
{label:'Swell',data:dataSwell,backgroundColor:'transparent',borderColor:'#f59e0b',pointRadius:0},
|
| 213 |
+
{label:'Oscillation',data:dataOsc,backgroundColor:'transparent',borderColor:'#3b82f6',pointRadius:0}
|
| 214 |
+
]},
|
| 215 |
+
options:{animation:false, plugins:{legend:{display:false}}, scales:{x:{type:'time',ticks:{maxTicksLimit:5}}}}
|
| 216 |
+
});
|
| 217 |
+
new Chart(document.getElementById('energyChart'), {
|
| 218 |
+
type:'bar',
|
| 219 |
+
data:{datasets:[
|
| 220 |
+
{label:'Model energy',data:dataEnergy.slice(-24),backgroundColor:'#6366f1'},
|
| 221 |
+
{label:'Energy saved',data:Array(24).fill(0.025),backgroundColor:'#34d399'}
|
| 222 |
+
]},
|
| 223 |
+
options:{animation:false, plugins:{legend:{display:false}}, scales:{x:{ticks:{maxTicksLimit:12}}}}
|
| 224 |
+
});
|
| 225 |
+
new Chart(document.getElementById('latencyChart'), {
|
| 226 |
+
type:'line',
|
| 227 |
+
data:{datasets:[
|
| 228 |
+
{label:'Latency ms',data:dataLatency.slice(-24),backgroundColor:'transparent',borderColor:'#8b5cf6',yAxisID:'y'},
|
| 229 |
+
{label:'Cost $',data:dataCost.slice(-24),backgroundColor:'transparent',borderColor:'#ec4899',borderDash:[5,5],yAxisID:'y1'}
|
| 230 |
+
]},
|
| 231 |
+
options:{animation:false, interaction:{mode:'nearest', axis:'x', intersect:false}, scales:{y:{type:'linear',position:'left'}, y1:{type:'linear',position:'right',grid:{drawOnChartArea:false}}}}
|
| 232 |
+
});
|
| 233 |
+
};
|
| 234 |
+
|
| 235 |
+
/* REFRESH UI */
|
| 236 |
+
function refresh(){
|
| 237 |
+
lastHealth = Math.max(0.6, Math.min(0.95, lastHealth - 0.001 + (Math.random()*0.004 - 0.002)));
|
| 238 |
+
document.getElementById('healthText').textContent = lastHealth.toFixed(2);
|
| 239 |
+
const gauge = document.getElementById('gauge');
|
| 240 |
+
let c = lastHealth>=0.8? '#22c55e':lastHealth>=0.5? '#f59e0b': '#ef4444';
|
| 241 |
+
gauge.style.borderColor = c;
|
| 242 |
+
lastEta = Math.max(5, Math.min(180, lastEta - 1 + Math.random()*4 - 2));
|
| 243 |
+
const eta = lastEta<60?Math.round(lastEta)+' s':`${Math.floor(lastEta/60)} m`;
|
| 244 |
+
document.getElementById('etaVal').textContent=eta;
|
| 245 |
+
const kpiEta = document.getElementById('kpiEta');
|
| 246 |
+
kpiEta.classList.toggle('blink', lastEta<60);
|
| 247 |
+
document.getElementById('latencyVal').textContent = (0.08 + Math.random()*0.08).toFixed(2) + ' ms';
|
| 248 |
+
document.getElementById('energyVal').textContent = (0.003 + Math.random()*0.004).toFixed(3) + ' Wh';
|
| 249 |
+
document.getElementById('co2Val').textContent = (1.8 + Math.random()*0.6).toFixed(2) + ' kg';
|
| 250 |
+
// alerts
|
| 251 |
+
const tbody = document.querySelector('#alertsTable tbody');
|
| 252 |
+
tbody.innerHTML='';
|
| 253 |
+
alerts.forEach(a=>{
|
| 254 |
+
const tr=document.createElement('tr');
|
| 255 |
+
tr.innerHTML = `
|
| 256 |
+
<td class="p-2">${format(a.time,'HH:mm:ss')}</td>
|
| 257 |
+
<td>${a.feeder}</td>
|
| 258 |
+
<td>${a.fault}</td>
|
| 259 |
+
<td>${a.eta}</td>
|
| 260 |
+
<td class="italic">${a.action}</td>`;
|
| 261 |
+
tbody.append(tr);
|
| 262 |
+
});
|
| 263 |
+
if(Math.random()>0.99) {
|
| 264 |
+
const fault = faultTypes[Math.floor(Math.random() * faultTypes.length)];
|
| 265 |
+
showToast(`${fault} detected on ${feeders[Math.floor(Math.random() * feeders.length)]}`, {type:'warning'});
|
| 266 |
+
}
|
| 267 |
+
}
|
| 268 |
+
const format = dateFns.format;
|
| 269 |
+
setInterval(refresh,1000);
|
| 270 |
+
|
| 271 |
+
/* TOAST MANAGER */
|
| 272 |
+
function showToast(msg, opts={}){
|
| 273 |
+
const box=document.createElement('div');
|
| 274 |
+
box.className='toast-enter bg-red-600 text-white p-3 rounded shadow';
|
| 275 |
+
box.textContent = msg;
|
| 276 |
+
document.getElementById('toast').appendChild(box);
|
| 277 |
+
box.classList.add('toast-enter-active');
|
| 278 |
+
setTimeout(()=>box.remove(),4000);
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
refresh();
|
| 282 |
+
feather.replace();
|
| 283 |
+
</script>
|
| 284 |
+
</body>
|
| 285 |
</html>
|