Replace full-list assign with stream_insert + phx-update=stream. Add DOM IDs to all packet rows. Skip deprecated phx-update=prepend. Ultraworked with Sisyphus Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
118 lines
6.6 KiB
Text
118 lines
6.6 KiB
Text
<div class="container mx-auto max-w-7xl py-8">
|
|
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10">
|
|
<div class="px-6 py-6">
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-gray-200 dark:divide-white/10">
|
|
<thead>
|
|
<tr>
|
|
<th class="sticky top-0 bg-white py-3 pr-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:bg-gray-800/50 dark:text-gray-400">
|
|
{gettext("Sender")}
|
|
</th>
|
|
<th class="sticky top-0 bg-white py-3 pr-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:bg-gray-800/50 dark:text-gray-400">
|
|
{gettext("SSID")}
|
|
</th>
|
|
<th class="sticky top-0 bg-white py-3 pr-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:bg-gray-800/50 dark:text-gray-400">
|
|
{gettext("Base Callsign")}
|
|
</th>
|
|
<th class="sticky top-0 bg-white py-3 pr-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:bg-gray-800/50 dark:text-gray-400">
|
|
{gettext("Data Type")}
|
|
</th>
|
|
<th class="sticky top-0 bg-white py-3 pr-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:bg-gray-800/50 dark:text-gray-400">
|
|
{gettext("Symbol")}
|
|
</th>
|
|
<th class="sticky top-0 bg-white py-3 pr-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:bg-gray-800/50 dark:text-gray-400">
|
|
{gettext("Path")}
|
|
</th>
|
|
<th class="sticky top-0 bg-white py-3 pr-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:bg-gray-800/50 dark:text-gray-400">
|
|
{gettext("Latitude")}
|
|
</th>
|
|
<th class="sticky top-0 bg-white py-3 pr-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:bg-gray-800/50 dark:text-gray-400">
|
|
{gettext("Longitude")}
|
|
</th>
|
|
<th class="sticky top-0 bg-white py-3 pr-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:bg-gray-800/50 dark:text-gray-400">
|
|
{gettext("Device")}
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="packets-table-body" phx-update="stream" class="divide-y divide-gray-100 dark:divide-white/5">
|
|
<tr :for={{id, packet} <- @streams.packets} id={id} class="even:bg-gray-50 dark:even:bg-white/[0.025]">
|
|
<td class="whitespace-nowrap py-3 pr-3">
|
|
<.link
|
|
navigate={~p"/packets/#{Map.get(packet, :base_callsign, Map.get(packet, "base_callsign", ""))}"}
|
|
class="font-semibold text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
|
|
>
|
|
{Map.get(packet, :sender, Map.get(packet, "sender", ""))}
|
|
</.link>
|
|
</td>
|
|
<td class="whitespace-nowrap py-3 pr-3 text-sm text-gray-500 dark:text-gray-400">
|
|
{Map.get(packet, :ssid, Map.get(packet, "ssid", ""))}
|
|
</td>
|
|
<td class="whitespace-nowrap py-3 pr-3">
|
|
<.link
|
|
navigate={~p"/packets/#{Map.get(packet, :base_callsign, Map.get(packet, "base_callsign", ""))}"}
|
|
class="font-semibold text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
|
|
>
|
|
{Map.get(packet, :base_callsign, Map.get(packet, "base_callsign", ""))}
|
|
</.link>
|
|
</td>
|
|
<td class="whitespace-nowrap py-3 pr-3">
|
|
<span class="inline-flex items-center rounded-md bg-indigo-50 px-2 py-1 text-xs font-medium text-indigo-700 ring-1 ring-inset ring-indigo-700/10 dark:bg-indigo-400/10 dark:text-indigo-400 dark:ring-indigo-400/30">
|
|
{Map.get(packet, :data_type, Map.get(packet, "data_type", ""))}
|
|
</span>
|
|
</td>
|
|
<td class="whitespace-nowrap py-3 pr-3">
|
|
<span class="text-xs font-mono text-gray-700 dark:text-gray-300">
|
|
<% data = Map.get(packet, :data_extended) || %{}
|
|
|
|
raw_table =
|
|
Map.get(data, :symbol_table_id) || Map.get(data, "symbol_table_id") || "/"
|
|
|
|
table = if raw_table in ["/", "\\", "]"], do: raw_table, else: "/"
|
|
code = Map.get(data, :symbol_code) || Map.get(data, "symbol_code") || ">" %>
|
|
{table}{code}
|
|
</span>
|
|
</td>
|
|
<td class="whitespace-nowrap py-3 pr-3">
|
|
<span class="text-xs font-mono text-gray-500 dark:text-gray-400">
|
|
{Map.get(packet, :path, Map.get(packet, "path", ""))}
|
|
</span>
|
|
</td>
|
|
<td class="whitespace-nowrap py-3 pr-3">
|
|
<span class="text-xs font-mono text-gray-700 dark:text-gray-300">
|
|
{format_coordinate(extract_coordinate(packet, :lat))}
|
|
</span>
|
|
</td>
|
|
<td class="whitespace-nowrap py-3 pr-3">
|
|
<span class="text-xs font-mono text-gray-700 dark:text-gray-300">
|
|
{format_coordinate(extract_coordinate(packet, :lon))}
|
|
</span>
|
|
</td>
|
|
<td class="whitespace-nowrap py-3 pr-3">
|
|
<span class="text-xs font-mono text-gray-500 dark:text-gray-400">
|
|
{Map.get(packet, :device_identifier, Map.get(packet, "device_identifier", ""))}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<%= if Enum.count(@streams.packets) == 0 do %>
|
|
<div class="text-center py-12">
|
|
<div class="flex justify-center mb-4">
|
|
<svg class="w-16 h-16 text-gray-400 dark:text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<h3 class="text-lg font-medium mb-2">{gettext("No packets")}</h3>
|
|
<p class="text-gray-500 dark:text-gray-400">{gettext("Packets will appear here as they are received.")}</p>
|
|
</div>
|
|
<% end %>
|
|
</div>
|