PHP Classes

File: templates/meshcore_nodes.twig

Recommend this page to a friend!
  Packages of Matthew Asham   Binkterm PHP   templates/meshcore_nodes.twig   Download  
File: templates/meshcore_nodes.twig
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Binkterm PHP
Bulletin board system based on the Web
Author: By
Last change:
Date: 5 days ago
Size: 6,360 bytes
 

Contents

Class file image Download
{% extends "base.twig" %} {% block title %}{{ t('ui.meshcore_nodes.page_title', {}, 'common') }} - {{ parent() }}{% endblock %} {% block head %} <link rel="stylesheet" href="/assets/leaflet/leaflet.css"> <link rel="stylesheet" href="/assets/leaflet/MarkerCluster.css"> <link rel="stylesheet" href="/assets/leaflet/MarkerCluster.Default.css"> <style> .packetbbs-node-link { cursor: pointer; text-decoration: none; } .packetbbs-node-link:hover, .packetbbs-node-link:focus { text-decoration: underline; } #meshcoreNodesMap { height: 420px; min-height: 300px; border: 1px solid rgba(148, 163, 184, 0.2); border-radius: 0.5rem; background: #111827; } #meshcoreNodesMap .leaflet-tile-pane { filter: grayscale(0.45) saturate(0.45) brightness(0.38) contrast(1.28); } #meshcoreNodesMap .leaflet-popup-content-wrapper, #meshcoreNodesMap .leaflet-popup-tip { background: #111827; color: #e2e8f0; } #meshcoreNodesMap .leaflet-popup-content a { color: #93c5fd; } #meshcoreNodesMap .leaflet-control-container .leaflet-bar a, #meshcoreNodesMap .leaflet-control-zoom a { background: rgba(15, 23, 42, 0.92); color: #e2e8f0; border-bottom-color: rgba(148, 163, 184, 0.18); } </style> {% endblock %} {% block content %} <div class="container"> <div class="d-flex justify-content-between align-items-center pt-3 pb-2 mb-3 border-bottom"> <h1 class="h2"> <i class="fas fa-broadcast-tower me-2"></i>{{ t('ui.meshcore_nodes.page_title', {}, 'common') }} </h1> </div> <p class="lead mb-4">{{ t('ui.meshcore_nodes.page_intro', {}, 'common') }}</p> {% if mappable_nodes | length > 0 %} <div class="card mb-4"> <div class="card-body p-0"> <div id="meshcoreNodesMap"></div> </div> </div> {% endif %} <div class="card"> <div class="card-header"> <strong>{{ t('ui.meshcore_nodes.registered_nodes', {}, 'common') }}</strong> </div> <div class="card-body p-0"> {% if nodes | length == 0 %} <p class="text-muted text-center py-4">{{ t('ui.meshcore_nodes.none_registered', {}, 'common') }}</p> {% else %} <div class="table-responsive"> <table class="table table-hover mb-0"> <thead class="table-dark"> <tr> <th>{{ t('ui.meshcore_nodes.col_name', {}, 'common') }}</th> <th>{{ t('ui.meshcore_nodes.col_network_type', {}, 'common') }}</th> <th>{{ t('ui.meshcore_nodes.col_location', {}, 'common') }}</th> <th></th> </tr> </thead> <tbody> {% for node in nodes %} <tr> <td> <strong> <a href="#" class="packetbbs-node-link" onclick="openMeshcoreNodeModal({{ node.id }}); return false;"> {{ node.handle | default('?') | e }} </a> </strong> </td> <td> {% if node.interface_type %} <span class="badge bg-secondary">{{ node.interface_type | e }}</span> {% else %} <span class="text-muted">?</span> {% endif %} </td> <td> {% if node.location %} <span class="small">{{ node.location | e }}</span> {% else %} <span class="text-muted">{{ t('ui.meshcore_nodes.no_location', {}, 'common') }}</span> {% endif %} </td> </tr> {% endfor %} </tbody> </table> </div> {% endif %} </div> </div> </div> {% include 'partials/meshcore_node_info_modal.twig' %} {% endblock %} {% block scripts %} <script src="/assets/leaflet/leaflet.js"></script> <script src="/assets/leaflet/leaflet.markercluster.js"></script> <script src="/js/meshcore-node-info.js"></script> <script> (function () { const mappableNodes = {{ mappable_nodes | json_encode | raw }}; if (mappableNodes.length > 0 && document.getElementById('meshcoreNodesMap')) { const map = L.map('meshcoreNodesMap'); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>' }).addTo(map); const markers = L.markerClusterGroup(); mappableNodes.forEach(function (node) { const lat = parseFloat(node.lat); const lon = parseFloat(node.lon); const name = node.handle || node.node_id_prefix || '?'; const prefix = node.node_id_prefix || ''; const popup = L.popup().setContent( '<strong>' + name + '</strong>' + (prefix ? '<br><code class="small">' + prefix + '?</code>' : '') + '<br><a href="#" onclick="openMeshcoreNodeModal(' + node.id + ');return false;">' + window.t('ui.meshcore_nodes.more_info', {}, 'More info') + '</a>' ); const marker = L.marker([lat, lon]).bindPopup(popup); markers.addLayer(marker); }); map.addLayer(markers); map.fitBounds(markers.getBounds(), { padding: [30, 30], maxZoom: 13 }); } // Auto-open node modal when page is loaded with a #node-{id} hash. const hashMatch = window.location.hash.match(/^#node-(\d+)$/); if (hashMatch) { openMeshcoreNodeModal(parseInt(hashMatch[1], 10)); } })(); </script> {% endblock %}