63 lines
2.2 KiB
TypeScript
63 lines
2.2 KiB
TypeScript
import React from 'react';
|
|
import { Badge, Card, Table } from 'react-bootstrap';
|
|
import Full from '../../components/Full';
|
|
import { nodeTypeNameByValue } from './MeshCoreData';
|
|
import { useMeshCoreData } from './MeshCoreContext';
|
|
|
|
const MeshCoreMapView: React.FC = () => {
|
|
const { mapPoints, streamReady } = useMeshCoreData();
|
|
|
|
return (
|
|
<Full className="meshcore-map-view">
|
|
<Card className="meshcore-table-card h-100 d-flex flex-column">
|
|
<Card.Header className="meshcore-table-header d-flex justify-content-between align-items-center">
|
|
<span>Node Map</span>
|
|
<Badge bg={streamReady ? 'success' : 'secondary'}>{streamReady ? 'stream ready' : 'stream offline'}</Badge>
|
|
</Card.Header>
|
|
<Card.Body className="meshcore-table-body d-flex flex-column gap-3">
|
|
<div className="meshcore-map-canvas">
|
|
{mapPoints.map((point) => (
|
|
<div
|
|
key={point.nodeId}
|
|
className="meshcore-map-dot"
|
|
style={{
|
|
left: `${((point.longitude - 4.4) / 1.2) * 100}%`,
|
|
top: `${100 - ((point.latitude - 51.6) / 0.8) * 100}%`,
|
|
}}
|
|
title={`Node ${point.nodeId}`}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
<div className="meshcore-table-scroll">
|
|
<Table responsive size="sm" className="meshcore-table mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th>Node</th>
|
|
<th>Type</th>
|
|
<th>Packets</th>
|
|
<th>Latitude</th>
|
|
<th>Longitude</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{mapPoints.map((point) => (
|
|
<tr key={point.nodeId}>
|
|
<td>{point.nodeId}</td>
|
|
<td>{nodeTypeNameByValue[point.nodeType] ?? point.nodeType}</td>
|
|
<td>{point.packetCount}</td>
|
|
<td>{point.latitude.toFixed(4)}</td>
|
|
<td>{point.longitude.toFixed(4)}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</Table>
|
|
</div>
|
|
</Card.Body>
|
|
</Card>
|
|
</Full>
|
|
);
|
|
};
|
|
|
|
export default MeshCoreMapView;
|