Fix jwt-token
This commit is contained in:
@@ -63,7 +63,7 @@ const Devices = () => {
|
||||
};
|
||||
|
||||
const handleRejectDevice = async (deviceId) => {
|
||||
if (window.confirm('Are you sure you want to reject this device?')) {
|
||||
if (window.confirm(t('devices.confirmReject'))) {
|
||||
try {
|
||||
await api.post(`/devices/${deviceId}/approve`, { approved: false });
|
||||
fetchDevices();
|
||||
@@ -73,7 +73,7 @@ const Devices = () => {
|
||||
alert('Your session has expired. Please log in again.');
|
||||
return;
|
||||
}
|
||||
alert('Error rejecting device: ' + (error.response?.data?.message || error.message));
|
||||
alert(t('devices.errorRejecting') + ' ' + (error.response?.data?.message || error.message));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -103,12 +103,12 @@ const Devices = () => {
|
||||
};
|
||||
|
||||
const handleDeleteDevice = async (deviceId) => {
|
||||
if (window.confirm('Are you sure you want to deactivate this device?')) {
|
||||
if (window.confirm(t('devices.confirmDelete'))) {
|
||||
try {
|
||||
await api.delete(`/devices/${deviceId}`);
|
||||
fetchDevices();
|
||||
} catch (error) {
|
||||
console.error('Error deleting device:', error);
|
||||
console.error(t('devices.errorDeleting'), error);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -125,13 +125,13 @@ const Devices = () => {
|
||||
};
|
||||
|
||||
const getSignalStrength = (lastHeartbeat) => {
|
||||
if (!lastHeartbeat) return 'Unknown';
|
||||
if (!lastHeartbeat) return t('devices.unknown');
|
||||
|
||||
const timeSince = (new Date() - new Date(lastHeartbeat)) / 1000 / 60; // minutes
|
||||
if (timeSince < 5) return 'Strong';
|
||||
if (timeSince < 15) return 'Good';
|
||||
if (timeSince < 60) return 'Weak';
|
||||
return 'Lost';
|
||||
if (timeSince < 5) return t('devices.signalStrong');
|
||||
if (timeSince < 15) return t('devices.signalGood');
|
||||
if (timeSince < 60) return t('devices.signalWeak');
|
||||
return t('devices.signalLost');
|
||||
};
|
||||
|
||||
const filteredDevices = devices.filter(device => {
|
||||
@@ -162,7 +162,7 @@ const Devices = () => {
|
||||
{t('devices.description')}
|
||||
{pendingCount > 0 && (
|
||||
<span className="ml-2 px-2 py-1 text-xs font-medium bg-yellow-200 text-yellow-800 rounded-full">
|
||||
{pendingCount} pending approval
|
||||
{pendingCount} {t('devices.pendingApproval')}
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
@@ -187,7 +187,7 @@ const Devices = () => {
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
||||
}`}
|
||||
>
|
||||
All Devices ({devices.length})
|
||||
{t('devices.allDevices')} ({devices.length})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilter('approved')}
|
||||
@@ -197,7 +197,7 @@ const Devices = () => {
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
||||
}`}
|
||||
>
|
||||
Approved ({devices.filter(d => d.is_approved).length})
|
||||
{t('devices.approved')} ({devices.filter(d => d.is_approved).length})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilter('pending')}
|
||||
@@ -207,7 +207,7 @@ const Devices = () => {
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
||||
}`}
|
||||
>
|
||||
Pending Approval ({pendingCount})
|
||||
{t('devices.pendingApprovalTab')} ({pendingCount})
|
||||
{pendingCount > 0 && (
|
||||
<span className="absolute -top-1 -right-1 h-2 w-2 bg-yellow-400 rounded-full"></span>
|
||||
)}
|
||||
@@ -228,11 +228,11 @@ const Devices = () => {
|
||||
device.stats?.status === 'online' ? 'bg-green-400' : 'bg-red-400'
|
||||
}`} />
|
||||
<h4 className="text-lg font-medium text-gray-900">
|
||||
{device.name || `Device ${device.id}`}
|
||||
{device.name || `${t('devices.device')} ${device.id}`}
|
||||
</h4>
|
||||
{!device.is_approved && (
|
||||
<span className="px-2 py-1 text-xs font-medium bg-yellow-200 text-yellow-800 rounded-full">
|
||||
Needs Approval
|
||||
{t('devices.needsApproval')}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -254,25 +254,25 @@ const Devices = () => {
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">Status</span>
|
||||
<span className="text-sm text-gray-500">{t('devices.status')}</span>
|
||||
<span className={`px-2 py-1 rounded-full text-xs font-medium ${
|
||||
getStatusColor(device.stats?.status)
|
||||
}`}>
|
||||
{device.stats?.status || 'Unknown'}
|
||||
{device.stats?.status ? t(`devices.${device.stats.status}`) : t('devices.unknown')}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">Approval</span>
|
||||
<span className="text-sm text-gray-500">{t('devices.approval')}</span>
|
||||
<span className={`px-2 py-1 rounded-full text-xs font-medium ${
|
||||
device.is_approved ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'
|
||||
}`}>
|
||||
{device.is_approved ? 'Approved' : 'Pending'}
|
||||
{device.is_approved ? t('devices.approved') : t('devices.pending')}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">Device ID</span>
|
||||
<span className="text-sm text-gray-500">{t('devices.deviceId')}</span>
|
||||
<span className="text-sm font-medium text-gray-900">
|
||||
{device.id}
|
||||
</span>
|
||||
@@ -280,7 +280,7 @@ const Devices = () => {
|
||||
|
||||
{device.location_description && (
|
||||
<div className="flex items-start justify-between">
|
||||
<span className="text-sm text-gray-500">Location</span>
|
||||
<span className="text-sm text-gray-500">{t('devices.location')}</span>
|
||||
<span className="text-sm text-gray-900 text-right">
|
||||
{device.location_description}
|
||||
</span>
|
||||
@@ -289,7 +289,7 @@ const Devices = () => {
|
||||
|
||||
{(device.geo_lat && device.geo_lon) && (
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">Coordinates</span>
|
||||
<span className="text-sm text-gray-500">{t('devices.coordinates')}</span>
|
||||
<span className="text-sm text-gray-900">
|
||||
{device.geo_lat}, {device.geo_lon}
|
||||
</span>
|
||||
@@ -297,7 +297,7 @@ const Devices = () => {
|
||||
)}
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">Signal</span>
|
||||
<span className="text-sm text-gray-500">{t('devices.signal')}</span>
|
||||
<span className="text-sm text-gray-900">
|
||||
{getSignalStrength(device.last_heartbeat)}
|
||||
</span>
|
||||
@@ -305,7 +305,7 @@ const Devices = () => {
|
||||
|
||||
{device.stats && (
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">Detections (24h)</span>
|
||||
<span className="text-sm text-gray-500">{t('devices.detections24h')}</span>
|
||||
<span className={`text-sm font-medium ${
|
||||
device.stats.detections_24h > 0 ? 'text-red-600' : 'text-green-600'
|
||||
}`}>
|
||||
@@ -316,7 +316,7 @@ const Devices = () => {
|
||||
|
||||
{device.last_heartbeat && (
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">Last Seen</span>
|
||||
<span className="text-sm text-gray-500">{t('devices.lastSeen')}</span>
|
||||
<span className="text-sm text-gray-900">
|
||||
{format(new Date(device.last_heartbeat), 'MMM dd, HH:mm')}
|
||||
</span>
|
||||
@@ -325,7 +325,7 @@ const Devices = () => {
|
||||
|
||||
{device.firmware_version && (
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-500">Firmware</span>
|
||||
<span className="text-sm text-gray-500">{t('devices.firmware')}</span>
|
||||
<span className="text-sm text-gray-900">
|
||||
{device.firmware_version}
|
||||
</span>
|
||||
@@ -341,13 +341,13 @@ const Devices = () => {
|
||||
onClick={() => handleApproveDevice(device.id)}
|
||||
className="flex-1 text-xs bg-green-100 text-green-700 py-2 px-3 rounded hover:bg-green-200 transition-colors font-medium"
|
||||
>
|
||||
✓ Approve Device
|
||||
✓ {t('devices.approveDevice')}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleRejectDevice(device.id)}
|
||||
className="flex-1 text-xs bg-red-100 text-red-700 py-2 px-3 rounded hover:bg-red-200 transition-colors font-medium"
|
||||
>
|
||||
✗ Reject
|
||||
✗ {t('devices.reject')}
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
@@ -356,13 +356,13 @@ const Devices = () => {
|
||||
onClick={() => handleViewDetails(device)}
|
||||
className="flex-1 text-xs bg-gray-100 text-gray-700 py-2 px-3 rounded hover:bg-gray-200 transition-colors"
|
||||
>
|
||||
View Details
|
||||
{t('devices.viewDetails')}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleViewOnMap(device)}
|
||||
className="flex-1 text-xs bg-primary-100 text-primary-700 py-2 px-3 rounded hover:bg-primary-200 transition-colors"
|
||||
>
|
||||
View on Map
|
||||
{t('devices.viewOnMap')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -375,14 +375,14 @@ const Devices = () => {
|
||||
<div className="text-center py-12">
|
||||
<ServerIcon className="mx-auto h-12 w-12 text-gray-400" />
|
||||
<h3 className="mt-2 text-sm font-medium text-gray-900">
|
||||
No {filter === 'all' ? '' : filter} devices
|
||||
{filter === 'all' ? t('devices.noDevices') : `${t('devices.noDevicesFiltered').replace('the current filter', filter)}`}
|
||||
</h3>
|
||||
<p className="mt-1 text-sm text-gray-500">
|
||||
{filter === 'pending'
|
||||
? 'No devices are currently pending approval.'
|
||||
? t('devices.noDevicesPending')
|
||||
: filter === 'approved'
|
||||
? 'No devices have been approved yet.'
|
||||
: 'No devices match the current filter.'
|
||||
? t('devices.noDevicesApproved')
|
||||
: t('devices.noDevicesFiltered')
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
@@ -391,9 +391,9 @@ const Devices = () => {
|
||||
{devices.length === 0 && (
|
||||
<div className="text-center py-12">
|
||||
<ServerIcon className="mx-auto h-12 w-12 text-gray-400" />
|
||||
<h3 className="mt-2 text-sm font-medium text-gray-900">No devices</h3>
|
||||
<h3 className="mt-2 text-sm font-medium text-gray-900">{t('devices.noDevices')}</h3>
|
||||
<p className="mt-1 text-sm text-gray-500">
|
||||
Get started by adding your first drone detection device.
|
||||
{t('devices.noDevicesDescription')}
|
||||
</p>
|
||||
<div className="mt-6">
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user