Fix jwt-token

This commit is contained in:
2025-09-07 16:51:38 +02:00
parent e2ab2782d2
commit 312a769cdb
2 changed files with 98 additions and 71 deletions

View File

@@ -233,37 +233,44 @@ const MapView = () => {
// Set initial bounds and center ONLY on first load // Set initial bounds and center ONLY on first load
if (deviceData.length > 0 && isInitialLoad) { if (deviceData.length > 0 && isInitialLoad) {
const lats = deviceData.map(device => device.geo_lat); // Filter devices that have coordinates
const lons = deviceData.map(device => device.geo_lon); const devicesWithCoords = deviceData.filter(device =>
device.geo_lat !== null && device.geo_lon !== null
);
const minLat = Math.min(...lats); if (devicesWithCoords.length > 0) {
const maxLat = Math.max(...lats); const lats = devicesWithCoords.map(device => device.geo_lat);
const minLon = Math.min(...lons); const lons = devicesWithCoords.map(device => device.geo_lon);
const maxLon = Math.max(...lons);
// Add padding around the bounds (15% on each side for better visibility) const minLat = Math.min(...lats);
const latPadding = (maxLat - minLat) * 0.15; const maxLat = Math.max(...lats);
const lonPadding = (maxLon - minLon) * 0.15; const minLon = Math.min(...lons);
const maxLon = Math.max(...lons);
const bounds = [ // Add padding around the bounds (15% on each side for better visibility)
[minLat - latPadding, minLon - lonPadding], // Southwest const latPadding = (maxLat - minLat) * 0.15;
[maxLat + latPadding, maxLon + lonPadding] // Northeast const lonPadding = (maxLon - minLon) * 0.15;
];
console.log('MapView: Setting initial bounds and center for devices'); const bounds = [
setMapBounds(bounds); [minLat - latPadding, minLon - lonPadding], // Southwest
setShouldFitBounds(true); [maxLat + latPadding, maxLon + lonPadding] // Northeast
];
// Calculate center console.log('MapView: Setting initial bounds and center for devices with coordinates');
const centerLat = (minLat + maxLat) / 2; setMapBounds(bounds);
const centerLon = (minLon + maxLon) / 2; setShouldFitBounds(true);
setMapCenter([centerLat, centerLon]);
// Disable automatic fitting after initial setup (with longer delay) // Calculate center
setTimeout(() => { const centerLat = (minLat + maxLat) / 2;
console.log('MapView: Disabling automatic bounds fitting - manual navigation now preserved'); const centerLon = (minLon + maxLon) / 2;
setShouldFitBounds(false); setMapCenter([centerLat, centerLon]);
}, 2000);
// Disable automatic fitting after initial setup (with longer delay)
setTimeout(() => {
console.log('MapView: Disabling automatic bounds fitting - manual navigation now preserved');
setShouldFitBounds(false);
}, 2000);
}
} }
// Always mark initial load as complete after first fetch // Always mark initial load as complete after first fetch
@@ -999,46 +1006,64 @@ const DroneDetectionPopup = ({ detection, age, droneTypes, droneDetectionHistory
); );
}; };
const DeviceListItem = ({ device, status, detections, onClick }) => ( const DeviceListItem = ({ device, status, detections, onClick }) => {
<div const hasCoordinates = device.geo_lat !== null && device.geo_lon !== null;
className="px-6 py-4 hover:bg-gray-50 cursor-pointer transition-colors"
onClick={onClick} return (
> <div
<div className="flex items-center justify-between"> className="px-6 py-4 hover:bg-gray-50 cursor-pointer transition-colors"
<div className="flex items-center space-x-3"> onClick={onClick}
<div className={`w-3 h-3 rounded-full ${ >
status === 'online' <div className="flex items-center justify-between">
? detections.length > 0 ? 'bg-red-400 animate-pulse' : 'bg-green-400' <div className="flex items-center space-x-3">
: 'bg-gray-400' <div className={`w-3 h-3 rounded-full ${
}`} /> status === 'online'
<div> ? detections.length > 0 ? 'bg-red-400 animate-pulse' : 'bg-green-400'
<div className="text-sm font-medium text-gray-900"> : 'bg-gray-400'
{device.name || `Device ${device.id}`} }`} />
</div> <div>
<div className="text-sm text-gray-500"> <div className="text-sm font-medium text-gray-900">
{device.location_description || `${device.geo_lat}, ${device.geo_lon}`} {device.name || `Device ${device.id}`}
</div>
<div className="text-sm text-gray-500">
{hasCoordinates
? (device.location_description || `${device.geo_lat}, ${device.geo_lon}`)
: (
<span className="text-amber-600 font-medium">
Coordinates missing - please add location
</span>
)
}
</div>
</div> </div>
</div> </div>
</div>
<div className="flex items-center space-x-4"> <div className="flex items-center space-x-4">
{detections.length > 0 && ( {!hasCoordinates && (
<div className="flex items-center space-x-1 text-red-600"> <div className="flex items-center space-x-1 text-amber-600">
<ExclamationTriangleIcon className="h-4 w-4" /> <ExclamationTriangleIcon className="h-4 w-4" />
<span className="text-sm font-medium">{detections.length}</span> <span className="text-xs font-medium">Incomplete</span>
</div> </div>
)} )}
<span className={`px-2 py-1 rounded-full text-xs font-medium ${ {detections.length > 0 && (
status === 'online' <div className="flex items-center space-x-1 text-red-600">
? 'bg-green-100 text-green-800' <ExclamationTriangleIcon className="h-4 w-4" />
: 'bg-red-100 text-red-800' <span className="text-sm font-medium">{detections.length}</span>
}`}> </div>
{status} )}
</span>
<span className={`px-2 py-1 rounded-full text-xs font-medium ${
status === 'online'
? 'bg-green-100 text-green-800'
: 'bg-red-100 text-red-800'
}`}>
{status}
</span>
</div>
</div> </div>
</div> </div>
</div> );
); };
export default MapView; export default MapView;

