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
+
+