From dcfa5bf799a9a21a9e6c05b6fe400cca48c58a1a Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Tue, 6 Jan 2026 19:24:55 +0100 Subject: [PATCH] fix: String concatenation with DOM elements in CrowdSec views MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed "[object HTMLElement]" display bugs in CrowdSec dashboard views by properly structuring DOM element children arrays. ## Problem: Multiple CrowdSec dashboard views were showing "[object HTMLElement]" instead of properly rendered content. This occurred when JavaScript code tried to concatenate strings with E() DOM elements using the + operator. ## Root Cause: ```javascript // WRONG: String concatenation with DOM elements E('p', {}, _('Access metrics at: ') + E('code', {}, url)) // Results in: "Access metrics at: [object HTMLElement]" ``` When you concatenate a string with a DOM element, JavaScript converts the DOM element to its string representation "[object HTMLElement]", which then gets rendered as text. ## Solution: Changed from string concatenation to proper children arrays: ```javascript // CORRECT: Array of children E('p', {}, [ _('Access metrics at: '), E('code', {}, url) ]) ``` ## Files Fixed: ### metrics.js (line 299-302): - Fixed "Access metrics at: [object HTMLElement]" in metrics export info box - Changed from concatenation to children array ### settings.js (line 217-220): - Fixed "Or use: [object HTMLElement]" in collections empty state - Changed from concatenation to children array ### waf.js (lines 123-126): - Fixed 4 instances in WAF setup instructions: - "Install AppSec collections: [object HTMLElement]" - "Restart CrowdSec service: [object HTMLElement]" - "Verify status: [object HTMLElement]" - Changed all from concatenation to children arrays ## Technical Notes: - The E() helper function expects children to be: 1. A single string 2. A single DOM element 3. An array of strings and/or DOM elements - String concatenation (+) cannot be used to combine text with DOM elements - Always use array notation when mixing text and elements ## Testing: - Deployed to router 192.168.8.191 - Metrics view now displays "Access metrics at: http://127.0.0.1:6060/metrics" correctly - Settings view shows "Or use: cscli hub update" properly - WAF view renders all setup instructions with code blocks correctly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .../resources/view/crowdsec-dashboard/metrics.js | 7 ++++--- .../resources/view/crowdsec-dashboard/settings.js | 6 ++++-- .../resources/view/crowdsec-dashboard/waf.js | 15 ++++++++++++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/metrics.js b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/metrics.js index eb041a6e..5e921e39 100644 --- a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/metrics.js +++ b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/metrics.js @@ -296,9 +296,10 @@ return view.extend({ ]), E('div', { 'class': 'cs-info-box', 'style': 'margin-top: 16px; padding: 12px; background: rgba(0,150,255,0.1); border-left: 4px solid var(--cs-accent-cyan); border-radius: 4px;' }, [ E('p', { 'style': 'margin: 0 0 8px 0; color: var(--cs-text-primary); font-weight: 600;' }, _('About Metrics Export')), - E('p', { 'style': 'margin: 0; color: var(--cs-text-secondary); font-size: 14px;' }, - _('When enabled, CrowdSec exports Prometheus-compatible metrics that can be scraped by monitoring tools. Access metrics at: ') + - E('code', {}, prometheusEndpoint)) + E('p', { 'style': 'margin: 0; color: var(--cs-text-secondary); font-size: 14px;' }, [ + _('When enabled, CrowdSec exports Prometheus-compatible metrics that can be scraped by monitoring tools. Access metrics at: '), + E('code', {}, prometheusEndpoint) + ]) ]) ]) ]); diff --git a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/settings.js b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/settings.js index cb85899b..1a3d079e 100644 --- a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/settings.js +++ b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/settings.js @@ -214,8 +214,10 @@ return view.extend({ E('tr', {}, [ E('td', { 'colspan': 5, 'style': 'text-align: center; padding: 2em; color: #999;' }, [ E('p', {}, _('No collections found. Click "Update Hub" to fetch the collection list.')), - E('p', { 'style': 'margin-top: 0.5em; font-size: 0.9em;' }, - _('Or use: ') + E('code', {}, 'cscli hub update')) + E('p', { 'style': 'margin-top: 0.5em; font-size: 0.9em;' }, [ + _('Or use: '), + E('code', {}, 'cscli hub update') + ]) ]) ]) ) diff --git a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/waf.js b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/waf.js index d3d2e6cc..db7fa05e 100644 --- a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/waf.js +++ b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/waf.js @@ -120,10 +120,19 @@ return view.extend({ E('p', { 'style': 'margin: 0 0 12px 0; color: var(--cs-text-secondary); font-size: 14px;' }, _('To enable the Web Application Firewall, you need to:')), E('ol', { 'style': 'margin: 0; padding-left: 20px; color: var(--cs-text-secondary); font-size: 14px;' }, [ - E('li', {}, _('Install AppSec collections: ') + E('code', {}, 'cscli collections install crowdsecurity/appsec-*')), + E('li', {}, [ + _('Install AppSec collections: '), + E('code', {}, 'cscli collections install crowdsecurity/appsec-*') + ]), E('li', {}, _('Configure AppSec in your acquis.yaml')), - E('li', {}, _('Restart CrowdSec service: ') + E('code', {}, '/etc/init.d/crowdsec restart')), - E('li', {}, _('Verify status: ') + E('code', {}, 'cscli appsec status')) + E('li', {}, [ + _('Restart CrowdSec service: '), + E('code', {}, '/etc/init.d/crowdsec restart') + ]), + E('li', {}, [ + _('Verify status: '), + E('code', {}, 'cscli appsec status') + ]) ]) ]), E('div', { 'class': 'cs-info-box', 'style': 'margin-top: 16px;' }, [