View File

@@ -137,11 +137,10 @@ router.get('/', authenticateToken, async (req, res) => {
// GET /api/devices/map - Get devices with location data for map display // GET /api/devices/map - Get devices with location data for map display
router.get('/map', authenticateToken, async (req, res) => { router.get('/map', authenticateToken, async (req, res) => {
try { try {
// Get all active devices, including those without coordinates
const devices = await Device.findAll({ const devices = await Device.findAll({
where: { where: {
is_active: true, is_active: true
geo_lat: { [Op.ne]: null },
geo_lon: { [Op.ne]: null }
}, },
attributes: [ attributes: [
'id', 'id',
@@ -153,7 +152,7 @@ router.get('/map', authenticateToken, async (req, res) => {
] ]
}); });
// Get recent detections for each device // Get recent detections for each device and mark coordinate status
const devicesWithDetections = await Promise.all(devices.map(async (device) => { const devicesWithDetections = await Promise.all(devices.map(async (device) => {
const recentDetections = await DroneDetection.count({ const recentDetections = await DroneDetection.count({
where: { where: {
@@ -170,12 +169,15 @@ router.get('/map', authenticateToken, async (req, res) => {
: null; : null;
const isOnline = timeSinceLastHeartbeat && timeSinceLastHeartbeat < 600; // 10 minutes const isOnline = timeSinceLastHeartbeat && timeSinceLastHeartbeat < 600; // 10 minutes
const hasCoordinates = device.geo_lat !== null && device.geo_lon !== null;
return { return {
...device.toJSON(), ...device.toJSON(),
has_recent_detections: recentDetections > 0, has_recent_detections: recentDetections > 0,
detection_count_10m: recentDetections, detection_count_10m: recentDetections,
status: isOnline ? 'online' : 'offline' status: isOnline ? 'online' : 'offline',
has_coordinates: hasCoordinates,
coordinate_status: hasCoordinates ? 'complete' : 'incomplete'
}; };
})); }));