status page cards
This commit is contained in:
parent
f1bc428086
commit
0ffba18d52
2 changed files with 236 additions and 322 deletions
|
|
@ -7,133 +7,135 @@ defmodule AprsmeWeb.StatusLive.ConnectionCardComponent do
|
|||
def render(assigns) do
|
||||
~H"""
|
||||
<div class="mb-8">
|
||||
<h2 class="text-xl font-semibold text-gray-900 mb-4">APRS-IS Connection</h2>
|
||||
<div class="bg-gray-50 p-4 rounded-lg">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Status:</span>
|
||||
<%= if @aprs_status.connected do %>
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
|
||||
<svg class="w-2 h-2 mr-1" fill="currentColor" viewBox="0 0 8 8">
|
||||
<circle cx="4" cy="4" r="3" />
|
||||
</svg>
|
||||
Connected
|
||||
</span>
|
||||
<% else %>
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
|
||||
<svg class="w-2 h-2 mr-1" fill="currentColor" viewBox="0 0 8 8">
|
||||
<circle cx="4" cy="4" r="3" />
|
||||
</svg>
|
||||
Disconnected
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Server:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">
|
||||
{@aprs_status.server}:{@aprs_status.port}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Login ID:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">{@aprs_status.login_id}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Connected Since:</span>
|
||||
<span class="text-sm text-gray-900">
|
||||
<%= if @aprs_status.connected_at do %>
|
||||
{Calendar.strftime(@aprs_status.connected_at, "%Y-%m-%d %H:%M:%S UTC")}
|
||||
<h2 class="text-xl font-semibold mb-4">APRS-IS Connection</h2>
|
||||
<div class="card bg-base-200">
|
||||
<div class="card-body">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Status:</span>
|
||||
<%= if @aprs_status.connected do %>
|
||||
<div class="badge badge-success gap-1">
|
||||
<div class="w-2 h-2 bg-current rounded-full"></div>
|
||||
Connected
|
||||
</div>
|
||||
<% else %>
|
||||
<span class="text-gray-400">Not connected</span>
|
||||
<div class="badge badge-error gap-1">
|
||||
<div class="w-2 h-2 bg-current rounded-full"></div>
|
||||
Disconnected
|
||||
</div>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Uptime:</span>
|
||||
<span class={[
|
||||
"text-sm font-medium",
|
||||
if(@aprs_status.connected, do: "text-green-700", else: "text-red-600")
|
||||
]}>
|
||||
{AprsmeWeb.StatusLive.Index.format_uptime(@aprs_status.uptime_seconds)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center col-span-2">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Filter:</span>
|
||||
<span class="text-sm text-gray-900 font-mono bg-gray-100 px-2 py-1 rounded border">
|
||||
{@aprs_status.filter}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Packet Statistics -->
|
||||
<div class="mt-4 pt-4 border-t border-gray-200">
|
||||
<h3 class="text-sm font-medium text-gray-700 mb-3">Packet Statistics</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Total Packets:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">
|
||||
{AprsmeWeb.StatusLive.Index.format_number(@aprs_status.packet_stats.total_packets)}
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Server:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{@aprs_status.server}:{@aprs_status.port}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Packets/Sec:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">
|
||||
{@aprs_status.packet_stats.packets_per_second}
|
||||
</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Login ID:</span>
|
||||
<span class="text-sm font-mono">{@aprs_status.login_id}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Last Packet:</span>
|
||||
<span class="text-sm text-gray-900">
|
||||
<%= if @aprs_status.packet_stats.last_packet_at do %>
|
||||
{AprsmeWeb.StatusLive.Index.format_time_ago(
|
||||
@aprs_status.packet_stats.last_packet_at
|
||||
)}
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Connected Since:</span>
|
||||
<span class="text-sm">
|
||||
<%= if @aprs_status.connected_at do %>
|
||||
{Calendar.strftime(@aprs_status.connected_at, "%Y-%m-%d %H:%M:%S UTC")}
|
||||
<% else %>
|
||||
<span class="text-gray-400">None</span>
|
||||
<span class="opacity-50">Not connected</span>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Stored Packets:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">
|
||||
{AprsmeWeb.StatusLive.Index.format_number(@aprs_status.stored_packet_count)}
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Uptime:</span>
|
||||
<span class={[
|
||||
"text-sm font-medium",
|
||||
if(@aprs_status.connected, do: "text-success", else: "text-error")
|
||||
]}>
|
||||
{AprsmeWeb.StatusLive.Index.format_uptime(@aprs_status.uptime_seconds)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 pt-4 border-t border-gray-200">
|
||||
<div class="flex items-center col-span-2">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Filter:</span>
|
||||
<div class="badge badge-outline font-mono">
|
||||
{@aprs_status.filter}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Packet Statistics -->
|
||||
<div class="divider"></div>
|
||||
<div>
|
||||
<h3 class="text-sm font-medium mb-3">Packet Statistics</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-5 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Total Packets:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{AprsmeWeb.StatusLive.Index.format_number(@aprs_status.packet_stats.total_packets)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Packets/Sec:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{@aprs_status.packet_stats.packets_per_second}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Packets/Min:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{@aprs_status.packet_stats.packets_per_second * 60}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Last Packet:</span>
|
||||
<span class="text-sm">
|
||||
<%= if @aprs_status.packet_stats.last_packet_at do %>
|
||||
{AprsmeWeb.StatusLive.Index.format_time_ago(
|
||||
@aprs_status.packet_stats.last_packet_at
|
||||
)}
|
||||
<% else %>
|
||||
<span class="opacity-50">None</span>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Stored Packets:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{AprsmeWeb.StatusLive.Index.format_number(@aprs_status.stored_packet_count)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm font-medium text-gray-500">Connection Health:</span>
|
||||
<span class="text-sm font-medium opacity-70">Connection Health:</span>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center mr-2">
|
||||
<div class="rating rating-sm mr-2">
|
||||
<%= for i <- 1..5 do %>
|
||||
<svg
|
||||
class={[
|
||||
"w-4 h-4",
|
||||
if(i <= @health_score, do: "text-green-400", else: "text-gray-300")
|
||||
]}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
||||
</svg>
|
||||
<input
|
||||
type="radio"
|
||||
name="health-rating"
|
||||
class="mask mask-star-2 bg-orange-400"
|
||||
disabled
|
||||
checked={i <= @health_score}
|
||||
/>
|
||||
<% end %>
|
||||
</div>
|
||||
<span class="text-sm font-medium text-gray-700">
|
||||
<span class="text-sm font-medium">
|
||||
{@health_score}/5
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-1 text-xs text-gray-500">
|
||||
<p class="text-xs opacity-70 mt-1">
|
||||
{AprsmeWeb.StatusLive.Index.get_health_description(@health_score, @aprs_status.connected)}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
aprs_status: get_aprs_status(),
|
||||
version: get_app_version(),
|
||||
current_time: DateTime.utc_now(),
|
||||
auto_refresh: true,
|
||||
health_score: calculate_health_score(get_aprs_status())
|
||||
)
|
||||
|
||||
|
|
@ -27,46 +26,23 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
{:ok, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("toggle_auto_refresh", _params, socket) do
|
||||
new_auto_refresh = !socket.assigns.auto_refresh
|
||||
|
||||
socket = assign(socket, auto_refresh: new_auto_refresh)
|
||||
|
||||
if new_auto_refresh do
|
||||
schedule_refresh()
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("refresh_now", _params, socket) do
|
||||
socket = refresh_status(socket)
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(:refresh_status, socket) do
|
||||
socket = refresh_status(socket)
|
||||
|
||||
# Schedule next refresh if auto-refresh is enabled
|
||||
if socket.assigns.auto_refresh do
|
||||
schedule_refresh()
|
||||
end
|
||||
|
||||
# Schedule next refresh
|
||||
schedule_refresh()
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<div class="mx-auto max-w-4xl">
|
||||
<div class="bg-white shadow rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="container mx-auto max-w-4xl p-4">
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<h1 class="text-3xl font-bold text-gray-900">APRS.me System Status</h1>
|
||||
<div class="text-sm text-gray-500">
|
||||
<h1 class="card-title text-3xl">APRS.me System Status</h1>
|
||||
<div class="text-sm opacity-70">
|
||||
Last updated:
|
||||
<span class="font-mono">{Calendar.strftime(@current_time, "%H:%M:%S UTC")}</span>
|
||||
</div>
|
||||
|
|
@ -74,31 +50,24 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
|
||||
<!-- Overall Status Alert -->
|
||||
<%= if not @aprs_status.connected do %>
|
||||
<div class="mb-6 rounded-md bg-red-50 p-4 border border-red-200">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg
|
||||
class="h-5 w-5 text-red-400"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-red-800">
|
||||
APRS-IS Connection Issue
|
||||
</h3>
|
||||
<div class="mt-2 text-sm text-red-700">
|
||||
<p>
|
||||
The system is currently disconnected from the APRS-IS network. This may be due to network issues or server maintenance.
|
||||
</p>
|
||||
</div>
|
||||
<div class="alert alert-error mb-6">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="stroke-current shrink-0 h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<div>
|
||||
<h3 class="font-bold">APRS-IS Connection Issue</h3>
|
||||
<div class="text-xs">
|
||||
The system is currently disconnected from the APRS-IS network. This may be due to network issues or server maintenance.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -106,132 +75,134 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
|
||||
<!-- APRS-IS Connection Status -->
|
||||
<div class="mb-8">
|
||||
<h2 class="text-xl font-semibold text-gray-900 mb-4">APRS-IS Connection</h2>
|
||||
<div class="bg-gray-50 p-4 rounded-lg">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Status:</span>
|
||||
<%= if @aprs_status.connected do %>
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
|
||||
<svg class="w-2 h-2 mr-1" fill="currentColor" viewBox="0 0 8 8">
|
||||
<circle cx="4" cy="4" r="3" />
|
||||
</svg>
|
||||
Connected
|
||||
</span>
|
||||
<% else %>
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
|
||||
<svg class="w-2 h-2 mr-1" fill="currentColor" viewBox="0 0 8 8">
|
||||
<circle cx="4" cy="4" r="3" />
|
||||
</svg>
|
||||
Disconnected
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Server:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">
|
||||
{@aprs_status.server}:{@aprs_status.port}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Login ID:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">{@aprs_status.login_id}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Connected Since:</span>
|
||||
<span class="text-sm text-gray-900">
|
||||
<%= if @aprs_status.connected_at do %>
|
||||
{Calendar.strftime(@aprs_status.connected_at, "%Y-%m-%d %H:%M:%S UTC")}
|
||||
<h2 class="text-xl font-semibold mb-4">APRS-IS Connection</h2>
|
||||
<div class="card bg-base-200">
|
||||
<div class="card-body">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Status:</span>
|
||||
<%= if @aprs_status.connected do %>
|
||||
<div class="badge badge-success gap-1">
|
||||
<div class="w-2 h-2 bg-current rounded-full"></div>
|
||||
Connected
|
||||
</div>
|
||||
<% else %>
|
||||
<span class="text-gray-400">Not connected</span>
|
||||
<div class="badge badge-error gap-1">
|
||||
<div class="w-2 h-2 bg-current rounded-full"></div>
|
||||
Disconnected
|
||||
</div>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Uptime:</span>
|
||||
<span class={[
|
||||
"text-sm font-medium",
|
||||
if(@aprs_status.connected, do: "text-green-700", else: "text-red-600")
|
||||
]}>
|
||||
{format_uptime(@aprs_status.uptime_seconds)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center col-span-2">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Filter:</span>
|
||||
<span class="text-sm text-gray-900 font-mono bg-gray-100 px-2 py-1 rounded border">
|
||||
{@aprs_status.filter}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Packet Statistics -->
|
||||
<div class="mt-4 pt-4 border-t border-gray-200">
|
||||
<h3 class="text-sm font-medium text-gray-700 mb-3">Packet Statistics</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Total Packets:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">
|
||||
{format_number(@aprs_status.packet_stats.total_packets)}
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Server:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{@aprs_status.server}:{@aprs_status.port}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Packets/Sec:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">
|
||||
{@aprs_status.packet_stats.packets_per_second}
|
||||
</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Login ID:</span>
|
||||
<span class="text-sm font-mono">{@aprs_status.login_id}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Last Packet:</span>
|
||||
<span class="text-sm text-gray-900">
|
||||
<%= if @aprs_status.packet_stats.last_packet_at do %>
|
||||
{format_time_ago(@aprs_status.packet_stats.last_packet_at)}
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Connected Since:</span>
|
||||
<span class="text-sm">
|
||||
<%= if @aprs_status.connected_at do %>
|
||||
{Calendar.strftime(@aprs_status.connected_at, "%Y-%m-%d %H:%M:%S UTC")}
|
||||
<% else %>
|
||||
<span class="text-gray-400">None</span>
|
||||
<span class="opacity-50">Not connected</span>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Stored Packets:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">
|
||||
{format_number(@aprs_status.stored_packet_count)}
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Uptime:</span>
|
||||
<span class={[
|
||||
"text-sm font-medium",
|
||||
if(@aprs_status.connected, do: "text-success", else: "text-error")
|
||||
]}>
|
||||
{format_uptime(@aprs_status.uptime_seconds)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center col-span-2">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Filter:</span>
|
||||
<div class="badge badge-outline font-mono">
|
||||
{@aprs_status.filter}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Packet Statistics -->
|
||||
<div class="divider"></div>
|
||||
<div>
|
||||
<h3 class="text-sm font-medium mb-3">Packet Statistics</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-5 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Total Packets:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{format_number(@aprs_status.packet_stats.total_packets)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Packets/Sec:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{@aprs_status.packet_stats.packets_per_second}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Packets/Min:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{@aprs_status.packet_stats.packets_per_second * 60}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Last Packet:</span>
|
||||
<span class="text-sm">
|
||||
<%= if @aprs_status.packet_stats.last_packet_at do %>
|
||||
{format_time_ago(@aprs_status.packet_stats.last_packet_at)}
|
||||
<% else %>
|
||||
<span class="opacity-50">None</span>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Stored Packets:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{format_number(@aprs_status.stored_packet_count)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Health Score -->
|
||||
<div class="mt-4 pt-4 border-t border-gray-200">
|
||||
<div class="divider"></div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm font-medium text-gray-500">Connection Health:</span>
|
||||
<span class="text-sm font-medium opacity-70">Connection Health:</span>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center mr-2">
|
||||
<div class="rating rating-sm mr-2">
|
||||
<%= for i <- 1..5 do %>
|
||||
<svg
|
||||
class={[
|
||||
"w-4 h-4",
|
||||
if(i <= @health_score, do: "text-green-400", else: "text-gray-300")
|
||||
]}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
||||
</svg>
|
||||
<input
|
||||
type="radio"
|
||||
name="health-rating"
|
||||
class="mask mask-star-2 bg-orange-400"
|
||||
disabled
|
||||
checked={i <= @health_score}
|
||||
/>
|
||||
<% end %>
|
||||
</div>
|
||||
<span class="text-sm font-medium text-gray-700">
|
||||
<span class="text-sm font-medium">
|
||||
{@health_score}/5
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-1 text-xs text-gray-500">
|
||||
<p class="text-xs opacity-70 mt-1">
|
||||
{get_health_description(@health_score, @aprs_status.connected)}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -240,82 +211,23 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
|
||||
<!-- Application Information -->
|
||||
<div class="mb-8">
|
||||
<h2 class="text-xl font-semibold text-gray-900 mb-4">Application Information</h2>
|
||||
<div class="bg-gray-50 p-4 rounded-lg">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Version:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">{@version}</span>
|
||||
</div>
|
||||
<h2 class="text-xl font-semibold mb-4">Application Information</h2>
|
||||
<div class="card bg-base-200">
|
||||
<div class="card-body">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Version:</span>
|
||||
<span class="text-sm font-mono">{@version}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium text-gray-500 mr-2">Current Time:</span>
|
||||
<span class="text-sm text-gray-900 font-mono">
|
||||
{Calendar.strftime(@current_time, "%Y-%m-%d %H:%M:%S UTC")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Auto-refresh controls -->
|
||||
<div class="bg-blue-50 p-4 rounded-lg">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-shrink-0">
|
||||
<svg
|
||||
class="h-5 w-5 text-blue-400"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm text-blue-700">
|
||||
Auto-refresh:
|
||||
<span class="font-semibold">
|
||||
{if @auto_refresh, do: "ON", else: "OFF"}
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Current Time:</span>
|
||||
<span class="text-sm font-mono">
|
||||
{Calendar.strftime(@current_time, "%Y-%m-%d %H:%M:%S UTC")}
|
||||
</span>
|
||||
<%= if @auto_refresh do %>
|
||||
(every second)
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<button
|
||||
phx-click="toggle_auto_refresh"
|
||||
class={[
|
||||
"inline-flex items-center px-3 py-1 border text-xs font-medium rounded focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500",
|
||||
if(@auto_refresh,
|
||||
do: "border-blue-200 text-blue-700 bg-blue-100 hover:bg-blue-200",
|
||||
else: "border-gray-300 text-gray-700 bg-white hover:bg-gray-50"
|
||||
)
|
||||
]}
|
||||
>
|
||||
{if @auto_refresh, do: "Disable", else: "Enable"} Auto-refresh
|
||||
</button>
|
||||
<button
|
||||
phx-click="refresh_now"
|
||||
class="inline-flex items-center px-3 py-1 border border-transparent text-xs font-medium rounded text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
||||
>
|
||||
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
|
||||
/>
|
||||
</svg>
|
||||
Refresh Now
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue