Fix jwt-token

This commit is contained in:
2025-09-19 15:11:42 +02:00
parent 5d21bb5b0a
commit 2b4a7bf09e
2 changed files with 96 additions and 32 deletions

View File

@@ -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)

View File

@@ -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',