-
Detection Information
+
{t('alerts.detectionDetails')}
- Detection ID:
+ {t('debug.payloadViewer.detectionId')}
{selectedPayload.id}
- Device ID:
+ {t('debug.payloadViewer.deviceId')}
{selectedPayload.deviceId}
- Server Timestamp:
+ {t('debug.payloadViewer.timestamp')}
{format(new Date(selectedPayload.timestamp), 'yyyy-MM-dd HH:mm:ss')}
- Drone Type:
+ {t('debug.droneType')}
{selectedPayload.processedData.drone_type}
@@ -457,7 +459,7 @@ const Debug = () => {
{/* Processed Data */}
-
Processed Data
+
{t('debug.payloadViewer.processedData')}
{JSON.stringify(selectedPayload.processedData, null, 2)}
@@ -467,7 +469,7 @@ const Debug = () => {
{/* Raw Payload */}
-
Raw Payload from Detector
+
{t('debug.payloadViewer.rawPayload')}
{selectedPayload.rawPayload ? (
@@ -494,7 +496,7 @@ const Debug = () => {
onClick={closePayloadModal}
className="px-4 py-2 bg-gray-300 text-gray-700 rounded-md hover:bg-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-500"
>
- Close
+ {t('common.close')}
diff --git a/client/src/pages/Settings.jsx b/client/src/pages/Settings.jsx
index 748705a..d2155f3 100644
--- a/client/src/pages/Settings.jsx
+++ b/client/src/pages/Settings.jsx
@@ -82,7 +82,7 @@ const Settings = () => {
setTenantConfig(response.data.data);
} catch (error) {
console.error('Failed to fetch tenant config:', error);
- toast.error('Failed to load tenant settings');
+ toast.error(t('settings.failedToLoad'));
} finally {
setLoading(false);
}
@@ -104,7 +104,7 @@ const Settings = () => {
{t('settings.accessDenied')}
- {t('settings.accessDeniedMessage')}
+ {t('settings.noPermission')}
diff --git a/client/src/utils/tempTranslations.js b/client/src/utils/tempTranslations.js
index 3ff195d..6003538 100644
--- a/client/src/utils/tempTranslations.js
+++ b/client/src/utils/tempTranslations.js
@@ -376,6 +376,23 @@ const translations = {
highPriority: 'High Priority',
mediumPriority: 'Medium Priority',
clearAll: 'Clear All',
+ noAlerts: 'No movement alerts',
+ noAlertsDescription: 'Drone movement patterns will appear here',
+ droneDevice: 'Drone {droneId} • Device {deviceId}',
+ droneType: 'Drone Type:',
+ frequency: 'Frequency:',
+ confidence: 'Confidence:',
+ signalDuration: 'Signal Duration:',
+ movementPattern: 'Movement Pattern:',
+ pattern: 'Pattern:',
+ speed: 'Speed:',
+ distance: 'Distance:',
+ trackingStats: 'Tracking Stats:',
+ detectionsOverTime: '{count} detections over {time} minutes',
+ recentRssiHistory: 'Recent RSSI History:',
+ strengthening: 'strengthening',
+ weakening: 'weakening',
+ stable: 'stable',
droneTypes: {
djiMavic: 'DJI Mavic',
racingDrone: 'Racing Drone',
@@ -385,6 +402,184 @@ const translations = {
unknown: 'Unknown'
}
},
+ debug: {
+ title: 'Debug Console',
+ subtitle: 'Admin-only access to all detection data including drone type 0 (None)',
+ debugInformation: 'Debug Information',
+ totalNoneDetections: 'Total None detections: {count}',
+ filters: 'Filters',
+ droneType: 'Drone Type',
+ deviceId: 'Device ID',
+ resultsPerPage: 'Results per page',
+ filterByDeviceId: 'Filter by device ID',
+ allTypes: 'All Types',
+ debugDetections: 'Debug Detections ({count})',
+ noDebugData: 'No debug data',
+ noDetectionsFound: 'No detections found matching the current filters.',
+ idTime: 'ID / Time',
+ device: 'Device',
+ rssiFreq: 'RSSI / Freq',
+ threatLevel: 'Threat Level',
+ debug: 'Debug',
+ actions: 'Actions',
+ viewPayload: 'View Payload',
+ deleteDetection: 'Delete Detection',
+ droneTypeOptions: {
+ none: '0 - None (Debug)',
+ unknown: '1 - Unknown',
+ orlan: '2 - Orlan',
+ zala: '3 - Zala',
+ eleron: '4 - Eleron',
+ zalaLancet: '5 - Zala Lancet',
+ lancet: '6 - Lancet',
+ fpvCrossFire: '7 - FPV CrossFire',
+ fpvElrs: '8 - FPV ELRS',
+ maybeOrlan: '9 - Maybe Orlan',
+ maybeZala: '10 - Maybe Zala',
+ maybeLancet: '11 - Maybe Lancet',
+ maybeEleron: '12 - Maybe Eleron',
+ dji: '13 - DJI',
+ supercam: '14 - Supercam',
+ maybeSupercam: '15 - Maybe Supercam',
+ reb: '16 - REB',
+ cryptoOrlan: '17 - Crypto Orlan',
+ djiEnterprise: '18 - DJI Enterprise'
+ },
+ payloadViewer: {
+ title: 'Debug Payload Viewer',
+ detectionId: 'Detection ID:',
+ timestamp: 'Timestamp:',
+ deviceId: 'Device ID:',
+ rawPayload: 'Raw Payload:',
+ processedData: 'Processed Data:',
+ noPayloadData: 'No raw payload data found for this detection',
+ failedToFetch: 'Failed to fetch payload data'
+ }
+ },
+ settings: {
+ title: 'Settings',
+ loading: 'Loading settings...',
+ accessDenied: 'Access Denied',
+ noPermission: 'You do not have permission to access settings.',
+ general: 'General',
+ branding: 'Branding',
+ security: 'Security',
+ authentication: 'Authentication',
+ users: 'Users',
+ saveChanges: 'Save Changes',
+ saving: 'Saving...',
+ saved: 'Settings saved successfully',
+ failedToSave: 'Failed to save settings',
+ failedToLoad: 'Failed to load tenant settings'
+ },
+ alerts: {
+ title: 'Alert Management',
+ description: 'Manage alert rules and view alert activity',
+ loading: 'Loading alerts...',
+ rules: 'Rules',
+ logs: 'Logs',
+ stats: 'Stats',
+ createRule: 'Create Rule',
+ createAlert: 'Create Alert',
+ createAlertRule: 'Create Alert Rule',
+ editRule: 'Edit Rule',
+ deleteRule: 'Delete Rule',
+ ruleDetails: 'Rule Details',
+ noRules: 'No alert rules configured',
+ noAlertRules: 'No alert rules',
+ noRulesDescription: 'Create your first alert rule to start monitoring drone activity.',
+ noAlertRulesDescription: 'Create your first alert rule to start monitoring drone activity.',
+ noLogs: 'No alert logs',
+ noLogsDescription: 'Alert activity will appear here once rules are triggered.',
+ name: 'Name',
+ description: 'Description',
+ priority: 'Priority',
+ minDetections: 'Minimum Detections',
+ timeWindow: 'Time Window (seconds)',
+ cooldownPeriod: 'Cooldown Period (seconds)',
+ alertChannels: 'Alert Channels',
+ minThreatLevel: 'Minimum Threat Level',
+ droneTypes: 'Drone Types',
+ deviceIds: 'Device IDs',
+ smsPhoneNumber: 'SMS Phone Number',
+ webhookUrl: 'Webhook URL',
+ enabled: 'Enabled',
+ disabled: 'Disabled',
+ active: 'Active',
+ inactive: 'Inactive',
+ triggered: 'Triggered',
+ sentAt: 'Sent At',
+ channel: 'Channel',
+ channels: 'Channels',
+ status: 'Status',
+ message: 'Message',
+ detectionDetails: 'Detection Details',
+ viewDetails: 'View Details',
+ alertEvent: 'Alert Event',
+ relatedAlerts: 'Related Alerts',
+ showMore: 'Show {count} more alerts',
+ showLess: 'Show less',
+ alertRules: 'Alert Rules',
+ alertLogs: 'Alert Logs',
+ conditions: 'Conditions',
+ actions: 'Actions',
+ created: 'Created',
+ cooldown: 'Cooldown',
+ minThreat: 'Min Threat',
+ totalAlerts24h: 'Total Alerts (24h)',
+ sentSuccessfully: 'Sent Successfully',
+ failed: 'Failed',
+ pending: 'Pending',
+ low: 'Low',
+ medium: 'Medium',
+ high: 'High',
+ critical: 'Critical',
+ priorities: {
+ low: 'Low',
+ medium: 'Medium',
+ high: 'High',
+ critical: 'Critical'
+ },
+ channels: {
+ sms: 'SMS',
+ webhook: 'Webhook',
+ email: 'Email'
+ },
+ threatLevels: {
+ low: 'Low',
+ medium: 'Medium',
+ high: 'High',
+ critical: 'Critical'
+ },
+ form: {
+ nameRequired: 'Rule name is required',
+ nameHelp: 'A descriptive name for this alert rule',
+ descriptionHelp: 'Optional description of what this rule monitors',
+ priorityHelp: 'Priority level for alerts generated by this rule',
+ minDetectionsHelp: 'Minimum number of detections required to trigger alert',
+ timeWindowHelp: 'Time window in seconds to count detections',
+ cooldownHelp: 'Minimum time between alerts for the same rule',
+ channelsRequired: 'At least one alert channel is required',
+ channelsHelp: 'How alerts from this rule will be delivered',
+ threatLevelHelp: 'Only trigger for detections with this threat level or higher',
+ droneTypesHelp: 'Leave empty to monitor all drone types',
+ deviceIdsHelp: 'Leave empty to monitor all devices',
+ smsHelp: 'Phone number for SMS alerts (required if SMS channel selected)',
+ webhookHelp: 'URL for webhook alerts (required if webhook channel selected)',
+ updateFailed: 'Failed to update alert rule',
+ editAlertRule: 'Edit Alert Rule',
+ anyLevel: 'Any Level',
+ monitoring: 'Monitoring',
+ droneTypesFilter: 'Drone Types Filter',
+ leaveEmptyAllTypes: 'Leave empty to monitor all drone types',
+ alertChannelsLabel: 'Alert Channels',
+ selectChannels: 'Select how alerts will be sent',
+ smsPhoneLabel: 'SMS Phone Number',
+ smsRequired: 'Required when SMS is selected',
+ webhookUrlLabel: 'Webhook URL',
+ webhookRequired: 'Required when webhook is selected'
+ }
+ },
register: {
registrationDisabled: 'Registration is not enabled for this tenant',
configLoadFailed: 'Failed to load authentication configuration',
@@ -414,6 +609,7 @@ const translations = {
info: 'Information',
cancel: 'Cancel',
save: 'Save',
+ copy: 'Copy to Clipboard',
delete: 'Delete',
edit: 'Edit',
view: 'View',
@@ -860,6 +1056,23 @@ const translations = {
highPriority: 'Hög prioritet',
mediumPriority: 'Medel prioritet',
clearAll: 'Rensa alla',
+ noAlerts: 'Inga rörelselarm',
+ noAlertsDescription: 'Drönarrörelsemönster kommer att visas här',
+ droneDevice: 'Drönare {droneId} • Enhet {deviceId}',
+ droneType: 'Drönartyp:',
+ frequency: 'Frekvens:',
+ confidence: 'Säkerhet:',
+ signalDuration: 'Signallängd:',
+ movementPattern: 'Rörelsemönster:',
+ pattern: 'Mönster:',
+ speed: 'Hastighet:',
+ distance: 'Avstånd:',
+ trackingStats: 'Spårningsstatistik:',
+ detectionsOverTime: '{count} detekteringar över {time} minuter',
+ recentRssiHistory: 'Senaste RSSI-historik:',
+ strengthening: 'förstärks',
+ weakening: 'försvagas',
+ stable: 'stabil',
droneTypes: {
djiMavic: 'DJI Mavic',
racingDrone: 'Racingdrönare',
@@ -869,6 +1082,184 @@ const translations = {
unknown: 'Okänd'
}
},
+ debug: {
+ title: 'Felsökningskonsol',
+ subtitle: 'Endast admin-åtkomst till all detekteringsdata inklusive drönartyp 0 (Ingen)',
+ debugInformation: 'Felsökningsinformation',
+ totalNoneDetections: 'Totalt antal Ingen-detekteringar: {count}',
+ filters: 'Filter',
+ droneType: 'Drönartyp',
+ deviceId: 'Enhets-ID',
+ resultsPerPage: 'Resultat per sida',
+ filterByDeviceId: 'Filtrera efter enhets-ID',
+ allTypes: 'Alla typer',
+ debugDetections: 'Felsökningsdetekteringar ({count})',
+ noDebugData: 'Ingen felsökningsdata',
+ noDetectionsFound: 'Inga detekteringar hittades som matchar nuvarande filter.',
+ idTime: 'ID / Tid',
+ device: 'Enhet',
+ rssiFreq: 'RSSI / Frekv',
+ threatLevel: 'Hotnivå',
+ debug: 'Felsökning',
+ actions: 'Åtgärder',
+ viewPayload: 'Visa nyttolast',
+ deleteDetection: 'Ta bort detektion',
+ droneTypeOptions: {
+ none: '0 - Ingen (Felsökning)',
+ unknown: '1 - Okänd',
+ orlan: '2 - Orlan',
+ zala: '3 - Zala',
+ eleron: '4 - Eleron',
+ zalaLancet: '5 - Zala Lancet',
+ lancet: '6 - Lancet',
+ fpvCrossFire: '7 - FPV CrossFire',
+ fpvElrs: '8 - FPV ELRS',
+ maybeOrlan: '9 - Kanske Orlan',
+ maybeZala: '10 - Kanske Zala',
+ maybeLancet: '11 - Kanske Lancet',
+ maybeEleron: '12 - Kanske Eleron',
+ dji: '13 - DJI',
+ supercam: '14 - Supercam',
+ maybeSupercam: '15 - Kanske Supercam',
+ reb: '16 - REB',
+ cryptoOrlan: '17 - Krypto Orlan',
+ djiEnterprise: '18 - DJI Enterprise'
+ },
+ payloadViewer: {
+ title: 'Felsökningsnyttolastvisare',
+ detectionId: 'Detektions-ID:',
+ timestamp: 'Tidsstämpel:',
+ deviceId: 'Enhets-ID:',
+ rawPayload: 'Rå nyttolast:',
+ processedData: 'Bearbetad data:',
+ noPayloadData: 'Ingen rå nyttolastdata hittades för denna detektion',
+ failedToFetch: 'Misslyckades med att hämta nyttolastdata'
+ }
+ },
+ settings: {
+ title: 'Inställningar',
+ loading: 'Laddar inställningar...',
+ accessDenied: 'Åtkomst nekad',
+ noPermission: 'Du har inte behörighet att komma åt inställningar.',
+ general: 'Allmänt',
+ branding: 'Varumärke',
+ security: 'Säkerhet',
+ authentication: 'Autentisering',
+ users: 'Användare',
+ saveChanges: 'Spara ändringar',
+ saving: 'Sparar...',
+ saved: 'Inställningar sparade framgångsrikt',
+ failedToSave: 'Misslyckades med att spara inställningar',
+ failedToLoad: 'Misslyckades med att ladda klientinställningar'
+ },
+ alerts: {
+ title: 'Larmhantering',
+ description: 'Hantera larmregler och visa larmaktivitet',
+ loading: 'Laddar larm...',
+ rules: 'Regler',
+ logs: 'Loggar',
+ stats: 'Statistik',
+ createRule: 'Skapa regel',
+ createAlert: 'Skapa larm',
+ createAlertRule: 'Skapa larmregel',
+ editRule: 'Redigera regel',
+ deleteRule: 'Ta bort regel',
+ ruleDetails: 'Regeldetaljer',
+ noRules: 'Inga larmregler konfigurerade',
+ noAlertRules: 'Inga larmregler',
+ noRulesDescription: 'Skapa din första larmregel för att börja övervaka drönaraktivitet.',
+ noAlertRulesDescription: 'Skapa din första larmregel för att börja övervaka drönaraktivitet.',
+ noLogs: 'Inga larmloggar',
+ noLogsDescription: 'Larmaktivitet kommer att visas här när regler utlöses.',
+ name: 'Namn',
+ description: 'Beskrivning',
+ priority: 'Prioritet',
+ minDetections: 'Minsta antal detekteringar',
+ timeWindow: 'Tidsfönster (sekunder)',
+ cooldownPeriod: 'Nedkylningsperiod (sekunder)',
+ alertChannels: 'Larmkanaler',
+ minThreatLevel: 'Lägsta hotnivå',
+ droneTypes: 'Drönartyper',
+ deviceIds: 'Enhets-ID:n',
+ smsPhoneNumber: 'SMS-telefonnummer',
+ webhookUrl: 'Webhook-URL',
+ enabled: 'Aktiverad',
+ disabled: 'Inaktiverad',
+ active: 'Aktiv',
+ inactive: 'Inaktiv',
+ triggered: 'Utlöst',
+ sentAt: 'Skickat vid',
+ channel: 'Kanal',
+ channels: 'Kanaler',
+ status: 'Status',
+ message: 'Meddelande',
+ detectionDetails: 'Detekteringsdetaljer',
+ viewDetails: 'Visa detaljer',
+ alertEvent: 'Larmhändelse',
+ relatedAlerts: 'Relaterade larm',
+ showMore: 'Visa {count} fler larm',
+ showLess: 'Visa mindre',
+ alertRules: 'Larmregler',
+ alertLogs: 'Larmloggar',
+ conditions: 'Villkor',
+ actions: 'Åtgärder',
+ created: 'Skapad',
+ cooldown: 'Nedkylning',
+ minThreat: 'Min hot',
+ totalAlerts24h: 'Totala larm (24h)',
+ sentSuccessfully: 'Skickade framgångsrikt',
+ failed: 'Misslyckades',
+ pending: 'Väntande',
+ low: 'Låg',
+ medium: 'Medel',
+ high: 'Hög',
+ critical: 'Kritisk',
+ priorities: {
+ low: 'Låg',
+ medium: 'Medel',
+ high: 'Hög',
+ critical: 'Kritisk'
+ },
+ channels: {
+ sms: 'SMS',
+ webhook: 'Webhook',
+ email: 'E-post'
+ },
+ threatLevels: {
+ low: 'Låg',
+ medium: 'Medel',
+ high: 'Hög',
+ critical: 'Kritisk'
+ },
+ form: {
+ nameRequired: 'Regelnamn krävs',
+ nameHelp: 'Ett beskrivande namn för denna larmregel',
+ descriptionHelp: 'Valfri beskrivning av vad denna regel övervakar',
+ priorityHelp: 'Prioritetsnivå för larm genererade av denna regel',
+ minDetectionsHelp: 'Minsta antal detekteringar som krävs för att utlösa larm',
+ timeWindowHelp: 'Tidsfönster i sekunder för att räkna detekteringar',
+ cooldownHelp: 'Minimitid mellan larm för samma regel',
+ channelsRequired: 'Minst en larmkanal krävs',
+ channelsHelp: 'Hur larm från denna regel kommer att levereras',
+ threatLevelHelp: 'Utlös endast för detekteringar med denna hotnivå eller högre',
+ droneTypesHelp: 'Lämna tomt för att övervaka alla drönartyper',
+ deviceIdsHelp: 'Lämna tomt för att övervaka alla enheter',
+ smsHelp: 'Telefonnummer för SMS-larm (krävs om SMS-kanal är vald)',
+ webhookHelp: 'URL för webhook-larm (krävs om webhook-kanal är vald)',
+ updateFailed: 'Misslyckades med att uppdatera larmregel',
+ editAlertRule: 'Redigera larmregel',
+ anyLevel: 'Alla nivåer',
+ monitoring: 'Övervakning',
+ droneTypesFilter: 'Drönartypsfilter',
+ leaveEmptyAllTypes: 'Lämna tomt för att övervaka alla drönartyper',
+ alertChannelsLabel: 'Larmkanaler',
+ selectChannels: 'Välj hur larm kommer att skickas',
+ smsPhoneLabel: 'SMS-telefonnummer',
+ smsRequired: 'Krävs när SMS är valt',
+ webhookUrlLabel: 'Webhook-URL',
+ webhookRequired: 'Krävs när webhook är valt'
+ }
+ },
register: {
registrationDisabled: 'Registrering är inte aktiverad för denna klient',
configLoadFailed: 'Misslyckades med att ladda autentiseringskonfiguration',
@@ -898,6 +1289,7 @@ const translations = {
info: 'Information',
cancel: 'Avbryt',
save: 'Spara',
+ copy: 'Kopiera till urklipp',
delete: 'Ta bort',
edit: 'Redigera',
view: 'Visa',