diff --git a/src/meshcore_hub/web/static/css/app.css b/src/meshcore_hub/web/static/css/app.css index 5eeb635..aa7df99 100644 --- a/src/meshcore_hub/web/static/css/app.css +++ b/src/meshcore_hub/web/static/css/app.css @@ -23,8 +23,8 @@ --color-nodes: oklch(0.65 0.24 265); /* violet */ --color-adverts: oklch(0.7 0.17 330); /* magenta */ --color-messages: oklch(0.75 0.18 180); /* teal */ - --color-map: oklch(0.72 0.19 142); /* green */ - --color-members: oklch(0.75 0.15 75); /* amber */ + --color-map: oklch(0.8 0.17 80); /* yellow (matches btn-warning) */ + --color-members: oklch(0.72 0.17 50); /* orange */ } /* ========================================================================== diff --git a/src/meshcore_hub/web/static/js/spa/pages/node-detail.js b/src/meshcore_hub/web/static/js/spa/pages/node-detail.js index e276b7b..7c91748 100644 --- a/src/meshcore_hub/web/static/js/spa/pages/node-detail.js +++ b/src/meshcore_hub/web/static/js/spa/pages/node-detail.js @@ -199,17 +199,20 @@ ${heroHtml} cleanupFns.push(() => map.remove()); } - // Initialize QR code - if (typeof QRCode !== 'undefined') { - const typeMap = { chat: 1, repeater: 2, room: 3, sensor: 4 }; - const typeNum = typeMap[(node.adv_type || '').toLowerCase()] || 1; - const url = 'meshcore://contact/add?name=' + encodeURIComponent(displayName) + '&public_key=' + node.public_key + '&type=' + typeNum; - new QRCode(document.getElementById('qr-code'), { - text: url, width: 140, height: 140, - colorDark: '#000000', colorLight: '#ffffff', - correctLevel: QRCode.CorrectLevel.L, - }); - } + // Initialize QR code (defer to next frame so layout settles after map init) + requestAnimationFrame(() => { + const qrEl = document.getElementById('qr-code'); + if (qrEl && typeof QRCode !== 'undefined') { + const typeMap = { chat: 1, repeater: 2, room: 3, sensor: 4 }; + const typeNum = typeMap[(node.adv_type || '').toLowerCase()] || 1; + const url = 'meshcore://contact/add?name=' + encodeURIComponent(displayName) + '&public_key=' + node.public_key + '&type=' + typeNum; + new QRCode(qrEl, { + text: url, width: 140, height: 140, + colorDark: '#000000', colorLight: '#ffffff', + correctLevel: QRCode.CorrectLevel.L, + }); + } + }); return () => { cleanupFns.forEach(fn => fn()); diff --git a/src/meshcore_hub/web/templates/_macros.html b/src/meshcore_hub/web/templates/_macros.html deleted file mode 100644 index a994ef9..0000000 --- a/src/meshcore_hub/web/templates/_macros.html +++ /dev/null @@ -1,47 +0,0 @@ -{# Reusable macros for templates #} - -{# - Pagination macro - - Parameters: - - page: Current page number - - total_pages: Total number of pages - - params: Dict of query parameters to preserve (e.g., {"search": "foo", "limit": 50}) -#} -{% macro pagination(page, total_pages, params={}) %} -{% if total_pages > 1 %} -{% set query_parts = [] %} -{% for key, value in params.items() %} -{% if value is not none and value != '' %} -{% set _ = query_parts.append(key ~ '=' ~ value) %} -{% endif %} -{% endfor %} -{% set base_query = query_parts|join('&') %} -{% set query_prefix = '&' if base_query else '' %} -
-
- {% if page > 1 %} - Previous - {% else %} - - {% endif %} - - {% for p in range(1, total_pages + 1) %} - {% if p == page %} - - {% elif p == 1 or p == total_pages or (p >= page - 2 and p <= page + 2) %} - {{ p }} - {% elif p == 2 or p == total_pages - 1 %} - - {% endif %} - {% endfor %} - - {% if page < total_pages %} - Next - {% else %} - - {% endif %} -
-
-{% endif %} -{% endmacro %} diff --git a/src/meshcore_hub/web/templates/admin/access_denied.html b/src/meshcore_hub/web/templates/admin/access_denied.html deleted file mode 100644 index 1e0b91e..0000000 --- a/src/meshcore_hub/web/templates/admin/access_denied.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "base.html" %} -{% from "macros/icons.html" import icon_lock %} - -{% block title %}Access Denied - {{ network_name }}{% endblock %} - -{% block content %} -
-
- {{ icon_lock("h-24 w-24 mx-auto text-error opacity-50 mb-6") }} -

Access Denied

-

You don't have permission to access the admin area.

-

Please contact the network administrator if you believe this is an error.

- -
-
-{% endblock %} diff --git a/src/meshcore_hub/web/templates/admin/index.html b/src/meshcore_hub/web/templates/admin/index.html deleted file mode 100644 index ad821a8..0000000 --- a/src/meshcore_hub/web/templates/admin/index.html +++ /dev/null @@ -1,57 +0,0 @@ -{% extends "base.html" %} -{% from "macros/icons.html" import icon_user, icon_email, icon_users, icon_tag %} - -{% block title %}Admin - {{ network_name }}{% endblock %} - -{% block content %} -
-
-

Admin

- -
- Sign Out -
- - -
- {% if auth_username or auth_user %} - - {{ icon_user("h-4 w-4") }} - {{ auth_username or auth_user }} - - {% endif %} - {% if auth_email %} - - {{ icon_email("h-4 w-4") }} - {{ auth_email }} - - {% endif %} -
- - -
- -
-

- {{ icon_users("h-6 w-6") }} - Members -

-

Manage network members and operators.

-
-
- -
-

- {{ icon_tag("h-6 w-6") }} - Node Tags -

-

Manage custom tags and metadata for network nodes.

-
-
-
-{% endblock %} diff --git a/src/meshcore_hub/web/templates/admin/members.html b/src/meshcore_hub/web/templates/admin/members.html deleted file mode 100644 index 1364f8b..0000000 --- a/src/meshcore_hub/web/templates/admin/members.html +++ /dev/null @@ -1,277 +0,0 @@ -{% extends "base.html" %} -{% from "macros/icons.html" import icon_success, icon_error, icon_alert %} - -{% block title %}Admin: Members - {{ network_name }}{% endblock %} - -{% block content %} -
-
-

Members

- -
- Sign Out -
- - -{% if message %} -
- {{ icon_success("stroke-current shrink-0 h-6 w-6") }} - {{ message }} -
-{% endif %} - -{% if error %} -
- {{ icon_error("stroke-current shrink-0 h-6 w-6") }} - {{ error }} -
-{% endif %} - - -
-
-
-

Network Members ({{ members|length }})

- -
- - {% if members %} -
- - - - - - - - - - - - {% for member in members %} - - - - - - - - {% endfor %} - -
Member IDNameCallsignContactActions
{{ member.member_id }}{{ member.name }} - {% if member.callsign %} - {{ member.callsign }} - {% else %} - - - {% endif %} - {{ member.contact or '-' }} -
- - -
-
-
- {% else %} -
-

No members configured yet.

-

Click "Add Member" to create the first member.

-
- {% endif %} -
-
- - - - - - - - - - - - - - - - - - -{% endblock %} - -{% block extra_scripts %} - -{% endblock %} diff --git a/src/meshcore_hub/web/templates/admin/node_tags.html b/src/meshcore_hub/web/templates/admin/node_tags.html deleted file mode 100644 index 4886e7f..0000000 --- a/src/meshcore_hub/web/templates/admin/node_tags.html +++ /dev/null @@ -1,419 +0,0 @@ -{% extends "base.html" %} -{% from "macros/icons.html" import icon_success, icon_error, icon_alert, icon_info, icon_tag %} - -{% block title %}Admin: Node Tags - {{ network_name }}{% endblock %} - -{% block content %} -
-
-

Node Tags

- -
- Sign Out -
- - -{% if message %} -
- {{ icon_success("stroke-current shrink-0 h-6 w-6") }} - {{ message }} -
-{% endif %} - -{% if error %} -
- {{ icon_error("stroke-current shrink-0 h-6 w-6") }} - {{ error }} -
-{% endif %} - - -
-
-

Select Node

-
-
- - -
- -
-
-
- -{% if selected_public_key and selected_node %} - -
-
-
-
- {% if selected_node.adv_type and selected_node.adv_type|lower == 'chat' %}💬{% elif selected_node.adv_type and selected_node.adv_type|lower == 'repeater' %}📡{% elif selected_node.adv_type and selected_node.adv_type|lower == 'room' %}🪧{% else %}📍{% endif %} -
-

{{ selected_node.name or 'Unnamed Node' }}

-

{{ selected_public_key }}

-
-
-
- {% if tags %} - - - {% endif %} - View Node -
-
-
-
- - -
-
-

Tags ({{ tags|length }})

- - {% if tags %} -
- - - - - - - - - - - - {% for tag in tags %} - - - - - - - - {% endfor %} - -
KeyValueTypeUpdatedActions
{{ tag.key }}{{ tag.value or '-' }} - {{ tag.value_type }} - {{ tag.updated_at|localdate }} -
- - - -
-
-
- {% else %} -
-

No tags found for this node.

-

Add a new tag below.

-
- {% endif %} -
-
- - -
-
-

Add New Tag

-
- - -
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -{% elif selected_public_key and not selected_node %} -
- {{ icon_alert("stroke-current shrink-0 h-6 w-6") }} - Node not found: {{ selected_public_key }} -
-{% else %} -
-
- {{ icon_tag("h-16 w-16 mx-auto mb-4 opacity-30") }} -

Select a Node

-

Choose a node from the dropdown above to view and manage its tags.

-
-
-{% endif %} -{% endblock %} - -{% block extra_scripts %} - -{% endblock %} diff --git a/src/meshcore_hub/web/templates/advertisements.html b/src/meshcore_hub/web/templates/advertisements.html deleted file mode 100644 index 4e6737d..0000000 --- a/src/meshcore_hub/web/templates/advertisements.html +++ /dev/null @@ -1,165 +0,0 @@ -{% extends "base.html" %} -{% from "_macros.html" import pagination %} -{% from "macros/icons.html" import icon_alert %} - -{% block title %}Advertisements - {{ network_name }}{% endblock %} - -{% block content %} -
-

Advertisements

-
- {% if timezone and timezone != 'UTC' %}{{ timezone }}{% endif %} - {{ total }} total -
-
- -{% if api_error %} -
- {{ icon_alert("stroke-current shrink-0 h-6 w-6") }} - Could not fetch data from API: {{ api_error }} -
-{% endif %} - - -
-
-
-
- - -
- {% if nodes %} -
- - -
- {% endif %} - {% if members %} -
- - -
- {% endif %} -
- - Clear -
-
-
-
- - -
- {% for ad in advertisements %} - -
-
-
- {% if ad.adv_type and ad.adv_type|lower == 'chat' %}💬{% elif ad.adv_type and ad.adv_type|lower == 'repeater' %}📡{% elif ad.adv_type and ad.adv_type|lower == 'room' %}🪧{% else %}📍{% endif %} -
- {% if ad.node_tag_name or ad.node_name or ad.name %} -
{{ ad.node_tag_name or ad.node_name or ad.name }}
-
{{ ad.public_key[:16] }}...
- {% else %} -
{{ ad.public_key[:16] }}...
- {% endif %} -
-
-
-
- {{ ad.received_at|localtime_short }} -
- {% if ad.receivers and ad.receivers|length >= 1 %} -
- {% for recv in ad.receivers %} - 📡 - {% endfor %} -
- {% elif ad.received_by %} - 📡 - {% endif %} -
-
-
-
- {% else %} -
No advertisements found.
- {% endfor %} -
- - - - -{{ pagination(page, total_pages, {"search": search, "public_key": public_key, "member_id": member_id, "limit": limit}) }} -{% endblock %} diff --git a/src/meshcore_hub/web/templates/base.html b/src/meshcore_hub/web/templates/base.html deleted file mode 100644 index f62d5ce..0000000 --- a/src/meshcore_hub/web/templates/base.html +++ /dev/null @@ -1,126 +0,0 @@ -{% from "macros/icons.html" import icon_home, icon_dashboard, icon_nodes, icon_advertisements, icon_messages, icon_map, icon_members, icon_page, icon_menu %} - - - - - - {% block title %}{{ network_name }}{% endblock %} - - - {% set default_description = (network_name ~ " - " ~ network_welcome_text) if network_welcome_text else (network_name ~ " - MeshCore off-grid LoRa mesh network dashboard.") %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {% block extra_head %}{% endblock %} - - - - - - -
- {% block content %}{% endblock %} -
- - - - - - - - {% block extra_scripts %}{% endblock %} - - diff --git a/src/meshcore_hub/web/templates/dashboard.html b/src/meshcore_hub/web/templates/dashboard.html deleted file mode 100644 index f11ee90..0000000 --- a/src/meshcore_hub/web/templates/dashboard.html +++ /dev/null @@ -1,195 +0,0 @@ -{% extends "base.html" %} -{% from "macros/icons.html" import icon_nodes, icon_advertisements, icon_messages, icon_alert, icon_channel %} - -{% block title %}Dashboard - {{ network_name }}{% endblock %} - -{% block content %} -
-

Dashboard

-
- -{% if api_error %} -
- {{ icon_alert("stroke-current shrink-0 h-6 w-6") }} - Could not fetch data from API: {{ api_error }} -
-{% endif %} - - -
- -
-
- {{ icon_nodes("h-8 w-8") }} -
-
Total Nodes
-
{{ stats.total_nodes }}
-
All discovered nodes
-
- - -
-
- {{ icon_advertisements("h-8 w-8") }} -
-
Advertisements
-
{{ stats.advertisements_7d }}
-
Last 7 days
-
- - -
-
- {{ icon_messages("h-8 w-8") }} -
-
Messages
-
{{ stats.messages_7d }}
-
Last 7 days
-
-
- - -
- -
-
-

- {{ icon_nodes("h-5 w-5") }} - Total Nodes -

-

Over time (last 7 days)

-
- -
-
-
- - -
-
-

- {{ icon_advertisements("h-5 w-5") }} - Advertisements -

-

Per day (last 7 days)

-
- -
-
-
- - -
-
-

- {{ icon_messages("h-5 w-5") }} - Messages -

-

Per day (last 7 days)

-
- -
-
-
-
- - -
- -
-
-

- {{ icon_advertisements("h-6 w-6") }} - Recent Advertisements -

- {% if stats.recent_advertisements %} -
- - - - - - - - - - {% for ad in stats.recent_advertisements %} - - - - - - {% endfor %} - -
NodeTypeReceived
- -
{{ ad.friendly_name or ad.name or ad.public_key[:12] + '...' }}
-
- {% if ad.friendly_name or ad.name %} -
{{ ad.public_key[:12] }}...
- {% endif %} -
- {% if ad.adv_type and ad.adv_type|lower == 'chat' %} - 💬 - {% elif ad.adv_type and ad.adv_type|lower == 'repeater' %} - 📡 - {% elif ad.adv_type and ad.adv_type|lower == 'room' %} - 🪧 - {% elif ad.adv_type %} - 📍 - {% else %} - - - {% endif %} - {{ ad.received_at|localtimeonly }}
-
- {% else %} -

No advertisements recorded yet.

- {% endif %} -
-
- - - {% if stats.channel_messages %} -
-
-

- {{ icon_channel("h-6 w-6") }} - Recent Channel Messages -

-
- {% for channel, messages in stats.channel_messages.items() %} -
-

- CH{{ channel }} - Channel {{ channel }} -

-
- {% for msg in messages %} -
- {{ msg.received_at|localtimeonly_short }} - {{ msg.text }} -
- {% endfor %} -
-
- {% endfor %} -
-
-
- {% endif %} -
- -{% endblock %} - -{% block extra_scripts %} - - - -{% endblock %} diff --git a/src/meshcore_hub/web/templates/errors/404.html b/src/meshcore_hub/web/templates/errors/404.html deleted file mode 100644 index 2922b8d..0000000 --- a/src/meshcore_hub/web/templates/errors/404.html +++ /dev/null @@ -1,32 +0,0 @@ -{% extends "base.html" %} -{% from "macros/icons.html" import icon_home, icon_nodes %} - -{% block title %}Page Not Found - {{ network_name }}{% endblock %} - -{% block content %} -
-
-
-
404
-

Page Not Found

-

- {% if detail %} - {{ detail }} - {% else %} - The page you're looking for doesn't exist or has been moved. - {% endif %} -

- -
-
-
-{% endblock %} diff --git a/src/meshcore_hub/web/templates/home.html b/src/meshcore_hub/web/templates/home.html deleted file mode 100644 index af31afb..0000000 --- a/src/meshcore_hub/web/templates/home.html +++ /dev/null @@ -1,198 +0,0 @@ -{% extends "base.html" %} -{% from "macros/icons.html" import icon_dashboard, icon_map, icon_nodes, icon_advertisements, icon_messages, icon_page, icon_info, icon_chart, icon_globe, icon_github %} - -{% block title %}{{ network_name }}{% endblock %} - -{% block content %} - -
- -
- -
- {{ network_name }} -
-

{{ network_name }}

- {% if network_city and network_country %} -

{{ network_city }}, {{ network_country }}

- {% endif %} -
-
- {% if network_welcome_text %} -

{{ network_welcome_text }}

- {% else %} -

- Welcome to the {{ network_name }} mesh network dashboard. - Monitor network activity, view connected nodes, and explore message history. -

- {% endif %} -
- -
- - -
- -
-
- {{ icon_nodes("h-8 w-8") }} -
-
Total Nodes
-
{{ stats.total_nodes }}
-
All discovered nodes
-
- - -
-
- {{ icon_advertisements("h-8 w-8") }} -
-
Advertisements
-
{{ stats.advertisements_7d }}
-
Last 7 days
-
- - -
-
- {{ icon_messages("h-8 w-8") }} -
-
Messages
-
{{ stats.messages_7d }}
-
Last 7 days
-
-
-
- -
- -
-
-

- {{ icon_info("h-6 w-6") }} - Network Info -

-
- {% if network_radio_config %} - {% if network_radio_config.profile %} -
- Profile: - {{ network_radio_config.profile }} -
- {% endif %} - {% if network_radio_config.frequency %} -
- Frequency: - {{ network_radio_config.frequency }} -
- {% endif %} - {% if network_radio_config.bandwidth %} -
- Bandwidth: - {{ network_radio_config.bandwidth }} -
- {% endif %} - {% if network_radio_config.spreading_factor %} -
- Spreading Factor: - {{ network_radio_config.spreading_factor }} -
- {% endif %} - {% if network_radio_config.coding_rate %} -
- Coding Rate: - {{ network_radio_config.coding_rate }} -
- {% endif %} - {% if network_radio_config.tx_power %} -
- TX Power: - {{ network_radio_config.tx_power }} -
- {% endif %} - {% endif %} - {% if network_location and network_location != (0.0, 0.0) %} -
- Location: - {{ "%.4f"|format(network_location[0]) }}, {{ "%.4f"|format(network_location[1]) }} -
- {% endif %} -
-
-
- - -
-
-

Our local off-grid mesh network is made possible by

- - MeshCore - -

Connecting people and things, without using the internet

- -
-
- - -
-
-

- {{ icon_chart("h-6 w-6") }} - Network Activity -

-

Activity per day (last 7 days)

-
- -
-
-
-
-{% endblock %} - -{% block extra_scripts %} - - - -{% endblock %} diff --git a/src/meshcore_hub/web/templates/macros/icons.html b/src/meshcore_hub/web/templates/macros/icons.html deleted file mode 100644 index 8c88135..0000000 --- a/src/meshcore_hub/web/templates/macros/icons.html +++ /dev/null @@ -1,143 +0,0 @@ -{% macro icon_dashboard(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_map(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_nodes(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_advertisements(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_messages(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_home(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_members(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_page(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_info(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_alert(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_chart(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_refresh(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_menu(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_github(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_external_link(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_globe(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_error(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_channel(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_success(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_lock(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_user(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_email(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_tag(class="h-5 w-5") %} - - - -{% endmacro %} - -{% macro icon_users(class="h-5 w-5") %} - - - -{% endmacro %} diff --git a/src/meshcore_hub/web/templates/map.html b/src/meshcore_hub/web/templates/map.html deleted file mode 100644 index 5463c92..0000000 --- a/src/meshcore_hub/web/templates/map.html +++ /dev/null @@ -1,91 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Map - {{ network_name }}{% endblock %} - -{% block content %} -
-

Map

-
- {% if timezone and timezone != 'UTC' %}{{ timezone }}{% endif %} - Loading... - -
-
- - -
-
-
-
- - -
-
- - -
-
- - -
-
- -
- -
-
-
- -
-
-
-
-
- - -
- Legend: -
-
- Infrastructure -
-
-
- Public -
-
- -
-

Nodes are placed on the map based on GPS coordinates from node reports or manual tags.

-
-{% endblock %} - -{% block extra_scripts %} - - -{% endblock %} diff --git a/src/meshcore_hub/web/templates/members.html b/src/meshcore_hub/web/templates/members.html deleted file mode 100644 index 593e896..0000000 --- a/src/meshcore_hub/web/templates/members.html +++ /dev/null @@ -1,104 +0,0 @@ -{% extends "base.html" %} -{% from "macros/icons.html" import icon_info %} - -{% block title %}Members - {{ network_name }}{% endblock %} - -{% block content %} -
-

Members

- {{ members|length }} members -
- -{% if members %} -
- {% for member in members %} -
-
-

- {{ member.name }} - {% if member.callsign %} - {{ member.callsign }} - {% endif %} -

- - {% if member.description %} -

{{ member.description }}

- {% endif %} - - {% if member.contact %} -

- Contact: {{ member.contact }} -

- {% endif %} - - {% if member.nodes %} - - {% endif %} -
-
- {% endfor %} -
-{% else %} -
- {{ icon_info("stroke-current shrink-0 h-6 w-6") }} -
-

No members configured

-

To display network members, create a members.yaml file in your seed directory.

-
-
- -
-
-

Members File Format

-

Create a YAML file at $SEED_HOME/members.yaml with the following structure:

-
members:
-  - member_id: johndoe
-    name: John Doe
-    callsign: AB1CD
-    role: Network Admin
-    description: Manages the main repeater node.
-    contact: john@example.com
-  - member_id: janesmith
-    name: Jane Smith
-    role: Member
-    description: Regular user in the downtown area.
-

- Run meshcore-hub collector seed to import members.
- To associate nodes with members, add a member_id tag to nodes in node_tags.yaml. -

-
-
-{% endif %} -{% endblock %} diff --git a/src/meshcore_hub/web/templates/messages.html b/src/meshcore_hub/web/templates/messages.html deleted file mode 100644 index 882928e..0000000 --- a/src/meshcore_hub/web/templates/messages.html +++ /dev/null @@ -1,149 +0,0 @@ -{% extends "base.html" %} -{% from "_macros.html" import pagination %} -{% from "macros/icons.html" import icon_alert %} - -{% block title %}Messages - {{ network_name }}{% endblock %} - -{% block content %} -
-

Messages

-
- {% if timezone and timezone != 'UTC' %}{{ timezone }}{% endif %} - {{ total }} total -
-
- -{% if api_error %} -
- {{ icon_alert("stroke-current shrink-0 h-6 w-6") }} - Could not fetch data from API: {{ api_error }} -
-{% endif %} - - -
-
-
-
- - -
-
- - Clear -
-
-
-
- - -
- {% for msg in messages %} -
-
-
-
- - {% if msg.message_type == 'channel' %}📻{% else %}👤{% endif %} - -
-
- {% if msg.message_type == 'channel' %} - Public - {% else %} - {% if msg.sender_tag_name or msg.sender_name %} - {{ msg.sender_tag_name or msg.sender_name }} - {% else %} - {{ (msg.pubkey_prefix or '-')[:12] }} - {% endif %} - {% endif %} -
-
- {{ msg.received_at|localtime_short }} -
-
-
-
- {% if msg.receivers and msg.receivers|length >= 1 %} -
- {% for recv in msg.receivers %} - 📡 - {% endfor %} -
- {% elif msg.received_by %} - 📡 - {% endif %} -
-
-

{{ msg.text or '-' }}

-
-
- {% else %} -
No messages found.
- {% endfor %} -
- - - - -{{ pagination(page, total_pages, {"message_type": message_type, "limit": limit}) }} -{% endblock %} diff --git a/src/meshcore_hub/web/templates/node_detail.html b/src/meshcore_hub/web/templates/node_detail.html deleted file mode 100644 index 3a2269b..0000000 --- a/src/meshcore_hub/web/templates/node_detail.html +++ /dev/null @@ -1,280 +0,0 @@ -{% extends "base.html" %} -{% from "macros/icons.html" import icon_alert, icon_error %} - -{% block title %}{% if node %}{{ node.name or ('Node ' ~ public_key[:8] ~ '...') }} - {{ network_name }}{% else %}Node Not Found - {{ network_name }}{% endif %}{% endblock %} - -{% block extra_head %} - -{% endblock %} - -{% block content %} - - -{% if api_error %} -
- {{ icon_alert("stroke-current shrink-0 h-6 w-6") }} - Could not fetch data from API: {{ api_error }} -
-{% endif %} - -{% if node %} -{# Get display name from tag or node.name #} -{% set ns = namespace(tag_name=none) %} -{% for tag in node.tags or [] %} - {% if tag.key == 'name' %} - {% set ns.tag_name = tag.value %} - {% endif %} -{% endfor %} -{% set display_name = ns.tag_name or node.name or 'Unnamed Node' %} - -{# Get coordinates from node model first, then fall back to tags (bug fix) #} -{% set ns_coords = namespace(lat=node.lat, lon=node.lon) %} -{% if not ns_coords.lat or not ns_coords.lon %} - {% for tag in node.tags or [] %} - {% if tag.key == 'lat' and not ns_coords.lat %} - {% set ns_coords.lat = tag.value|float %} - {% elif tag.key == 'lon' and not ns_coords.lon %} - {% set ns_coords.lon = tag.value|float %} - {% endif %} - {% endfor %} -{% endif %} -{% set has_coords = ns_coords.lat is not none and ns_coords.lon is not none %} - -{# Node type emoji #} -{% set type_emoji = '📍' %} -{% if node.adv_type %} - {% if node.adv_type|lower == 'chat' %} - {% set type_emoji = '💬' %} - {% elif node.adv_type|lower == 'repeater' %} - {% set type_emoji = '📡' %} - {% elif node.adv_type|lower == 'room' %} - {% set type_emoji = '🪧' %} - {% endif %} -{% endif %} - - -

- {{ type_emoji }} - {{ display_name }} -

- - -{% if has_coords %} -
- -
- - -
-
-
-
-{% else %} - -
-
-
-

Scan to add as contact

-
-
-{% endif %} - - -
-
- -
-

Public Key

- {{ node.public_key }} -
- - -
-
- First seen: - {{ node.first_seen|localtime }} -
-
- Last seen: - {{ node.last_seen|localtime }} -
- {% if has_coords %} -
- Location: - {{ ns_coords.lat }}, {{ ns_coords.lon }} -
- {% endif %} -
-
-
- -
- -
-
-

Recent Advertisements

- {% if advertisements %} -
- - - - - - - - - - {% for adv in advertisements %} - - - - - - {% endfor %} - -
TimeTypeReceived By
{{ adv.received_at|localtime }} - {% if adv.adv_type and adv.adv_type|lower == 'chat' %} - 💬 - {% elif adv.adv_type and adv.adv_type|lower == 'repeater' %} - 📡 - {% elif adv.adv_type and adv.adv_type|lower == 'room' %} - 🪧 - {% elif adv.adv_type %} - 📍 - {% else %} - - - {% endif %} - - {% if adv.received_by %} - - {% if adv.receiver_tag_name or adv.receiver_name %} -
{{ adv.receiver_tag_name or adv.receiver_name }}
-
{{ adv.received_by[:16] }}...
- {% else %} - {{ adv.received_by[:16] }}... - {% endif %} -
- {% else %} - - - {% endif %} -
-
- {% else %} -

No advertisements recorded.

- {% endif %} -
-
- - -
-
-

Tags

- {% if node.tags %} -
- - - - - - - - - - {% for tag in node.tags %} - - - - - - {% endfor %} - -
KeyValueType
{{ tag.key }}{{ tag.value }}{{ tag.value_type or 'string' }}
-
- {% else %} -

No tags defined.

- {% endif %} - {% if admin_enabled and is_authenticated %} - - {% endif %} -
-
-
- -{% else %} -
- {{ icon_error("stroke-current shrink-0 h-6 w-6") }} - Node not found: {{ public_key }} -
-Back to Nodes -{% endif %} -{% endblock %} - -{% block extra_scripts %} -{% if node %} -{% set ns_qr = namespace(tag_name=none) %} -{% for tag in node.tags or [] %} - {% if tag.key == 'name' %} - {% set ns_qr.tag_name = tag.value %} - {% endif %} -{% endfor %} - - - -{# Get coordinates from node model first, then fall back to tags #} -{% set ns_map = namespace(lat=node.lat, lon=node.lon, name=none) %} -{% if not ns_map.lat or not ns_map.lon %} - {% for tag in node.tags or [] %} - {% if tag.key == 'lat' and not ns_map.lat %} - {% set ns_map.lat = tag.value|float %} - {% elif tag.key == 'lon' and not ns_map.lon %} - {% set ns_map.lon = tag.value|float %} - {% endif %} - {% endfor %} -{% endif %} -{% for tag in node.tags or [] %} - {% if tag.key == 'name' %} - {% set ns_map.name = tag.value %} - {% endif %} -{% endfor %} -{% if ns_map.lat and ns_map.lon %} - - -{% endif %} -{% endif %} -{% endblock %} diff --git a/src/meshcore_hub/web/templates/nodes.html b/src/meshcore_hub/web/templates/nodes.html deleted file mode 100644 index 878b984..0000000 --- a/src/meshcore_hub/web/templates/nodes.html +++ /dev/null @@ -1,179 +0,0 @@ -{% extends "base.html" %} -{% from "_macros.html" import pagination %} -{% from "macros/icons.html" import icon_alert %} - -{% block title %}Nodes - {{ network_name }}{% endblock %} - -{% block content %} -
-

Nodes

-
- {% if timezone and timezone != 'UTC' %}{{ timezone }}{% endif %} - {{ total }} total -
-
- -{% if api_error %} -
- {{ icon_alert("stroke-current shrink-0 h-6 w-6") }} - Could not fetch data from API: {{ api_error }} -
-{% endif %} - - -
-
-
-
- - -
-
- - -
- {% if members %} -
- - -
- {% endif %} -
- - Clear -
-
-
-
- - -
- {% for node in nodes %} - {% set ns = namespace(tag_name=none) %} - {% for tag in node.tags or [] %} - {% if tag.key == 'name' %} - {% set ns.tag_name = tag.value %} - {% endif %} - {% endfor %} - -
-
-
- {% if node.adv_type and node.adv_type|lower == 'chat' %}💬{% elif node.adv_type and node.adv_type|lower == 'repeater' %}📡{% elif node.adv_type and node.adv_type|lower == 'room' %}🪧{% else %}📍{% endif %} -
- {% if ns.tag_name or node.name %} -
{{ ns.tag_name or node.name }}
-
{{ node.public_key[:16] }}...
- {% else %} -
{{ node.public_key[:16] }}...
- {% endif %} -
-
-
-
- {% if node.last_seen %} - {{ node.last_seen|localdate }} - {% else %} - - - {% endif %} -
- {% if node.tags %} -
- {% for tag in node.tags[:2] %} - {{ tag.key }} - {% endfor %} - {% if node.tags|length > 2 %} - +{{ node.tags|length - 2 }} - {% endif %} -
- {% endif %} -
-
-
-
- {% else %} -
No nodes found.
- {% endfor %} -
- - - - -{{ pagination(page, total_pages, {"search": search, "adv_type": adv_type, "member_id": member_id, "limit": limit}) }} -{% endblock %} diff --git a/src/meshcore_hub/web/templates/page.html b/src/meshcore_hub/web/templates/page.html deleted file mode 100644 index 93bd3a0..0000000 --- a/src/meshcore_hub/web/templates/page.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{{ page.title }} - {{ network_name }}{% endblock %} - -{% block meta_description %}{{ page.title }} - {{ network_name }}{% endblock %} - -{% block content %} -
-
-
- {{ page.content_html | safe }} -
-
-
-{% endblock %}