Fix jwt-token

This commit is contained in:
2025-08-18 09:05:20 +02:00
parent b54249aa7b
commit d183b0248f

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import { MapContainer, TileLayer, Marker, Popup, Circle, useMap } from 'react-leaflet';
import { Icon } from 'leaflet';
import L from 'leaflet'; // For divIcon and other Leaflet utilities
import { useSocket } from '../contexts/SocketContext';
import api from '../services/api';
import { format } from 'date-fns';
@@ -310,75 +311,157 @@ const MapView = () => {
})}
{/* RSSI-based Detection Rings around Detectors */}
{showDroneDetections && droneDetectionHistory
.filter(detection => {
const hasCoords = detection.geo_lat && detection.geo_lon;
console.log('MapView: Filtering detection:', detection, 'hasCoords:', hasCoords);
return hasCoords;
})
.map(detection => {
console.log('MapView: Rendering ring for detection:', detection);
const opacity = getDetectionOpacity(detection);
const age = getDetectionAge(detection);
console.log('MapView: Detection age:', age, 'opacity:', opacity);
// Calculate ring radius based on RSSI (rough distance estimation)
const getRssiRadius = (rssi) => {
if (rssi > -40) return 100; // <100m - very close
if (rssi > -60) return 500; // ~500m - close
if (rssi > -70) return 1500; // ~1.5km - medium
if (rssi > -80) return 4000; // ~4km - far
if (rssi > -90) return 8000; // ~8km - very far
return 15000; // ~15km - maximum range
};
{showDroneDetections && (() => {
const filteredDetections = droneDetectionHistory
.filter(detection => {
const hasCoords = detection.geo_lat && detection.geo_lon;
console.log('MapView: Filtering detection:', detection, 'hasCoords:', hasCoords);
return hasCoords;
});
const radius = getRssiRadius(detection.rssi);
console.log('MapView: Ring radius:', radius, 'for RSSI:', detection.rssi);
// Color based on threat level and RSSI strength
const getRingColor = (rssi, droneType) => {
// Orlan drones (type 1) always red
if (droneType === 1) return '#dc2626'; // red-600
// Group detections by detector position to handle multiple drones at same detector
const detectionsByDetector = filteredDetections.reduce((acc, detection) => {
const key = `${detection.geo_lat}_${detection.geo_lon}`;
if (!acc[key]) acc[key] = [];
acc[key].push(detection);
return acc;
}, {});
return Object.entries(detectionsByDetector).flatMap(([detectorKey, detections]) => {
return detections.map((detection, droneIndex) => {
console.log('MapView: Rendering ring for detection:', detection, 'droneIndex:', droneIndex, 'totalDrones:', detections.length);
const opacity = getDetectionOpacity(detection);
const age = getDetectionAge(detection);
console.log('MapView: Detection age:', age, 'opacity:', opacity);
// Other drones based on RSSI
if (rssi > -60) return '#dc2626'; // red-600 - close
if (rssi > -70) return '#ea580c'; // orange-600 - medium
return '#16a34a'; // green-600 - far
};
// Calculate ring radius based on RSSI (rough distance estimation)
const getRssiRadius = (rssi) => {
if (rssi > -40) return 100; // <100m - very close
if (rssi > -60) return 500; // ~500m - close
if (rssi > -70) return 1500; // ~1.5km - medium
if (rssi > -80) return 4000; // ~4km - far
if (rssi > -90) return 8000; // ~8km - very far
return 15000; // ~15km - maximum range
};
const ringColor = getRingColor(detection.rssi, detection.drone_type);
return (
<React.Fragment key={detection.id}>
{/* Detection Ring around Detector (NOT drone position) */}
<Circle
center={[detection.geo_lat, detection.geo_lon]} // Detector position
radius={radius}
pathOptions={{
color: ringColor,
fillColor: ringColor,
fillOpacity: 0.05 * opacity,
weight: detection.drone_type === 1 ? 3 : 2, // Thicker for Orlan
opacity: opacity * 0.8,
dashArray: detection.drone_type === 1 ? null : '5, 5' // Solid for Orlan, dashed for others
}}
/>
const radius = getRssiRadius(detection.rssi);
console.log('MapView: Ring radius:', radius, 'for RSSI:', detection.rssi);
// Color based on threat level and RSSI strength
const getRingColor = (rssi, droneType) => {
// Orlan drones (type 1) always red
if (droneType === 1) return '#dc2626'; // red-600
{/* Optional: Small info marker at detector showing detection details */}
{age < 1 && ( // Only show for very recent detections (< 1 minute)
<Marker
position={[detection.geo_lat, detection.geo_lon]}
icon={createDroneIcon(detection.rssi, detection.drone_type)}
opacity={opacity * 0.7}
>
<Popup>
<DroneDetectionPopup detection={detection} age={age} droneTypes={droneTypes} />
</Popup>
</Marker>
)}
</React.Fragment>
);
})}
// Other drones based on RSSI
if (rssi > -60) return '#dc2626'; // red-600 - close
if (rssi > -70) return '#ea580c'; // orange-600 - medium
return '#16a34a'; // green-600 - far
};
const ringColor = getRingColor(detection.rssi, detection.drone_type);
// Different visual styles for multiple drones at same detector
const getDashPattern = (droneType, droneIndex, totalDrones) => {
if (droneType === 1) return null; // Orlan always solid
if (totalDrones === 1) return '5, 5'; // Single drone - normal dashed
// Multiple drones - different dash patterns
const patterns = [
'5, 5', // Standard dashed
'10, 3, 3, 3', // Long dash, dot, dot
'15, 5', // Long dashes
'3, 3', // Short dashes
'8, 3, 3, 3, 3, 3' // Complex pattern
];
return patterns[droneIndex % patterns.length];
};
// Slight offset for multiple rings to make them more visible
const getPositionOffset = (droneIndex, totalDrones) => {
if (totalDrones === 1) return [0, 0];
const offsetDistance = 0.0001; // Very small offset in degrees
const angle = (droneIndex * 360 / totalDrones) * (Math.PI / 180);
return [
Math.cos(angle) * offsetDistance,
Math.sin(angle) * offsetDistance
];
};
const totalDrones = detections.length;
const dashPattern = getDashPattern(detection.drone_type, droneIndex, totalDrones);
const [latOffset, lonOffset] = getPositionOffset(droneIndex, totalDrones);
return (
<React.Fragment key={`${detection.id}_${droneIndex}`}>
{/* Detection Ring around Detector (NOT drone position) */}
<Circle
center={[
detection.geo_lat + latOffset,
detection.geo_lon + lonOffset
]} // Detector position with slight offset
radius={radius}
pathOptions={{
color: ringColor,
fillColor: ringColor,
fillOpacity: totalDrones > 1 ? 0.02 * opacity : 0.05 * opacity, // Less fill for multiple
weight: detection.drone_type === 1 ? 3 : (totalDrones > 1 ? 3 : 2), // Thicker for multiple or Orlan
opacity: opacity * 0.8,
dashArray: dashPattern
}}
/>
{/* Drone ID label for multiple drones */}
{totalDrones > 1 && age < 5 && ( // Show labels for recent detections with multiple drones
<Marker
position={[
detection.geo_lat + (latOffset * 3),
detection.geo_lon + (lonOffset * 3)
]}
icon={L.divIcon({
html: `<div style="
background: ${ringColor};
color: white;
padding: 2px 6px;
border-radius: 10px;
font-size: 10px;
font-weight: bold;
text-align: center;
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
white-space: nowrap;
">
${detection.drone_id || `D${droneIndex + 1}`}
</div>`,
className: 'drone-id-label',
iconSize: [30, 16],
iconAnchor: [15, 8]
})}
opacity={opacity * 0.9}
>
<Popup>
<DroneDetectionPopup detection={detection} age={age} droneTypes={droneTypes} />
</Popup>
</Marker>
)}
{/* Optional: Small info marker at detector showing detection details (for single drone) */}
{totalDrones === 1 && age < 1 && ( // Only show for very recent detections (< 1 minute) and single drone
<Marker
position={[detection.geo_lat, detection.geo_lon]}
icon={createDroneIcon(detection.rssi, detection.drone_type)}
opacity={opacity * 0.7}
>
<Popup>
<DroneDetectionPopup detection={detection} age={age} droneTypes={droneTypes} />
</Popup>
</Marker>
)}
</React.Fragment>
);
});
});
})()}
</MapContainer>
{/* Map Legend - Fixed positioning and visibility */}
@@ -419,6 +502,12 @@ const MapView = () => {
<div className="w-3 h-3 border-2 border-green-500 rounded-full bg-green-500 bg-opacity-10"></div>
<span className="text-gray-700">Far Range (&lt;-70dBm)</span>
</div>
<div className="border-t border-gray-200 mt-2 pt-2">
<div className="text-xs text-gray-600 mb-1">Multiple Drones:</div>
<div className="text-xs text-gray-500 mb-1"> Different dash patterns</div>
<div className="text-xs text-gray-500 mb-1"> Drone ID labels shown</div>
<div className="text-xs text-gray-500 mb-1"> Slight position offsets</div>
</div>
<div className="text-xs text-gray-500 mt-2">
Ring size = estimated distance from detector
</div>