Fix jwt-token
This commit is contained in:
@@ -148,7 +148,7 @@ const MapView = () => {
|
||||
10: "DJI Mavic",
|
||||
11: "DJI Phantom",
|
||||
20: "DJI Mini",
|
||||
99: "Unknown"
|
||||
99: t('map.unknown')
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -788,14 +788,14 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h4 className="font-semibold text-red-700 flex items-center space-x-1">
|
||||
<span>🚨</span>
|
||||
<span>Drone Detection Details</span>
|
||||
<span>{t('map.droneDetectionDetails')}</span>
|
||||
</h4>
|
||||
<span className={`px-2 py-1 rounded-full text-xs font-medium ${
|
||||
age < 1 ? 'bg-red-100 text-red-800' :
|
||||
age < 3 ? 'bg-orange-100 text-orange-800' :
|
||||
'bg-gray-100 text-gray-800'
|
||||
}`}>
|
||||
{age < 1 ? 'LIVE' : `${Math.round(age)}m ago`}
|
||||
{ age < 1 ? t('map.live') : `${Math.round(age)}m ago`}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -804,11 +804,11 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
<div className="bg-gray-50 rounded-lg p-2">
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Drone ID:</span>
|
||||
<span className="font-medium text-gray-700">{t('map.droneId')}:</span>
|
||||
<div className="text-gray-900 font-mono">{detection.drone_id}</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Type:</span>
|
||||
<span className="font-medium text-gray-700">{t('map.type')}:</span>
|
||||
<div className="text-gray-900">
|
||||
{droneTypes[detection.drone_type] || `Type ${detection.drone_type}`}
|
||||
</div>
|
||||
@@ -822,7 +822,7 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
|
||||
<div className="grid grid-cols-2 gap-2 mt-2">
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">RSSI:</span>
|
||||
<span className="font-medium text-gray-700">{t('map.rssi')}:</span>
|
||||
<div className={`font-mono ${
|
||||
detection.rssi > -50 ? 'text-red-600' :
|
||||
detection.rssi > -70 ? 'text-orange-600' :
|
||||
@@ -832,7 +832,7 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Frequency:</span>
|
||||
<span className="font-medium text-gray-700">{t('map.frequency')}:</span>
|
||||
<div className="text-gray-900">{detection.freq}MHz</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -840,10 +840,10 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
|
||||
{/* Detection Timeline */}
|
||||
<div className="border-t border-gray-200 pt-2">
|
||||
<span className="font-medium text-gray-700 block mb-2">Detection Timeline:</span>
|
||||
<span className="font-medium text-gray-700 block mb-2">{t('map.detectionTimeline')}:</span>
|
||||
<div className="text-xs space-y-1">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">First detected:</span>
|
||||
<span className="text-gray-600">{t('map.firstDetected')}:</span>
|
||||
<span className="font-mono text-gray-900">
|
||||
{(() => {
|
||||
const timestamp = firstDetection.device_timestamp || firstDetection.timestamp || firstDetection.server_timestamp;
|
||||
@@ -854,12 +854,12 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
} catch (e) {
|
||||
console.warn('Invalid firstDetection timestamp:', timestamp, e);
|
||||
}
|
||||
return 'Unknown';
|
||||
return t('map.unknown');
|
||||
})()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">Latest detection:</span>
|
||||
<span className="text-gray-600">{t('map.latestDetection')}:</span>
|
||||
<span className="font-mono text-gray-900">
|
||||
{(() => {
|
||||
const timestamp = detection.device_timestamp || detection.timestamp || detection.server_timestamp;
|
||||
@@ -870,13 +870,13 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
} catch (e) {
|
||||
console.warn('Invalid detection timestamp:', timestamp, e);
|
||||
}
|
||||
return 'Unknown';
|
||||
return t('map.unknown');
|
||||
})()}
|
||||
</span>
|
||||
</div>
|
||||
{droneHistory.length > 1 && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600">Total detections:</span>
|
||||
<span className="text-gray-600">{t('map.totalDetections')}:</span>
|
||||
<span className="font-medium text-gray-900">{droneHistory.length}</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -886,7 +886,7 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
{/* Movement Analysis */}
|
||||
{movementTrend && (
|
||||
<div className="border-t border-gray-200 pt-2">
|
||||
<span className="font-medium text-gray-700 block mb-2">Movement Analysis:</span>
|
||||
<span className="font-medium text-gray-700 block mb-2">{t('map.movementAnalysis')}:</span>
|
||||
<div className="text-xs space-y-2">
|
||||
<div className={`px-2 py-1 rounded ${
|
||||
movementTrend.trend === 'APPROACHING' ? 'bg-red-100 text-red-800' :
|
||||
@@ -894,19 +894,19 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
'bg-yellow-100 text-yellow-800'
|
||||
}`}>
|
||||
<div className="font-medium">
|
||||
{movementTrend.trend === 'APPROACHING' ? '⚠️ APPROACHING' :
|
||||
movementTrend.trend === 'RETREATING' ? '✅ RETREATING' :
|
||||
'➡️ STABLE POSITION'}
|
||||
{movementTrend.trend === 'APPROACHING' ? `⚠️ ${t('map.approaching')}` :
|
||||
movementTrend.trend === 'RETREATING' ? `✅ ${t('map.retreating')}` :
|
||||
`➡️ ${t('map.stablePosition')}`}
|
||||
</div>
|
||||
<div className="mt-1">
|
||||
RSSI change: {movementTrend.change > 0 ? '+' : ''}{typeof movementTrend.change === 'number' ? movementTrend.change.toFixed(1) : 'N/A'}dB
|
||||
over {typeof movementTrend.duration === 'number' ? movementTrend.duration.toFixed(1) : 'N/A'} minutes
|
||||
{t('map.rssiChange')}: {movementTrend.change > 0 ? '+' : ''}{typeof movementTrend.change === 'number' ? movementTrend.change.toFixed(1) : 'N/A'}dB
|
||||
{t('map.over')} {typeof movementTrend.duration === 'number' ? movementTrend.duration.toFixed(1) : 'N/A'} {t('map.minutes')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Signal Strength History Graph (simplified) */}
|
||||
<div className="bg-gray-50 rounded p-2">
|
||||
<div className="text-gray-600 mb-1">Signal Strength Trend:</div>
|
||||
<div className="text-gray-600 mb-1">{t('map.signalStrengthTrend')}:</div>
|
||||
<div className="flex items-end space-x-1 h-8">
|
||||
{droneHistory.slice(0, 8).reverse().map((hist, idx) => {
|
||||
const height = Math.max(10, Math.min(32, (hist.rssi + 100) / 2)); // Scale -100 to 0 dBm to 10-32px
|
||||
@@ -934,7 +934,7 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 mt-1">Last 8 detections (oldest to newest)</div>
|
||||
<div className="text-xs text-gray-500 mt-1">{t('map.lastDetections')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -942,26 +942,26 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
|
||||
{/* Current Detection Details */}
|
||||
<div className="border-t border-gray-200 pt-2">
|
||||
<span className="font-medium text-gray-700 block mb-2">Current Detection:</span>
|
||||
<span className="font-medium text-gray-700 block mb-2">{t('map.currentDetection')}:</span>
|
||||
<div className="grid grid-cols-2 gap-2 text-xs">
|
||||
<div>
|
||||
<span className="text-gray-600">Confidence:</span>
|
||||
<span className="text-gray-600">{t('map.confidence')}:</span>
|
||||
<div className="text-gray-900">
|
||||
{typeof detection.confidence_level === 'number' ? (detection.confidence_level * 100).toFixed(0) : 'N/A'}%
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-gray-600">Duration:</span>
|
||||
<span className="text-gray-600">{t('map.duration')}:</span>
|
||||
<div className="text-gray-900">
|
||||
{typeof detection.signal_duration === 'number' ? (detection.signal_duration / 1000).toFixed(1) : 'N/A'}s
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-gray-600">Detector:</span>
|
||||
<div className="text-gray-900">Device {detection.device_id}</div>
|
||||
<span className="text-gray-600">{t('map.detector')}:</span>
|
||||
<div className="text-gray-900">{t('map.deviceName')} {detection.device_id}</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-gray-600">Location:</span>
|
||||
<span className="text-gray-600">{t('map.location')}:</span>
|
||||
<div className="text-gray-900 font-mono">
|
||||
{typeof detection.geo_lat === 'number' ? detection.geo_lat.toFixed(4) : 'N/A'}, {typeof detection.geo_lon === 'number' ? detection.geo_lon.toFixed(4) : 'N/A'}
|
||||
</div>
|
||||
@@ -972,7 +972,7 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
{/* Legacy movement analysis from detection */}
|
||||
{detection.movement_analysis && (
|
||||
<div className="border-t border-gray-200 pt-2">
|
||||
<span className="font-medium text-gray-700 block mb-1">Real-time Analysis:</span>
|
||||
<span className="font-medium text-gray-700 block mb-1">{t('map.realTimeAnalysis')}:</span>
|
||||
<div className="text-xs space-y-1">
|
||||
<div className={`px-2 py-1 rounded ${
|
||||
detection.movement_analysis.alertLevel >= 3 ? 'bg-red-100 text-red-800' :
|
||||
@@ -985,13 +985,15 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
|
||||
|
||||
{detection.movement_analysis.rssiTrend && (
|
||||
<div className="flex items-center space-x-2 mt-1">
|
||||
<span className="text-gray-600">Instant trend:</span>
|
||||
<span className="text-gray-600">{t('map.instantTrend')}:</span>
|
||||
<span className={`font-medium ${
|
||||
detection.movement_analysis.rssiTrend.trend === 'STRENGTHENING' ? 'text-red-600' :
|
||||
detection.movement_analysis.rssiTrend.trend === 'WEAKENING' ? 'text-green-600' :
|
||||
'text-gray-600'
|
||||
}`}>
|
||||
{detection.movement_analysis.rssiTrend.trend}
|
||||
{detection.movement_analysis.rssiTrend.trend === 'STRENGTHENING' ? t('map.strengthening') :
|
||||
detection.movement_analysis.rssiTrend.trend === 'WEAKENING' ? t('map.weakening') :
|
||||
detection.movement_analysis.rssiTrend.trend}
|
||||
{detection.movement_analysis.rssiTrend.change !== 0 && (
|
||||
<span className="ml-1">
|
||||
({detection.movement_analysis.rssiTrend.change > 0 ? '+' : ''}{typeof detection.movement_analysis.rssiTrend.change === 'number' ? detection.movement_analysis.rssiTrend.change.toFixed(1) : 'N/A'}dB)
|
||||
|
||||
@@ -314,7 +314,38 @@ const translations = {
|
||||
droneLabels: 'Drone ID labels shown',
|
||||
positionOffsets: 'Slight position offsets for visibility',
|
||||
ringSize: 'Ring size = estimated distance from detector',
|
||||
showDroneDetections: 'Show Drone Detections'
|
||||
showDroneDetections: 'Show Drone Detections',
|
||||
droneDetectionDetails: 'Drone Detection Details',
|
||||
live: 'LIVE',
|
||||
droneId: 'Drone ID',
|
||||
type: 'Type',
|
||||
rssi: 'RSSI',
|
||||
frequency: 'Frequency',
|
||||
detectionTimeline: 'Detection Timeline',
|
||||
firstDetected: 'First detected',
|
||||
latestDetection: 'Latest detection',
|
||||
currentDetection: 'Current Detection',
|
||||
confidence: 'Confidence',
|
||||
duration: 'Duration',
|
||||
detector: 'Detector',
|
||||
location: 'Location',
|
||||
realTimeAnalysis: 'Real-time Analysis',
|
||||
firstDetection: 'First detection',
|
||||
movementAnalysis: 'Movement Analysis',
|
||||
totalDetections: 'Total detections',
|
||||
signalStrengthTrend: 'Signal Strength Trend',
|
||||
lastDetections: 'Last 8 detections (oldest to newest)',
|
||||
approaching: 'APPROACHING',
|
||||
retreating: 'RETREATING',
|
||||
stablePosition: 'STABLE POSITION',
|
||||
rssiChange: 'RSSI change',
|
||||
over: 'over',
|
||||
minutes: 'minutes',
|
||||
instantTrend: 'Instant trend',
|
||||
strengthening: 'STRENGTHENING',
|
||||
weakening: 'WEAKENING',
|
||||
deviceName: 'Device',
|
||||
unknown: 'Unknown'
|
||||
},
|
||||
movementAlerts: {
|
||||
title: 'Movement Alerts',
|
||||
@@ -713,7 +744,38 @@ const translations = {
|
||||
droneLabels: 'Drönar-ID-etiketter visas',
|
||||
positionOffsets: 'Lätta positionsförskjutningar för synlighet',
|
||||
ringSize: 'Ringstorlek = uppskattad distans från detektor',
|
||||
showDroneDetections: 'Visa drönardetekteringar'
|
||||
showDroneDetections: 'Visa drönardetekteringar',
|
||||
droneDetectionDetails: 'Drönardetekteringsdetaljer',
|
||||
live: 'LIVE',
|
||||
droneId: 'Drönar-ID',
|
||||
type: 'Typ',
|
||||
rssi: 'RSSI',
|
||||
frequency: 'Frekvens',
|
||||
detectionTimeline: 'Detekteringstidslinje',
|
||||
firstDetected: 'Först detekterad',
|
||||
latestDetection: 'Senaste detektion',
|
||||
currentDetection: 'Aktuell detektion',
|
||||
confidence: 'Konfidensgrad',
|
||||
duration: 'Varaktighet',
|
||||
detector: 'Detektor',
|
||||
location: 'Plats',
|
||||
realTimeAnalysis: 'Realtidsanalys',
|
||||
firstDetection: 'Första detektion',
|
||||
movementAnalysis: 'Rörelseanalys',
|
||||
totalDetections: 'Totalt antal detektioner',
|
||||
signalStrengthTrend: 'Signalstyrketrend',
|
||||
lastDetections: 'Senaste 8 detektioner (äldsta till nyaste)',
|
||||
approaching: 'NÄRMAR SIG',
|
||||
retreating: 'DRAR SIG TILLBAKA',
|
||||
stablePosition: 'STABIL POSITION',
|
||||
rssiChange: 'RSSI-förändring',
|
||||
over: 'över',
|
||||
minutes: 'minuter',
|
||||
instantTrend: 'Omedelbar trend',
|
||||
strengthening: 'FÖRSTÄRKNING',
|
||||
weakening: 'FÖRSVAGNING',
|
||||
deviceName: 'Enhet',
|
||||
unknown: 'Okänd'
|
||||
},
|
||||
movementAlerts: {
|
||||
title: 'Rörelselarm',
|
||||
|
||||
Reference in New Issue
Block a user