Fix jwt-token

This commit is contained in:
2025-09-23 09:35:30 +02:00
parent 3412aadb9c
commit 1905306a9b
3 changed files with 76 additions and 35 deletions

View File

@@ -1334,7 +1334,7 @@ const AlertDetailsModal = ({ alert, parseErrorMessage, onClose }) => {
<div className="text-gray-600 break-all">{alert.recipient}</div> <div className="text-gray-600 break-all">{alert.recipient}</div>
</div> </div>
<div> <div>
<span className="font-medium text-gray-700">Retry Count:</span> <span className="font-medium text-gray-700">{t('alerts.retryCount')}:</span>
<div className="text-gray-600">{alert.retry_count}</div> <div className="text-gray-600">{alert.retry_count}</div>
</div> </div>
<div> <div>

View File

@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import api from '../services/api'; import api from '../services/api';
import { format } from 'date-fns'; import { format } from 'date-fns';
import { formatFrequency } from '../utils/formatFrequency'; import { formatFrequency } from '../utils/formatFrequency';
import { t } from '../utils/tempTranslations'; // Temporary translation system import { useTranslation } from '../utils/tempTranslations';
import { import {
MagnifyingGlassIcon, MagnifyingGlassIcon,
FunnelIcon, FunnelIcon,
@@ -10,6 +10,7 @@ import {
} from '@heroicons/react/24/outline'; } from '@heroicons/react/24/outline';
const Detections = () => { const Detections = () => {
const { t } = useTranslation();
const [detections, setDetections] = useState([]); const [detections, setDetections] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [pagination, setPagination] = useState({}); const [pagination, setPagination] = useState({});
@@ -85,7 +86,7 @@ const Detections = () => {
{t('detections.title')} {t('detections.title')}
</h3> </h3>
<p className="mt-1 text-sm text-gray-500"> <p className="mt-1 text-sm text-gray-500">
History of all drone detections from your devices {t('detections.description')}
</p> </p>
</div> </div>
<button <button
@@ -93,7 +94,7 @@ const Detections = () => {
className="btn btn-secondary flex items-center space-x-2" className="btn btn-secondary flex items-center space-x-2"
> >
<FunnelIcon className="h-4 w-4" /> <FunnelIcon className="h-4 w-4" />
<span>Filters</span> <span>{t('detections.filters')}</span>
</button> </button>
</div> </div>
@@ -103,12 +104,12 @@ const Detections = () => {
<div className="grid grid-cols-1 md:grid-cols-4 gap-4"> <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">
Device ID {t('detections.deviceId')}
</label> </label>
<input <input
type="number" type="text"
className="w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-primary-500 focus:border-primary-500" className="w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-primary-500 focus:border-primary-500"
placeholder="Device ID" placeholder={t('detections.deviceIdPlaceholder')}
value={filters.device_id} value={filters.device_id}
onChange={(e) => handleFilterChange('device_id', e.target.value)} onChange={(e) => handleFilterChange('device_id', e.target.value)}
/> />
@@ -116,12 +117,12 @@ const Detections = () => {
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">
Drone ID {t('detections.droneId')}
</label> </label>
<input <input
type="number" type="text"
className="w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-primary-500 focus:border-primary-500" className="w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-primary-500 focus:border-primary-500"
placeholder="Drone ID" placeholder={t('detections.droneIdPlaceholder')}
value={filters.drone_id} value={filters.drone_id}
onChange={(e) => handleFilterChange('drone_id', e.target.value)} onChange={(e) => handleFilterChange('drone_id', e.target.value)}
/> />
@@ -129,7 +130,7 @@ const Detections = () => {
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">
Start Date {t('detections.startDate')}
</label> </label>
<input <input
type="datetime-local" type="datetime-local"
@@ -141,7 +142,7 @@ const Detections = () => {
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label className="block text-sm font-medium text-gray-700 mb-1">
End Date {t('detections.endDate')}
</label> </label>
<input <input
type="datetime-local" type="datetime-local"
@@ -157,7 +158,7 @@ const Detections = () => {
onClick={clearFilters} onClick={clearFilters}
className="btn btn-secondary" className="btn btn-secondary"
> >
Clear Filters {t('detections.clearFilters')}
</button> </button>
</div> </div>
</div> </div>
@@ -175,14 +176,14 @@ const Detections = () => {
<table className="table"> <table className="table">
<thead> <thead>
<tr> <tr>
<th>Device</th> <th>{t('detections.device')}</th>
<th>Drone ID</th> <th>{t('detections.droneId')}</th>
<th>Type</th> <th>{t('detections.type')}</th>
<th>Frequency</th> <th>{t('detections.frequency')}</th>
<th>RSSI</th> <th>{t('detections.rssi')}</th>
<th>Location</th> <th>{t('detections.location')}</th>
<th>Detected At</th> <th>{t('detections.detectedAt')}</th>
<th>Actions</th> <th>{t('detections.actions')}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -231,7 +232,7 @@ const Detections = () => {
{detection.device?.location_description || {detection.device?.location_description ||
(detection.geo_lat && detection.geo_lon ? (detection.geo_lat && detection.geo_lon ?
`${detection.geo_lat}, ${detection.geo_lon}` : `${detection.geo_lat}, ${detection.geo_lon}` :
'Unknown')} t('detections.unknown'))}
</div> </div>
</td> </td>
<td> <td>
@@ -264,7 +265,7 @@ const Detections = () => {
<MagnifyingGlassIcon className="mx-auto h-12 w-12 text-gray-400" /> <MagnifyingGlassIcon className="mx-auto h-12 w-12 text-gray-400" />
<h3 className="mt-2 text-sm font-medium text-gray-900">{t('detections.noDetections')}</h3> <h3 className="mt-2 text-sm font-medium text-gray-900">{t('detections.noDetections')}</h3>
<p className="mt-1 text-sm text-gray-500"> <p className="mt-1 text-sm text-gray-500">
Try adjusting your search filters. {t('detections.tryAdjustingFilters')}
</p> </p>
</div> </div>
)} )}
@@ -278,29 +279,29 @@ const Detections = () => {
disabled={filters.offset === 0} disabled={filters.offset === 0}
className="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 disabled:opacity-50" className="relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 disabled:opacity-50"
> >
Previous {t('detections.previous')}
</button> </button>
<button <button
onClick={() => handlePageChange(filters.offset + filters.limit)} onClick={() => handlePageChange(filters.offset + filters.limit)}
disabled={filters.offset + filters.limit >= pagination.total} disabled={filters.offset + filters.limit >= pagination.total}
className="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 disabled:opacity-50" className="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 disabled:opacity-50"
> >
Next {t('detections.next')}
</button> </button>
</div> </div>
<div className="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between"> <div className="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
<div> <div>
<p className="text-sm text-gray-700"> <p className="text-sm text-gray-700">
Showing{' '} {t('detections.showing')} {' '}
<span className="font-medium">{filters.offset + 1}</span> <span className="font-medium">{filters.offset + 1}</span>
{' '}to{' '} {' '}{t('detections.to')}{' '}
<span className="font-medium"> <span className="font-medium">
{Math.min(filters.offset + filters.limit, pagination.total)} {Math.min(filters.offset + filters.limit, pagination.total)}
</span> </span>
{' '}of{' '} {' '}{t('detections.of')}{' '}
<span className="font-medium">{pagination.total}</span> <span className="font-medium">{pagination.total}</span>
{' '}results {' '}{t('detections.results')}
</p> </p>
</div> </div>
@@ -311,14 +312,14 @@ const Detections = () => {
disabled={filters.offset === 0} disabled={filters.offset === 0}
className="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 disabled:opacity-50" className="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 disabled:opacity-50"
> >
Previous {t('detections.previous')}
</button> </button>
<button <button
onClick={() => handlePageChange(filters.offset + filters.limit)} onClick={() => handlePageChange(filters.offset + filters.limit)}
disabled={filters.offset + filters.limit >= pagination.total} disabled={filters.offset + filters.limit >= pagination.total}
className="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 disabled:opacity-50" className="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50 disabled:opacity-50"
> >
Next {t('detections.next')}
</button> </button>
</nav> </nav>
</div> </div>

View File

@@ -89,7 +89,26 @@ const translations = {
showOnMap: 'Show on Map', showOnMap: 'Show on Map',
highConfidence: 'High Confidence', highConfidence: 'High Confidence',
mediumConfidence: 'Medium Confidence', mediumConfidence: 'Medium Confidence',
lowConfidence: 'Low Confidence' lowConfidence: 'Low Confidence',
filters: 'Filters',
deviceId: 'Device ID',
droneId: 'Drone ID',
startDate: 'Start Date',
endDate: 'End Date',
clearFilters: 'Clear Filters',
deviceIdPlaceholder: 'Enter device ID',
droneIdPlaceholder: 'Enter drone ID',
frequency: 'Frequency',
rssi: 'RSSI',
detectedAt: 'Detected At',
unknown: 'Unknown',
tryAdjustingFilters: 'Try adjusting your search filters.',
previous: 'Previous',
next: 'Next',
showing: 'Showing',
to: 'to',
of: 'of',
results: 'results'
}, },
devices: { devices: {
title: 'All Devices', title: 'All Devices',
@@ -323,7 +342,7 @@ const translations = {
multipleContacts: 'Multiple Contacts', multipleContacts: 'Multiple Contacts',
noDevicesFound: 'No devices found', noDevicesFound: 'No devices found',
mapLegend: 'Map Legend', mapLegend: 'Map Legend',
deviceDetecting: 'Device Detecting', deviceDetecting: 'Active Detection',
droneDetectionRings: 'Drone Detection Rings', droneDetectionRings: 'Drone Detection Rings',
ringsDescription: 'Rings show estimated detection range based on RSSI', ringsDescription: 'Rings show estimated detection range based on RSSI',
orlanMilitary: 'Military-drone (Always Critical)', orlanMilitary: 'Military-drone (Always Critical)',
@@ -512,6 +531,7 @@ const translations = {
channel: 'Channel', channel: 'Channel',
channels: 'Channels', channels: 'Channels',
status: 'Status', status: 'Status',
retryCount: 'Retry Count',
message: 'Message', message: 'Message',
detectionDetails: 'Detection Details', detectionDetails: 'Detection Details',
viewDetails: 'View Details', viewDetails: 'View Details',
@@ -769,7 +789,26 @@ const translations = {
showOnMap: 'Visa på karta', showOnMap: 'Visa på karta',
highConfidence: 'Hög säkerhet', highConfidence: 'Hög säkerhet',
mediumConfidence: 'Medel säkerhet', mediumConfidence: 'Medel säkerhet',
lowConfidence: 'Låg säkerhet' lowConfidence: 'Låg säkerhet',
filters: 'Filter',
deviceId: 'Enhets-ID',
droneId: 'Drönare-ID',
startDate: 'Startdatum',
endDate: 'Slutdatum',
clearFilters: 'Rensa filter',
deviceIdPlaceholder: 'Ange enhets-ID',
droneIdPlaceholder: 'Ange drönare-ID',
frequency: 'Frekvens',
rssi: 'RSSI',
detectedAt: 'Detekterad vid',
unknown: 'Okänd',
tryAdjustingFilters: 'Försök justera dina sökfilter.',
previous: 'Föregående',
next: 'Nästa',
showing: 'Visar',
to: 'till',
of: 'av',
results: 'resultat'
}, },
devices: { devices: {
title: 'Alla enheter', title: 'Alla enheter',
@@ -1003,7 +1042,7 @@ const translations = {
multipleContacts: 'Flera kontakter', multipleContacts: 'Flera kontakter',
noDevicesFound: 'Inga enheter hittades', noDevicesFound: 'Inga enheter hittades',
mapLegend: 'Kartteckenförklaring', mapLegend: 'Kartteckenförklaring',
deviceDetecting: 'Enhet detekterar', deviceDetecting: 'Aktiv detektion',
droneDetectionRings: 'Drönardetekteringsringar', droneDetectionRings: 'Drönardetekteringsringar',
ringsDescription: 'Ringar visar uppskattad detekteringsräckvidd baserat på RSSI', ringsDescription: 'Ringar visar uppskattad detekteringsräckvidd baserat på RSSI',
orlanMilitary: 'Militärdrönare (Alltid kritisk)', orlanMilitary: 'Militärdrönare (Alltid kritisk)',
@@ -1192,6 +1231,7 @@ const translations = {
channel: 'Kanal', channel: 'Kanal',
channels: 'Kanaler', channels: 'Kanaler',
status: 'Status', status: 'Status',
retryCount: 'Antal återförsök',
message: 'Meddelande', message: 'Meddelande',
detectionDetails: 'Detekteringsdetaljer', detectionDetails: 'Detekteringsdetaljer',
viewDetails: 'Visa detaljer', viewDetails: 'Visa detaljer',