From 348b489b0e59c32ffef6680c73412a7b14579780 Mon Sep 17 00:00:00 2001 From: Alexander Borg Date: Fri, 19 Sep 2025 14:35:02 +0200 Subject: [PATCH] Fix jwt-token --- client/src/pages/Alerts.jsx | 88 +++++++++--------- client/src/pages/Settings.jsx | 98 +++++++++++++------- client/src/utils/tempTranslations.js | 128 ++++++++++++++++++++++++++- 3 files changed, 236 insertions(+), 78 deletions(-) diff --git a/client/src/pages/Alerts.jsx b/client/src/pages/Alerts.jsx index a6c0e8d..2e8b28c 100644 --- a/client/src/pages/Alerts.jsx +++ b/client/src/pages/Alerts.jsx @@ -137,19 +137,19 @@ const Alerts = () => {
{alertStats.total_alerts}
-
Total Alerts (24h)
+
{t('alerts.totalAlerts24h')}
{alertStats.sent_alerts}
-
Sent Successfully
+
{t('alerts.sentSuccessfully')}
{alertStats.failed_alerts}
-
Failed
+
{t('alerts.failed')}
{alertStats.pending_alerts}
-
Pending
+
{t('alerts.pending')}
)} @@ -165,7 +165,7 @@ const Alerts = () => { : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' }`} > - Alert Rules ({alertRules.length}) + {t('alerts.alertRules')} ({alertRules.length}) @@ -186,9 +186,9 @@ const Alerts = () => { {(alertRules?.length || 0) === 0 ? (
-

No alert rules

+

{t('alerts.noAlertRules')}

- Get started by creating your first alert rule. + {t('alerts.noAlertRulesDescription')}

@@ -205,13 +205,13 @@ const Alerts = () => { - - - - - - - + + + + + + + @@ -233,7 +233,7 @@ const Alerts = () => { - {rule.priority} + {t(`alerts.${rule.priority}`)} @@ -338,9 +338,9 @@ const Alerts = () => { {(alertLogs?.length || 0) === 0 ? (
-

No alert logs

+

{t('alerts.noAlertLogs')}

- Alert logs will appear here when alerts are triggered. + {t('alerts.noAlertLogsDescription')}

) : ( @@ -348,13 +348,13 @@ const Alerts = () => {
NamePriorityChannelsConditionsStatusCreatedActions{t('alerts.name')}{t('alerts.priority')}{t('alerts.channels')}{t('alerts.conditions')}{t('alerts.status')}{t('alerts.created')}{t('alerts.actions')}
@@ -251,28 +251,28 @@ const Alerts = () => {
{rule.min_detections > 1 && ( -
Min detections: {rule.min_detections}
+
{t('alerts.minDetections')}: {rule.min_detections}
)} {rule.time_window && ( -
Time window: {rule.time_window}s
+
{t('alerts.timeWindow')}: {rule.time_window}s
)} {rule.cooldown_period && ( -
Cooldown: {rule.cooldown_period}s
+
{t('alerts.cooldown')}: {rule.cooldown_period}s
)} {rule.min_threat_level && ( -
Min threat: {rule.min_threat_level}
+
{t('alerts.minThreat')}: {rule.min_threat_level}
)} {rule.drone_types && rule.drone_types.length > 0 && (
-
Drone types:
+
{t('alerts.droneTypes')}:
{rule.drone_types.map((typeId, index) => { - const droneTypes = { - 0: 'Consumer', - 1: 'Orlan', - 2: 'Professional', - 3: 'Racing', - 4: 'Unknown' + const droneTypeKeys = { + 0: 'consumer', + 1: 'orlan', + 2: 'professional', + 3: 'racing', + 4: 'unknown' }; return ( { : 'bg-gray-100 text-gray-800' }`} > - {droneTypes[typeId] || 'Unknown'} + {t(`alerts.${droneTypeKeys[typeId] || 'unknown'}`)} {typeId === 1 && '⚠️'} ); @@ -299,7 +299,7 @@ const Alerts = () => { ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800' }`}> - {rule.is_active ? 'Active' : 'Inactive'} + {rule.is_active ? t('alerts.active') : t('alerts.inactive')}
@@ -313,13 +313,13 @@ const Alerts = () => { onClick={() => handleEditRule(rule)} className="text-primary-600 hover:text-primary-900 text-sm" > - Edit + {t('alerts.edit')}
- - - - - - - + + + + + + + @@ -380,7 +380,7 @@ const Alerts = () => {
StatusTypeRecipientRuleDetectionMessageSent At{t('alerts.status')}{t('alerts.type')}{t('alerts.recipient')}{t('alerts.rule')}{t('alerts.detection')}{t('alerts.message')}{t('alerts.sentAt')}
- {log.rule?.name || 'Unknown Rule'} + {log.rule?.name || t('alerts.unknownRule')}
@@ -389,10 +389,10 @@ const Alerts = () => { onClick={() => handleViewDetection(log.detection_id)} className="text-primary-600 hover:text-primary-900 text-sm font-medium" > - View Details + {t('alerts.viewDetails')} ) : ( - N/A + {t('alerts.na')} )} diff --git a/client/src/pages/Settings.jsx b/client/src/pages/Settings.jsx index f37ecab..255b865 100644 --- a/client/src/pages/Settings.jsx +++ b/client/src/pages/Settings.jsx @@ -53,10 +53,45 @@ const ALL_TABS = [ const Settings = () => { const { user } = useAuth(); + const { t } = useTranslation(); const [tenantConfig, setTenantConfig] = useState(null); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); + // Define tabs with translations inside component + const ALL_TABS = [ + { + id: 'general', + name: t('settings.general'), + icon: CogIcon, + permission: 'tenant.view' + }, + { + id: 'branding', + name: t('settings.branding'), + icon: PaintBrushIcon, + permission: 'branding.view' + }, + { + id: 'security', + name: t('settings.security'), + icon: ShieldCheckIcon, + permission: 'security.view' + }, + { + id: 'authentication', + name: t('settings.authentication'), + icon: KeyIcon, + permission: 'auth.view' + }, + { + id: 'users', + name: t('settings.users'), + icon: UserGroupIcon, + permission: 'users.view' + } + ]; + // Calculate available tabs const availableTabs = user?.role ? ALL_TABS.filter(tab => hasPermission(user.role, tab.permission)) @@ -101,9 +136,9 @@ const Settings = () => {
-

Access Denied

+

{t('settings.accessDenied')}

- You don't have permission to access tenant settings. + {t('settings.accessDeniedMessage')}

@@ -167,27 +202,30 @@ const Settings = () => { }; // General Settings Component -const GeneralSettings = ({ tenantConfig }) => ( -
-
-

General Information

-
-
- -

{tenantConfig?.name}

-
-
- -

{tenantConfig?.slug}

-
-
- -

{tenantConfig?.auth_provider}

+const GeneralSettings = ({ tenantConfig }) => { + const { t } = useTranslation(); + return ( +
+
+

{t('settings.generalInformation')}

+
+
+ +

{tenantConfig?.name}

+
+
+ +

{tenantConfig?.slug}

+
+
+ +

{tenantConfig?.auth_provider}

+
-
-); + ); +}; // Branding Settings Component const BrandingSettings = ({ tenantConfig, onRefresh }) => { @@ -214,10 +252,10 @@ const BrandingSettings = ({ tenantConfig, onRefresh }) => { setSaving(true); try { await api.put('/tenant/branding', branding); - toast.success('Branding updated successfully'); + toast.success(t('settings.brandingUpdated')); if (onRefresh) onRefresh(); } catch (error) { - toast.error('Failed to update branding'); + toast.error(t('settings.brandingUpdateFailed')); } finally { setSaving(false); } @@ -279,7 +317,7 @@ const BrandingSettings = ({ tenantConfig, onRefresh }) => {

Branding & Appearance

- + { {/* Manual URL input as fallback */}
- + {
- +
{
- +
{ disabled={saving} className="bg-primary-600 text-white px-4 py-2 rounded-md hover:bg-primary-700 disabled:opacity-50" > - {saving ? 'Saving...' : 'Save Branding'} + {saving ? t('settings.saving') : t('settings.saveBranding')} ) : (
@@ -491,11 +529,11 @@ const SecuritySettings = ({ tenantConfig, onRefresh }) => { try { console.log('🔒 Sending security settings:', securitySettings); await api.put('/tenant/security', securitySettings); - toast.success('Security settings updated successfully'); + toast.success(t('settings.securityUpdated')); if (onRefresh) onRefresh(); } catch (error) { console.error('Failed to update security settings:', error); - toast.error('Failed to update security settings'); + toast.error(t('settings.securityUpdateFailed')); } finally { setSaving(false); } @@ -516,7 +554,7 @@ const SecuritySettings = ({ tenantConfig, onRefresh }) => { disabled={saving || !canEdit} className="bg-primary-600 text-white px-4 py-2 rounded-md hover:bg-primary-700 disabled:opacity-50" > - {saving ? 'Saving...' : 'Save Changes'} + {saving ? t('settings.saving') : t('settings.saveChanges')}
diff --git a/client/src/utils/tempTranslations.js b/client/src/utils/tempTranslations.js index 2c2ce1a..e05a9a8 100644 --- a/client/src/utils/tempTranslations.js +++ b/client/src/utils/tempTranslations.js @@ -168,7 +168,44 @@ const translations = { lowPriority: 'Low Priority', active: 'Active', inactive: 'Inactive', - triggered: 'Triggered' + totalAlerts24h: 'Total Alerts (24h)', + sentSuccessfully: 'Sent Successfully', + failed: 'Failed', + pending: 'Pending', + alertRules: 'Alert Rules', + alertLogs: 'Alert Logs', + noAlertRules: 'No alert rules', + noAlertRulesDescription: 'Get started by creating your first alert rule.', + createAlertRule: 'Create Alert Rule', + noAlertLogs: 'No alert logs', + noAlertLogsDescription: 'Alert logs will appear here when alerts are triggered.', + name: 'Name', + channels: 'Channels', + conditions: 'Conditions', + edit: 'Edit', + delete: 'Delete', + recipient: 'Recipient', + rule: 'Rule', + detection: 'Detection', + message: 'Message', + sentAt: 'Sent At', + viewDetails: 'View Details', + unknownRule: 'Unknown Rule', + na: 'N/A', + minDetections: 'Min detections', + timeWindow: 'Time window', + cooldown: 'Cooldown', + minThreat: 'Min threat', + droneTypes: 'Drone types', + consumer: 'Consumer', + orlan: 'Orlan', + professional: 'Professional', + racing: 'Racing', + unknown: 'Unknown', + critical: 'Critical', + high: 'High', + medium: 'Medium', + low: 'Low' }, settings: { title: 'Settings', @@ -187,7 +224,30 @@ const translations = { apiKeys: 'API Keys', dataRetention: 'Data Retention', exportData: 'Export Data', - deleteAccount: 'Delete Account' + deleteAccount: 'Delete Account', + loading: 'Loading settings...', + accessDenied: 'Access Denied', + accessDeniedMessage: "You don't have permission to access tenant settings.", + general: 'General', + branding: 'Branding', + authentication: 'Authentication', + users: 'Users', + generalInformation: 'General Information', + tenantName: 'Tenant Name', + tenantId: 'Tenant ID', + authenticationProvider: 'Authentication Provider', + companyName: 'Company Name', + logoUrl: 'Or enter logo URL manually', + primaryColor: 'Primary Color', + secondaryColor: 'Secondary Color', + save: 'Save', + saving: 'Saving...', + saveBranding: 'Save Branding', + saveChanges: 'Save Changes', + brandingUpdated: 'Branding updated successfully', + brandingUpdateFailed: 'Failed to update branding', + securityUpdated: 'Security settings updated successfully', + securityUpdateFailed: 'Failed to update security settings' }, auth: { login: 'Login', @@ -449,7 +509,44 @@ const translations = { lowPriority: 'Låg prioritet', active: 'Aktiv', inactive: 'Inaktiv', - triggered: 'Utlöst' + totalAlerts24h: 'Totalt larm (24h)', + sentSuccessfully: 'Skickade framgångsrikt', + failed: 'Misslyckades', + pending: 'Väntande', + alertRules: 'Larmregler', + alertLogs: 'Larmloggar', + noAlertRules: 'Inga larmregler', + noAlertRulesDescription: 'Kom igång genom att skapa din första larmregel.', + createAlertRule: 'Skapa larmregel', + noAlertLogs: 'Inga larmloggar', + noAlertLogsDescription: 'Larmloggar kommer att visas här när larm utlöses.', + name: 'Namn', + channels: 'Kanaler', + conditions: 'Villkor', + edit: 'Redigera', + delete: 'Ta bort', + recipient: 'Mottagare', + rule: 'Regel', + detection: 'Detektion', + message: 'Meddelande', + sentAt: 'Skickat vid', + viewDetails: 'Visa detaljer', + unknownRule: 'Okänd regel', + na: 'Ej tillämpligt', + minDetections: 'Min detekteringar', + timeWindow: 'Tidsfönster', + cooldown: 'Nedkylning', + minThreat: 'Min hot', + droneTypes: 'Drönartyper', + consumer: 'Konsument', + orlan: 'Orlan', + professional: 'Professionell', + racing: 'Racing', + unknown: 'Okänd', + critical: 'Kritisk', + high: 'Hög', + medium: 'Medel', + low: 'Låg' }, settings: { title: 'Inställningar', @@ -468,7 +565,30 @@ const translations = { apiKeys: 'API-nycklar', dataRetention: 'Datalagring', exportData: 'Exportera data', - deleteAccount: 'Ta bort konto' + deleteAccount: 'Ta bort konto', + loading: 'Laddar inställningar...', + accessDenied: 'Åtkomst nekad', + accessDeniedMessage: 'Du har inte behörighet att komma åt tenant-inställningar.', + general: 'Allmänt', + branding: 'Varumärke', + authentication: 'Autentisering', + users: 'Användare', + generalInformation: 'Allmän information', + tenantName: 'Tenant-namn', + tenantId: 'Tenant-ID', + authenticationProvider: 'Autentiseringsleverantör', + companyName: 'Företagsnamn', + logoUrl: 'Eller ange logotyp-URL manuellt', + primaryColor: 'Primärfärg', + secondaryColor: 'Sekundär färg', + save: 'Spara', + saving: 'Sparar...', + saveBranding: 'Spara varumärke', + saveChanges: 'Spara ändringar', + brandingUpdated: 'Varumärke uppdaterat framgångsrikt', + brandingUpdateFailed: 'Misslyckades med att uppdatera varumärke', + securityUpdated: 'Säkerhetsinställningar uppdaterade framgångsrikt', + securityUpdateFailed: 'Misslyckades med att uppdatera säkerhetsinställningar' }, auth: { login: 'Logga in',