BIG update: Update to 0.5.1. Added:
-Project management -Modem Managerment -Modem/unit pairing and more
This commit is contained in:
108
templates/modems.html
Normal file
108
templates/modems.html
Normal file
@@ -0,0 +1,108 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Field Modems - Terra-View{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="mb-8">
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white flex items-center">
|
||||
<svg class="w-8 h-8 mr-3 text-seismo-orange" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"></path>
|
||||
</svg>
|
||||
Field Modems
|
||||
</h1>
|
||||
<p class="text-gray-600 dark:text-gray-400 mt-1">Manage network connectivity devices for field equipment</p>
|
||||
</div>
|
||||
|
||||
<!-- Summary Stats -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8"
|
||||
hx-get="/api/modem-dashboard/stats"
|
||||
hx-trigger="load, every 30s"
|
||||
hx-swap="innerHTML">
|
||||
<!-- Stats will be loaded here -->
|
||||
<div class="animate-pulse bg-gray-200 dark:bg-gray-700 h-24 rounded-xl"></div>
|
||||
<div class="animate-pulse bg-gray-200 dark:bg-gray-700 h-24 rounded-xl"></div>
|
||||
<div class="animate-pulse bg-gray-200 dark:bg-gray-700 h-24 rounded-xl"></div>
|
||||
<div class="animate-pulse bg-gray-200 dark:bg-gray-700 h-24 rounded-xl"></div>
|
||||
</div>
|
||||
|
||||
<!-- Modem List -->
|
||||
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg p-6">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">All Modems</h2>
|
||||
<div class="flex items-center gap-4">
|
||||
<!-- Search -->
|
||||
<div class="relative">
|
||||
<input type="text"
|
||||
id="modem-search"
|
||||
placeholder="Search modems..."
|
||||
class="pl-9 pr-4 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-seismo-orange focus:border-transparent"
|
||||
hx-get="/api/modem-dashboard/units"
|
||||
hx-trigger="keyup changed delay:300ms"
|
||||
hx-target="#modem-list"
|
||||
hx-include="[name='search']"
|
||||
name="search">
|
||||
<svg class="w-4 h-4 absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<a href="/roster?device_type=modem" class="text-sm text-seismo-orange hover:underline">
|
||||
Add modem in roster
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="modem-list"
|
||||
hx-get="/api/modem-dashboard/units"
|
||||
hx-trigger="load, every 30s"
|
||||
hx-swap="innerHTML">
|
||||
<div class="animate-pulse space-y-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<div class="bg-gray-200 dark:bg-gray-700 h-40 rounded-lg"></div>
|
||||
<div class="bg-gray-200 dark:bg-gray-700 h-40 rounded-lg"></div>
|
||||
<div class="bg-gray-200 dark:bg-gray-700 h-40 rounded-lg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Ping a modem and show result
|
||||
async function pingModem(modemId) {
|
||||
const btn = document.getElementById(`ping-btn-${modemId}`);
|
||||
const resultDiv = document.getElementById(`ping-result-${modemId}`);
|
||||
|
||||
// Show loading state
|
||||
const originalText = btn.textContent;
|
||||
btn.textContent = 'Pinging...';
|
||||
btn.disabled = true;
|
||||
resultDiv.classList.remove('hidden');
|
||||
resultDiv.className = 'mt-2 text-xs text-gray-500';
|
||||
resultDiv.textContent = 'Testing connection...';
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/modem-dashboard/${modemId}/ping`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.status === 'success') {
|
||||
resultDiv.className = 'mt-2 text-xs text-green-600 dark:text-green-400';
|
||||
resultDiv.innerHTML = `<span class="inline-block w-2 h-2 bg-green-500 rounded-full mr-1"></span>Online (${data.response_time_ms}ms)`;
|
||||
} else {
|
||||
resultDiv.className = 'mt-2 text-xs text-red-600 dark:text-red-400';
|
||||
resultDiv.innerHTML = `<span class="inline-block w-2 h-2 bg-red-500 rounded-full mr-1"></span>${data.detail || 'Offline'}`;
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.className = 'mt-2 text-xs text-red-600 dark:text-red-400';
|
||||
resultDiv.textContent = 'Error: ' + error.message;
|
||||
}
|
||||
|
||||
// Restore button
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
|
||||
// Hide result after 10 seconds
|
||||
setTimeout(() => {
|
||||
resultDiv.classList.add('hidden');
|
||||
}, 10000);
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user