diff --git a/frontend/src/components/falukant/MessagesDialog.vue b/frontend/src/components/falukant/MessagesDialog.vue index f2e4062..2d973bc 100644 --- a/frontend/src/components/falukant/MessagesDialog.vue +++ b/frontend/src/components/falukant/MessagesDialog.vue @@ -151,6 +151,19 @@ export default { // Extrahiere Parameter aus value und effects params = this.extractParamsFromValue(value, n); + + // Wenn value eine einfache Zahl ist (z.B. für overproduction), als value-Parameter verwenden + if (typeof parsed.value === 'number') { + params.value = parsed.value; + } + + // Weitere Parameter aus parsed extrahieren (z.B. branch_id) + if (parsed.branch_id !== undefined) { + params.branch_id = parsed.branch_id; + } + if (parsed.region_id !== undefined) { + params.region_id = parsed.region_id; + } } } catch (e) { // Bei Parse-Fehler: Alte Struktur unterstützen @@ -250,6 +263,18 @@ export default { formatted.percent = `${params.percent > 0 ? '+' : ''}${params.percent.toFixed(1)}%`; } + // Einfache Werte (z.B. für overproduction) + if (params.value !== undefined && params.value !== null) { + formatted.value = Number(params.value); + } + + // Filiale-Information + if (params.branch_id !== undefined && params.branch_id !== null) { + formatted.branch_info = ` (Filiale #${params.branch_id})`; + } else { + formatted.branch_info = ''; + } + // Gesundheit formatieren if (params.change !== undefined && params.change !== null) { formatted.healthChange = params.change > 0 ? `+${params.change}` : `${params.change}`; diff --git a/frontend/src/i18n/locales/de/falukant.json b/frontend/src/i18n/locales/de/falukant.json index e601d74..cdcffe8 100644 --- a/frontend/src/i18n/locales/de/falukant.json +++ b/frontend/src/i18n/locales/de/falukant.json @@ -33,7 +33,7 @@ "notifications": { "notify_election_created": "Es wurde eine neue Wahl ausgeschrieben.", "production": { - "overproduction": "Überproduktion: Deine Produktion liegt {value}% über dem Bedarf." + "overproduction": "Überproduktion: Deine Produktion liegt {value} Einheiten über dem Bedarf{branch_info}." }, "transport": { "waiting": "Transport wartet" diff --git a/frontend/src/i18n/locales/en/falukant.json b/frontend/src/i18n/locales/en/falukant.json index a168749..5b09c50 100644 --- a/frontend/src/i18n/locales/en/falukant.json +++ b/frontend/src/i18n/locales/en/falukant.json @@ -19,7 +19,7 @@ "notifications": { "notify_election_created": "A new election has been scheduled.", "production": { - "overproduction": "Overproduction: your production is {value}% above demand." + "overproduction": "Overproduction: your production is {value} units above demand{branch_info}." }, "transport": { "waiting": "Transport waiting" diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 2c487d4..005bc46 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -192,8 +192,17 @@ const store = createStore({ try { if (socketIoUrl) { const parsed = new URL(socketIoUrl, window.location.origin); - // Falls /api oder ähnliche Pfade enthalten sind → auf Origin reduzieren (inkl. Port!) - socketIoUrl = parsed.origin; + // In Produktion: Verwende immer window.location.origin (Port 443), nicht den Port aus der Umgebungsvariable + // Socket.io wird über Nginx-Proxy auf /socket.io/ weitergeleitet + if (window.location.hostname === 'www.your-part.de' || window.location.hostname.includes('your-part.de')) { + socketIoUrl = window.location.origin; + } else { + // Lokale Entwicklung: Origin aus parsed verwenden (inkl. Port) + socketIoUrl = parsed.origin; + } + } else { + // Fallback: aktuelle Origin verwenden + socketIoUrl = window.location.origin; } } catch (e) { // Wenn Parsing fehlschlägt: letzte Rettung ist der aktuelle Origin @@ -284,12 +293,26 @@ const store = createStore({ // Wenn Umgebungsvariable nicht gesetzt ist oder leer, verwende Fallback-Logik if (!daemonUrl || (typeof daemonUrl === 'string' && daemonUrl.trim() === '')) { - // Fallback: direkte Verbindung zum Daemon-Port 4551 (ohne Apache-Proxy) - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; - daemonUrl = `${protocol}//${hostname}:4551/`; - console.log('[Daemon] Verwende Fallback basierend auf Hostname, Protokoll und Port 4551'); + // In Produktion: Verwende /ws/ über Nginx-Proxy (Port 443) + if (isProduction) { + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + daemonUrl = `${protocol}//${hostname}/ws/`; + console.log('[Daemon] Verwende Nginx-Proxy /ws/ über Port 443'); + } else { + // Lokale Entwicklung: direkte Verbindung zum Daemon-Port 4551 + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + daemonUrl = `${protocol}//${hostname}:4551/`; + console.log('[Daemon] Verwende Fallback basierend auf Hostname, Protokoll und Port 4551'); + } } else { - console.log('[Daemon] Verwende Umgebungsvariable'); + // Wenn Umgebungsvariable gesetzt ist, aber in Produktion: Konvertiere Port 4551 zu /ws/ + if (isProduction && daemonUrl.includes(':4551')) { + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + daemonUrl = `${protocol}//${hostname}/ws/`; + console.log('[Daemon] Konvertiere Port 4551 zu /ws/ für Nginx-Proxy'); + } else { + console.log('[Daemon] Verwende Umgebungsvariable'); + } } console.log('[Daemon] Finale Daemon-URL:', daemonUrl); diff --git a/yourpart-websocket-fixed.conf b/yourpart-websocket-fixed.conf new file mode 100644 index 0000000..8407b36 --- /dev/null +++ b/yourpart-websocket-fixed.conf @@ -0,0 +1,31 @@ +# /etc/apache2/sites-available/yourpart-websocket.conf + + ServerName www.your-part.de + + # SSL-Konfiguration + Include /etc/letsencrypt/options-ssl-apache.conf + SSLCertificateFile /etc/letsencrypt/live/www.your-part.de/fullchain.pem + SSLCertificateKeyFile /etc/letsencrypt/live/www.your-part.de/privkey.pem + + # HTTP/2 deaktivieren + Protocols http/1.1 + + # WebSocket-Proxy (unverschlüsselt zu Daemon) + ProxyPreserveHost On + ProxyRequests Off + + # WebSocket-Upgrade (muss VOR ProxyPass stehen) + RewriteEngine On + RewriteCond %{HTTP:Upgrade} websocket [NC] + RewriteCond %{HTTP:Connection} upgrade [NC] + RewriteRule ^/?(.*) "ws://localhost:4551/$1" [P,L] + + # Fallback für normale HTTP-Requests (falls nötig) + ProxyPass / http://localhost:2020/ + ProxyPassReverse / http://localhost:2020/ + + # CORS-Headers + Header always set Access-Control-Allow-Origin "https://www.your-part.de" + Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS" + Header always set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization" + diff --git a/yourpart-ws-fixed.conf b/yourpart-ws-fixed.conf new file mode 100644 index 0000000..ff1c441 --- /dev/null +++ b/yourpart-ws-fixed.conf @@ -0,0 +1,29 @@ + + + ServerName www.your-part.de + + SSLEngine on + Protocols http/1.1 + + Include /etc/letsencrypt/options-ssl-apache.conf + SSLCertificateFile /etc/letsencrypt/live/www.your-part.de/fullchain.pem + SSLCertificateKeyFile /etc/letsencrypt/live/www.your-part.de/privkey.pem + + ProxyPreserveHost On + RequestHeader set X-Forwarded-Proto "https" + AllowEncodedSlashes NoDecode + + # WebSocket-Upgrade für Socket.io (muss VOR ProxyPass stehen) + RewriteEngine on + RewriteCond %{HTTP:Upgrade} websocket [NC] + RewriteCond %{HTTP:Connection} upgrade [NC] + RewriteRule ^/socket.io/(.*)$ "ws://127.0.0.1:2020/socket.io/$1" [P,L] + + # HTTP-Proxy für Socket.io (Fallback für Polling) + ProxyPass "/socket.io/" "http://127.0.0.1:2020/socket.io/" retry=0 + ProxyPassReverse "/socket.io/" "http://127.0.0.1:2020/socket.io/" + + ErrorLog /var/log/apache2/yourpart-ws.error.log + CustomLog /var/log/apache2/yourpart-ws.access.log combined + +