From 4c70874fffc002321a809bdc9196bcbad043f276 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Tue, 30 Dec 2025 15:11:32 +0100 Subject: [PATCH] feat(netifyd/network-modes): add wizard views --- .../resources/netifyd-dashboard/api.js | 7 + .../view/netifyd-dashboard/settings.js | 437 +++++++++--------- .../view/netifyd-dashboard/wizard.js | 420 +++++++++++++++++ .../menu.d/luci-app-netifyd-dashboard.json | 8 + .../acl.d/luci-app-netifyd-dashboard.json | 3 +- .../resources/network-modes/api.js | 12 - .../resources/view/network-modes/settings.js | 1 + 7 files changed, 661 insertions(+), 227 deletions(-) create mode 100644 luci-app-netifyd-dashboard/htdocs/luci-static/resources/view/netifyd-dashboard/wizard.js diff --git a/luci-app-netifyd-dashboard/htdocs/luci-static/resources/netifyd-dashboard/api.js b/luci-app-netifyd-dashboard/htdocs/luci-static/resources/netifyd-dashboard/api.js index 1af19ab3..3ca30f6e 100644 --- a/luci-app-netifyd-dashboard/htdocs/luci-static/resources/netifyd-dashboard/api.js +++ b/luci-app-netifyd-dashboard/htdocs/luci-static/resources/netifyd-dashboard/api.js @@ -40,6 +40,12 @@ var callProtocols = rpc.declare({ expect: { protocols: [] } }); +var callDevices = rpc.declare({ + object: 'luci.netifyd-dashboard', + method: 'devices', + expect: { devices: [] } +}); + var callStats = rpc.declare({ object: 'luci.netifyd-dashboard', method: 'stats', @@ -72,6 +78,7 @@ return baseclass.extend({ getApplications: callApplications, getHosts: callHosts, getProtocols: callProtocols, + getDevices: callDevices, getStats: callStats, getSecuboxLogs: callSecuboxLogs, collectDebugSnapshot: callCollectDebug, diff --git a/luci-app-netifyd-dashboard/htdocs/luci-static/resources/view/netifyd-dashboard/settings.js b/luci-app-netifyd-dashboard/htdocs/luci-static/resources/view/netifyd-dashboard/settings.js index ae664ecd..5c59cb6a 100644 --- a/luci-app-netifyd-dashboard/htdocs/luci-static/resources/view/netifyd-dashboard/settings.js +++ b/luci-app-netifyd-dashboard/htdocs/luci-static/resources/view/netifyd-dashboard/settings.js @@ -12,239 +12,250 @@ return view.extend({ render: function(status) { status = status || {}; - var view = E('div', { 'class': 'cbi-map' }, [ - E('h2', {}, _('Netifyd Settings')), - E('div', { 'class': 'cbi-map-descr' }, - _('Configure and manage Netifyd deep packet inspection service.')), - - // Service Status - E('div', { 'class': 'cbi-section' }, [ - E('h3', {}, _('Service Status')), - E('div', { 'class': 'table cbi-section-table' }, [ - E('div', { 'class': 'tr cbi-section-table-row' }, [ - E('div', { 'class': 'td left', 'style': 'width: 33%; font-weight: bold;' }, _('Service Status')), - E('div', { 'class': 'td left' }, [ - E('span', { - 'class': 'badge', - 'style': 'background: ' + (status.running ? '#28a745' : '#dc3545') + '; color: white; padding: 0.25em 0.6em; border-radius: 3px;' - }, status.running ? _('Running') : _('Stopped')) - ]) - ]), - E('div', { 'class': 'tr cbi-section-table-row' }, [ - E('div', { 'class': 'td left', 'style': 'width: 33%; font-weight: bold;' }, _('Version')), - E('div', { 'class': 'td left' }, status.version || 'Unknown') - ]), - status.running ? E('div', { 'class': 'tr cbi-section-table-row' }, [ - E('div', { 'class': 'td left', 'style': 'width: 33%; font-weight: bold;' }, _('Process ID')), - E('div', { 'class': 'td left' }, [ - E('code', {}, (status.pid || 'N/A').toString()) - ]) - ]) : null, - status.running && status.uptime ? E('div', { 'class': 'tr cbi-section-table-row' }, [ - E('div', { 'class': 'td left', 'style': 'width: 33%; font-weight: bold;' }, _('Uptime')), - E('div', { 'class': 'td left' }, this.formatUptime(status.uptime)) - ]) : null, - status.running && status.memory_kb ? E('div', { 'class': 'tr cbi-section-table-row' }, [ - E('div', { 'class': 'td left', 'style': 'width: 33%; font-weight: bold;' }, _('Memory Usage')), - E('div', { 'class': 'td left' }, Math.round(status.memory_kb / 1024) + ' MB') - ]) : null, - E('div', { 'class': 'tr cbi-section-table-row' }, [ - E('div', { 'class': 'td left', 'style': 'width: 33%; font-weight: bold;' }, _('Monitored Interfaces')), - E('div', { 'class': 'td left' }, [ - status.interfaces && status.interfaces.length > 0 - ? status.interfaces.map(function(iface) { - return E('span', { - 'class': 'badge', - 'style': 'background: #0088cc; color: white; padding: 0.25em 0.6em; border-radius: 3px; margin-right: 0.5em;' - }, iface); - }) - : E('span', { 'style': 'color: #999;' }, _('None configured')) - ]) - ]) - ]) + var container = E('div', { + 'class': 'netifyd-settings', + 'style': 'max-width: 1200px; margin: 0 auto;' + }, [ + // Header + E('div', { 'style': 'margin-bottom: 2em;' }, [ + E('h1', { + 'style': 'font-size: 2em; margin: 0 0 0.5em 0; background: linear-gradient(135deg, #8b5cf6 0%, #3b82f6 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;' + }, _('Netifyd Settings')), + E('p', { 'style': 'color: #94a3b8; font-size: 1.05em;' }, + _('Configure and manage Netifyd deep packet inspection service')) ]), - // What is Netifyd - E('div', { 'class': 'cbi-section', 'style': 'margin-top: 2em;' }, [ - E('h3', {}, _('About Netifyd')), - E('div', { 'style': 'background: #f8f9fa; padding: 1em; border-radius: 4px;' }, [ - E('p', {}, _('Netifyd is a deep packet inspection (DPI) daemon that classifies network traffic by application protocol and category.')), - E('p', { 'style': 'margin-top: 0.5em;' }, _('It provides real-time insights into:')), - E('ul', { 'style': 'margin: 0.5em 0; padding-left: 2em;' }, [ - E('li', {}, _('Application detection (HTTP, HTTPS, DNS, SSH, etc.)')), - E('li', {}, _('Protocol identification (TCP, UDP, ICMP)')), - E('li', {}, _('Traffic categorization (Streaming, VoIP, Gaming, etc.)')), - E('li', {}, _('Device fingerprinting and tracking')), - E('li', {}, _('Bandwidth usage per application')) - ]), - E('p', { 'style': 'margin-top: 1em; padding: 0.75em; background: #e8f4f8; border-radius: 4px;' }, [ - E('strong', {}, _('Note:')), - ' ', - _('Netifyd uses kernel conntrack for flow tracking and deep packet inspection for application detection.') - ]) - ]) - ]), - - // Configuration Files - E('div', { 'class': 'cbi-section', 'style': 'margin-top: 2em;' }, [ - E('h3', {}, _('Configuration Files')), - E('div', { 'style': 'background: #f8f9fa; padding: 1em; border-radius: 4px;' }, [ - E('p', {}, [ - E('strong', {}, _('Main Configuration:')), - ' ', - E('code', {}, '/etc/netifyd.conf') - ]), - E('p', {}, [ - E('strong', {}, _('Service Configuration:')), - ' ', - E('code', {}, '/etc/config/netifyd') - ]), - E('p', {}, [ - E('strong', {}, _('Runtime Data:')), - ' ', - E('code', {}, '/var/run/netifyd/') - ]), - E('p', { 'style': 'margin-top: 1em; padding: 0.75em; background: #fff3cd; border-radius: 4px;' }, [ - E('strong', {}, _('Note:')), - ' ', - _('After modifying configuration files, restart netifyd from the command line.') - ]) - ]) - ]), - - // Common Configuration Examples - E('div', { 'class': 'cbi-section', 'style': 'margin-top: 2em;' }, [ - E('h3', {}, _('Common Configuration Examples')), - - // Monitor Specific Interfaces - E('div', { 'style': 'margin-bottom: 1.5em;' }, [ - E('h4', {}, _('Monitor Specific Interfaces')), - E('p', {}, _('Edit /etc/config/netifyd to specify which interfaces to monitor:')), - E('pre', { 'style': 'background: #f5f5f5; padding: 1em; border-radius: 4px; overflow-x: auto;' }, - 'config netifyd\n' + - ' option enabled \'1\'\n' + - ' list internal_if \'br-lan\'\n' + - ' list internal_if \'wlan0\'\n' + - ' list external_if \'eth0\'\n' - ), - E('p', { 'style': 'color: #666; font-size: 0.9em;' }, - _('Internal interfaces are monitored for client traffic, external for WAN traffic.')) + // Service Status Card + E('div', { 'style': 'background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 12px; padding: 2em; margin-bottom: 2em; border: 1px solid #334155;' }, [ + E('h2', { 'style': 'color: #f1f5f9; margin-top: 0; display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', {}, status.running ? '✅' : '⚠️'), + _('Service Status') ]), - // Enable Protocol Detection - E('div', { 'style': 'margin-bottom: 1.5em;' }, [ - E('h4', {}, _('Enable Advanced Detection')), - E('p', {}, _('Edit /etc/netifyd.conf for advanced DPI options:')), - E('pre', { 'style': 'background: #f5f5f5; padding: 1em; border-radius: 4px; overflow-x: auto;' }, - '# Enable deep packet inspection\n' + - 'enable_dpi=yes\n\n' + - '# Enable DNS resolution\n' + - 'enable_dns_hint=yes\n\n' + - '# Detection sensitivity (high, medium, low)\n' + - 'detection_sensitivity=high\n\n' + - '# Flow idle timeout (seconds)\n' + - 'flow_idle_timeout=300\n' + E('div', { 'style': 'display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.5em; margin-top: 1.5em;' }, [ + // Status + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.25em; border: 1px solid #1e293b;' }, [ + E('div', { 'style': 'color: #64748b; font-size: 0.9em; margin-bottom: 0.5em;' }, _('Status')), + E('div', { + 'class': 'badge', + 'style': 'display: inline-block; padding: 0.5em 1em; border-radius: 6px; font-weight: bold; background: ' + (status.running ? 'linear-gradient(135deg, #10b981, #059669)' : 'linear-gradient(135deg, #ef4444, #dc2626)') + '; color: white;' + }, status.running ? _('Running') : _('Stopped')) + ]), + + // Version + status.version ? E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.25em; border: 1px solid #1e293b;' }, [ + E('div', { 'style': 'color: #64748b; font-size: 0.9em; margin-bottom: 0.5em;' }, _('Version')), + E('div', { 'style': 'color: #8b5cf6; font-size: 1.5em; font-weight: bold;' }, status.version) + ]) : null, + + // Uptime + status.running && status.uptime ? E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.25em; border: 1px solid #1e293b;' }, [ + E('div', { 'style': 'color: #64748b; font-size: 0.9em; margin-bottom: 0.5em;' }, _('Uptime')), + E('div', { 'style': 'color: #3b82f6; font-size: 1.5em; font-weight: bold;' }, this.formatUptime(status.uptime)) + ]) : null, + + // Memory + status.running && status.memory_kb ? E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.25em; border: 1px solid #1e293b;' }, [ + E('div', { 'style': 'color: #64748b; font-size: 0.9em; margin-bottom: 0.5em;' }, _('Memory')), + E('div', { 'style': 'color: #06b6d4; font-size: 1.5em; font-weight: bold;' }, Math.round(status.memory_kb / 1024) + ' MB') + ]) : null + ]), + + // Monitored Interfaces + status.interfaces && status.interfaces.length > 0 ? E('div', { 'style': 'margin-top: 1.5em; padding-top: 1.5em; border-top: 1px solid #1e293b;' }, [ + E('div', { 'style': 'color: #cbd5e1; font-size: 0.95em; margin-bottom: 1em;' }, _('Monitored Interfaces')), + E('div', { 'style': 'display: flex; gap: 0.75em; flex-wrap: wrap;' }, + status.interfaces.map(function(iface) { + return E('span', { + 'style': 'background: linear-gradient(135deg, #8b5cf6, #3b82f6); color: white; padding: 0.5em 1em; border-radius: 6px; font-weight: 500;' + }, iface); + }) ) + ]) : null + ]), + + // Configuration Info + E('div', { 'style': 'background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 12px; padding: 2em; margin-bottom: 2em; border: 1px solid #334155;' }, [ + E('h2', { 'style': 'color: #f1f5f9; margin-top: 0; display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', {}, '⚙️'), + _('Configuration Files') ]), - // Performance Tuning - E('div', { 'style': 'margin-bottom: 1.5em;' }, [ - E('h4', {}, _('Performance Tuning')), - E('p', {}, _('Adjust resource usage in /etc/netifyd.conf:')), - E('pre', { 'style': 'background: #f5f5f5; padding: 1em; border-radius: 4px; overflow-x: auto;' }, - '# Maximum flows to track\n' + - 'max_flows=65536\n\n' + - '# Thread pool size\n' + - 'thread_pool_size=4\n\n' + - '# Flow hash table size\n' + - 'flow_hash_size=32768\n' - ), - E('p', { 'style': 'color: #666; font-size: 0.9em;' }, - _('Reduce values on low-memory devices, increase for high-traffic networks.')) + E('div', { 'style': 'display: grid; gap: 1em; margin-top: 1.5em;' }, [ + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.25em; border: 1px solid #1e293b; display: flex; justify-content: space-between; align-items: center;' }, [ + E('div', {}, [ + E('div', { 'style': 'color: #cbd5e1; font-weight: 500; margin-bottom: 0.25em;' }, _('Main Configuration')), + E('div', { 'style': 'color: #64748b; font-size: 0.9em;' }, _('Service and interface settings')) + ]), + E('code', { 'style': 'color: #8b5cf6; background: #020617; padding: 0.5em 1em; border-radius: 4px; font-size: 0.95em;' }, '/etc/netifyd.conf') + ]), + + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.25em; border: 1px solid #1e293b; display: flex; justify-content: space-between; align-items: center;' }, [ + E('div', {}, [ + E('div', { 'style': 'color: #cbd5e1; font-weight: 500; margin-bottom: 0.25em;' }, _('UCI Configuration')), + E('div', { 'style': 'color: #64748b; font-size: 0.9em;' }, _('OpenWrt system integration')) + ]), + E('code', { 'style': 'color: #3b82f6; background: #020617; padding: 0.5em 1em; border-radius: 4px; font-size: 0.95em;' }, '/etc/config/netifyd') + ]), + + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.25em; border: 1px solid #1e293b; display: flex; justify-content: space-between; align-items: center;' }, [ + E('div', {}, [ + E('div', { 'style': 'color: #cbd5e1; font-weight: 500; margin-bottom: 0.25em;' }, _('Runtime Data')), + E('div', { 'style': 'color: #64748b; font-size: 0.9em;' }, _('Real-time flow and status data')) + ]), + E('code', { 'style': 'color: #06b6d4; background: #020617; padding: 0.5em 1em; border-radius: 4px; font-size: 0.95em;' }, '/var/run/netifyd/') + ]) + ]), + + E('div', { 'style': 'background: linear-gradient(135deg, #92400e, #b45309); border-radius: 8px; padding: 1.25em; margin-top: 1.5em; border: 1px solid #f59e0b;' }, [ + E('div', { 'style': 'display: flex; align-items: flex-start; gap: 0.75em;' }, [ + E('span', { 'style': 'font-size: 1.3em; flex-shrink: 0;' }, '⚠️'), + E('div', {}, [ + E('strong', { 'style': 'color: #fcd34d; font-size: 1.05em;' }, _('Note')), + E('p', { 'style': 'color: #fde68a; margin: 0.5em 0 0 0;' }, + _('After modifying configuration files, restart netifyd from the command line:') + ' ' + + E('code', { 'style': 'background: #451a03; padding: 0.25em 0.5em; border-radius: 3px;' }, '/etc/init.d/netifyd restart')) + ]) + ]) ]) ]), - // Useful Commands - E('div', { 'class': 'cbi-section', 'style': 'margin-top: 2em; background: #e8f4f8; padding: 1em;' }, [ - E('h3', {}, _('Useful Commands')), - E('pre', { 'style': 'background: white; padding: 1em; border-radius: 4px; overflow-x: auto;' }, [ - '# Service control\n', - '/etc/init.d/netifyd start\n', - '/etc/init.d/netifyd stop\n', - '/etc/init.d/netifyd restart\n', - '/etc/init.d/netifyd status\n', - '\n', - '# View logs\n', - 'logread | grep netifyd\n', - '\n', - '# Check version\n', - 'netifyd --version\n', - '\n', - '# View current flows\n', - 'cat /var/run/netifyd/flows.json\n', - '\n', - '# Check process status\n', - 'ps | grep netifyd\n', - 'top -n 1 | grep netifyd\n', - '\n', - '# Debug mode\n', - 'netifyd -d -I br-lan\n' + // Quick Commands + E('div', { 'style': 'background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 12px; padding: 2em; margin-bottom: 2em; border: 1px solid #334155;' }, [ + E('h2', { 'style': 'color: #f1f5f9; margin-top: 0; display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', {}, '💻'), + _('Useful Commands') + ]), + + E('div', { 'style': 'background: #020617; border-radius: 8px; padding: 1.5em; margin-top: 1.5em; border: 1px solid #1e293b;' }, [ + E('pre', { + 'style': 'color: #e2e8f0; margin: 0; font-family: monospace; font-size: 0.95em; line-height: 1.8;' + }, [ + E('div', { 'style': 'color: #64748b;' }, '# Service control'), + '/etc/init.d/netifyd start\n', + '/etc/init.d/netifyd stop\n', + '/etc/init.d/netifyd restart\n', + '/etc/init.d/netifyd status\n\n', + E('div', { 'style': 'color: #64748b;' }, '# View logs'), + 'logread | grep netifyd\n\n', + E('div', { 'style': 'color: #64748b;' }, '# Check version'), + 'netifyd --version\n\n', + E('div', { 'style': 'color: #64748b;' }, '# View current flows'), + 'cat /var/run/netifyd/flows.json' + ]) ]) ]), - // Integration & API - E('div', { 'class': 'cbi-section', 'style': 'margin-top: 2em;' }, [ - E('h3', {}, _('Integration & API')), - E('div', { 'style': 'background: #f8f9fa; padding: 1em; border-radius: 4px;' }, [ - E('p', {}, _('Netifyd provides a Unix socket interface for real-time data access:')), - E('ul', { 'style': 'margin: 0.5em 0; padding-left: 2em;' }, [ - E('li', {}, [ - E('strong', {}, _('Socket:')), - ' ', - E('code', {}, '/var/run/netifyd/netifyd.sock') - ]), - E('li', {}, [ - E('strong', {}, _('Status JSON:')), - ' ', - E('code', {}, '/var/run/netifyd/status.json') - ]), - E('li', {}, [ - E('strong', {}, _('Flows JSON:')), - ' ', - E('code', {}, '/var/run/netifyd/flows.json') + // Documentation Section (Collapsed by default) + E('details', { 'style': 'background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 12px; padding: 2em; margin-bottom: 2em; border: 1px solid #334155;' }, [ + E('summary', { + 'style': 'color: #f1f5f9; font-size: 1.3em; font-weight: bold; cursor: pointer; display: flex; align-items: center; gap: 0.5em; user-select: none;' + }, [ + E('span', {}, '📚'), + _('Documentation & Resources') + ]), + + E('div', { 'style': 'margin-top: 2em;' }, [ + // About Netifyd + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.5em; margin-bottom: 1.5em; border: 1px solid #1e293b;' }, [ + E('h3', { 'style': 'color: #cbd5e1; margin-top: 0;' }, _('What is Netifyd?')), + E('p', { 'style': 'color: #94a3b8; line-height: 1.6;' }, + _('Netifyd is a deep packet inspection (DPI) daemon that classifies network traffic by application protocol and category. It provides real-time insights into network activity without relying on cloud services.')), + + E('div', { 'style': 'display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1em; margin-top: 1em;' }, [ + E('div', { 'style': 'background: #020617; padding: 1em; border-radius: 6px; border-left: 3px solid #8b5cf6;' }, [ + E('div', { 'style': 'color: #8b5cf6; font-weight: bold; margin-bottom: 0.5em;' }, '300+'), + E('div', { 'style': 'color: #94a3b8; font-size: 0.9em;' }, _('Protocol Signatures')) + ]), + E('div', { 'style': 'background: #020617; padding: 1em; border-radius: 6px; border-left: 3px solid #3b82f6;' }, [ + E('div', { 'style': 'color: #3b82f6; font-weight: bold; margin-bottom: 0.5em;' }, '1000+'), + E('div', { 'style': 'color: #94a3b8; font-size: 0.9em;' }, _('Application Signatures')) + ]), + E('div', { 'style': 'background: #020617; padding: 1em; border-radius: 6px; border-left: 3px solid #10b981;' }, [ + E('div', { 'style': 'color: #10b981; font-weight: bold; margin-bottom: 0.5em;' }, _('Real-time')), + E('div', { 'style': 'color: #94a3b8; font-size: 0.9em;' }, _('DPI Classification')) + ]) ]) ]), - E('p', { 'style': 'margin-top: 1em;' }, _('This dashboard uses the RPCD backend to parse conntrack data and provide DPI insights.')), - E('p', { 'style': 'margin-top: 0.5em; color: #666; font-size: 0.9em;' }, - _('For advanced integrations, consider using netify-fwa (Flow Web API) for RESTful access to flow data.')) - ]) - ]), - // Documentation Links - E('div', { 'class': 'cbi-section', 'style': 'margin-top: 2em;' }, [ - E('h3', {}, _('Documentation & Resources')), - E('ul', { 'style': 'margin-top: 0.5em;' }, [ - E('li', {}, [ - E('a', { 'href': 'https://www.netify.ai/', 'target': '_blank' }, - _('Official Netify Website')) + // Configuration Examples + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.5em; margin-bottom: 1.5em; border: 1px solid #1e293b;' }, [ + E('h3', { 'style': 'color: #cbd5e1; margin-top: 0;' }, _('Configuration Examples')), + + E('div', { 'style': 'margin-bottom: 1.5em;' }, [ + E('h4', { 'style': 'color: #8b5cf6; margin: 0.5em 0;' }, _('Monitor Specific Interfaces')), + E('pre', { + 'style': 'background: #020617; color: #e2e8f0; padding: 1em; border-radius: 6px; overflow-x: auto; border: 1px solid #1e293b; margin: 0.5em 0;' + }, + 'config netifyd\n' + + ' option enabled \'1\'\n' + + ' list internal_if \'br-lan\'\n' + + ' list internal_if \'wlan0\'\n' + + ' list external_if \'eth0\'' + ) + ]), + + E('div', { 'style': 'margin-bottom: 1.5em;' }, [ + E('h4', { 'style': 'color: #3b82f6; margin: 0.5em 0;' }, _('Advanced DPI Options')), + E('pre', { + 'style': 'background: #020617; color: #e2e8f0; padding: 1em; border-radius: 6px; overflow-x: auto; border: 1px solid #1e293b; margin: 0.5em 0;' + }, + 'enable_dpi=yes\n' + + 'enable_dns_hint=yes\n' + + 'detection_sensitivity=high\n' + + 'flow_idle_timeout=300' + ) + ]), + + E('div', {}, [ + E('h4', { 'style': 'color: #10b981; margin: 0.5em 0;' }, _('Performance Tuning')), + E('pre', { + 'style': 'background: #020617; color: #e2e8f0; padding: 1em; border-radius: 6px; overflow-x: auto; border: 1px solid #1e293b; margin: 0.5em 0;' + }, + 'max_flows=65536\n' + + 'thread_pool_size=4\n' + + 'flow_hash_size=32768' + ), + E('div', { 'style': 'color: #64748b; font-size: 0.9em; margin-top: 0.5em; font-style: italic;' }, + _('💡 Reduce values on low-memory devices')) + ]) ]), - E('li', {}, [ - E('a', { 'href': 'https://gitlab.com/netify.ai/public/netify-daemon', 'target': '_blank' }, - _('Netifyd GitLab Repository')) - ]), - E('li', {}, [ - E('a', { 'href': 'https://www.netify.ai/documentation', 'target': '_blank' }, - _('Netify Documentation')) - ]), - E('li', {}, [ - E('a', { 'href': 'https://openwrt.org/packages/pkgdata/netifyd', 'target': '_blank' }, - _('OpenWrt Package Info')) + + // Resources + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.5em; border: 1px solid #1e293b;' }, [ + E('h3', { 'style': 'color: #cbd5e1; margin-top: 0;' }, _('External Resources')), + E('div', { 'style': 'display: grid; gap: 0.75em;' }, [ + E('a', { + 'href': 'https://www.netify.ai/', + 'target': '_blank', + 'style': 'color: #8b5cf6; text-decoration: none; display: flex; align-items: center; gap: 0.5em; padding: 0.75em; background: #020617; border-radius: 6px; border: 1px solid #1e293b;' + }, [ + E('span', {}, '🔗'), + _('Official Netify Website') + ]), + E('a', { + 'href': 'https://www.netify.ai/documentation', + 'target': '_blank', + 'style': 'color: #3b82f6; text-decoration: none; display: flex; align-items: center; gap: 0.5em; padding: 0.75em; background: #020617; border-radius: 6px; border: 1px solid #1e293b;' + }, [ + E('span', {}, '📖'), + _('Netify Documentation') + ]), + E('a', { + 'href': 'https://gitlab.com/netify.ai/public/netify-daemon', + 'target': '_blank', + 'style': 'color: #06b6d4; text-decoration: none; display: flex; align-items: center; gap: 0.5em; padding: 0.75em; background: #020617; border-radius: 6px; border: 1px solid #1e293b;' + }, [ + E('span', {}, '💻'), + _('GitLab Repository') + ]) + ]) ]) ]) ]) ]); - return view; + return container; }, formatUptime: function(seconds) { @@ -252,13 +263,11 @@ return view.extend({ var d = Math.floor(seconds / 86400); var h = Math.floor((seconds % 86400) / 3600); var m = Math.floor((seconds % 3600) / 60); - var s = seconds % 60; var parts = []; if (d > 0) parts.push(d + 'd'); if (h > 0) parts.push(h + 'h'); if (m > 0) parts.push(m + 'm'); - if (s > 0 && parts.length === 0) parts.push(s + 's'); - return parts.join(' ') || '0s'; + return parts.join(' ') || '< 1m'; }, handleSaveApply: null, diff --git a/luci-app-netifyd-dashboard/htdocs/luci-static/resources/view/netifyd-dashboard/wizard.js b/luci-app-netifyd-dashboard/htdocs/luci-static/resources/view/netifyd-dashboard/wizard.js new file mode 100644 index 00000000..80d3a9e7 --- /dev/null +++ b/luci-app-netifyd-dashboard/htdocs/luci-static/resources/view/netifyd-dashboard/wizard.js @@ -0,0 +1,420 @@ +'use strict'; +'require view'; +'require ui'; +'require rpc'; +'require secubox-theme/theme as Theme'; +'require netifyd-dashboard.api as API'; + +return view.extend({ + currentStep: 1, + totalSteps: 4, + + load: function() { + return API.getStatus(); + }, + + render: function(status) { + var self = this; + status = status || {}; + + var container = E('div', { + 'class': 'netifyd-wizard-container', + 'style': 'max-width: 900px; margin: 2em auto; padding: 2em;' + }, [ + // Header + E('div', { 'style': 'text-align: center; margin-bottom: 3em;' }, [ + E('div', { + 'style': 'font-size: 3em; margin-bottom: 0.5em;' + }, '🔍'), + E('h1', { + 'style': 'font-size: 2.5em; margin: 0.2em 0; background: linear-gradient(135deg, #8b5cf6 0%, #3b82f6 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent;' + }, 'Netifyd Setup Wizard'), + E('p', { + 'style': 'color: #94a3b8; font-size: 1.1em; margin-top: 0.5em;' + }, 'Deep Packet Inspection for OpenWrt') + ]), + + // Progress Bar + this.renderProgressBar(), + + // Steps Container + E('div', { 'id': 'wizard-steps', 'style': 'margin-top: 3em;' }, [ + this.renderStep1(status), + this.renderStep2(status), + this.renderStep3(status), + this.renderStep4(status) + ]), + + // Navigation + this.renderNavigation() + ]); + + return container; + }, + + renderProgressBar: function() { + var steps = ['Check Status', 'Install', 'Configure', 'Verify']; + + return E('div', { 'style': 'display: flex; justify-content: space-between; align-items: center; margin: 2em 0; position: relative;' }, [ + E('div', { + 'style': 'position: absolute; top: 20px; left: 0; right: 0; height: 2px; background: #1e293b; z-index: 0;' + }), + E('div', { + 'id': 'progress-fill', + 'style': 'position: absolute; top: 20px; left: 0; height: 2px; background: linear-gradient(90deg, #8b5cf6, #3b82f6); transition: width 0.3s ease; z-index: 1; width: ' + ((this.currentStep - 1) / (this.totalSteps - 1) * 100) + '%;' + }), + steps.map(function(step, index) { + var stepNum = index + 1; + var isActive = stepNum === this.currentStep; + var isComplete = stepNum < this.currentStep; + + return E('div', { + 'style': 'display: flex; flex-direction: column; align-items: center; z-index: 2; position: relative;' + }, [ + E('div', { + 'class': 'wizard-step-circle', + 'style': 'width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; border: 2px solid ' + (isComplete ? '#8b5cf6' : isActive ? '#3b82f6' : '#1e293b') + '; background: ' + (isComplete ? '#8b5cf6' : isActive ? '#1e293b' : '#0f172a') + '; color: ' + (isComplete || isActive ? 'white' : '#475569') + '; transition: all 0.3s ease;' + }, isComplete ? '✓' : stepNum), + E('div', { + 'style': 'margin-top: 0.5em; font-size: 0.9em; color: ' + (isActive ? '#3b82f6' : isComplete ? '#8b5cf6' : '#64748b') + '; font-weight: ' + (isActive ? 'bold' : 'normal') + ';' + }, step) + ]); + }.bind(this)) + ]); + }, + + renderStep1: function(status) { + return E('div', { + 'id': 'step-1', + 'class': 'wizard-step', + 'style': 'display: ' + (this.currentStep === 1 ? 'block' : 'none') + ';' + }, [ + E('div', { 'style': 'background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 12px; padding: 2em; border: 1px solid #334155;' }, [ + E('h2', { 'style': 'color: #f1f5f9; margin-top: 0; display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', {}, '✅'), + 'Step 1: Check Installation' + ]), + + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.5em; margin: 1.5em 0; border: 1px solid #1e293b;' }, [ + E('div', { 'style': 'display: flex; justify-content: space-between; align-items: center; margin-bottom: 1em;' }, [ + E('span', { 'style': 'color: #cbd5e1; font-size: 1.1em;' }, 'Netifyd Service Status'), + E('span', { + 'class': 'badge', + 'style': 'padding: 0.5em 1em; border-radius: 6px; font-weight: bold; background: ' + (status.running ? 'linear-gradient(135deg, #10b981, #059669)' : 'linear-gradient(135deg, #ef4444, #dc2626)') + '; color: white;' + }, status.running ? '✓ Running' : '✗ Stopped') + ]), + + status.version ? E('div', { 'style': 'color: #94a3b8; margin-top: 0.5em;' }, [ + 'Version: ', + E('code', { 'style': 'color: #8b5cf6; background: #1e293b; padding: 0.25em 0.5em; border-radius: 4px;' }, status.version) + ]) : null, + + status.running && status.pid ? E('div', { 'style': 'color: #94a3b8; margin-top: 0.5em;' }, [ + 'Process ID: ', + E('code', { 'style': 'color: #3b82f6; background: #1e293b; padding: 0.25em 0.5em; border-radius: 4px;' }, status.pid) + ]) : null + ]), + + status.running ? E('div', { 'style': 'background: linear-gradient(135deg, #064e3b, #065f46); border-radius: 8px; padding: 1.5em; margin-top: 1.5em; border: 1px solid #10b981;' }, [ + E('div', { 'style': 'display: flex; align-items: center; gap: 0.5em; margin-bottom: 0.5em;' }, [ + E('span', { 'style': 'font-size: 1.5em;' }, '✓'), + E('strong', { 'style': 'color: #d1fae5; font-size: 1.1em;' }, 'Netifyd is installed and running') + ]), + E('p', { 'style': 'color: #a7f3d0; margin: 0.5em 0 0 2em;' }, 'You can proceed to the next step to configure monitoring.') + ]) : E('div', { 'style': 'background: linear-gradient(135deg, #7f1d1d, #991b1b); border-radius: 8px; padding: 1.5em; margin-top: 1.5em; border: 1px solid #ef4444;' }, [ + E('div', { 'style': 'display: flex; align-items: center; gap: 0.5em; margin-bottom: 0.5em;' }, [ + E('span', { 'style': 'font-size: 1.5em;' }, '⚠️'), + E('strong', { 'style': 'color: #fecaca; font-size: 1.1em;' }, 'Netifyd is not installed') + ]), + E('p', { 'style': 'color: #fca5a5; margin: 0.5em 0 0 2em;' }, 'Please proceed to Step 2 to install it.') + ]) + ]) + ]); + }, + + renderStep2: function(status) { + return E('div', { + 'id': 'step-2', + 'class': 'wizard-step', + 'style': 'display: ' + (this.currentStep === 2 ? 'block' : 'none') + ';' + }, [ + E('div', { 'style': 'background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 12px; padding: 2em; border: 1px solid #334155;' }, [ + E('h2', { 'style': 'color: #f1f5f9; margin-top: 0; display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', {}, '📦'), + 'Step 2: Install Netifyd' + ]), + + E('p', { 'style': 'color: #cbd5e1; font-size: 1.05em; line-height: 1.6;' }, + 'Netifyd is a deep packet inspection daemon that provides real-time network intelligence. It detects applications, protocols, and devices on your network.'), + + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.5em; margin: 1.5em 0; border: 1px solid #1e293b;' }, [ + E('h3', { 'style': 'color: #f1f5f9; margin-top: 0; display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', {}, '💡'), + 'Installation via SSH' + ]), + E('p', { 'style': 'color: #94a3b8; margin-bottom: 1em;' }, 'Connect to your router via SSH and run these commands:'), + + E('pre', { 'style': 'background: #020617; color: #e2e8f0; padding: 1em; border-radius: 6px; overflow-x: auto; border: 1px solid #1e293b;' }, + '# Update package lists\n' + + 'opkg update\n\n' + + '# Install netifyd\n' + + 'opkg install netifyd\n\n' + + '# Enable service at boot\n' + + '/etc/init.d/netifyd enable\n\n' + + '# Start the service\n' + + '/etc/init.d/netifyd start' + ) + ]), + + E('div', { 'style': 'background: linear-gradient(135deg, #1e3a8a, #1e40af); border-radius: 8px; padding: 1.5em; margin-top: 1.5em; border: 1px solid #3b82f6;' }, [ + E('div', { 'style': 'display: flex; align-items: flex-start; gap: 0.75em;' }, [ + E('span', { 'style': 'font-size: 1.3em; flex-shrink: 0;' }, 'ℹ️'), + E('div', {}, [ + E('strong', { 'style': 'color: #dbeafe; font-size: 1.05em;' }, 'System Requirements'), + E('ul', { 'style': 'color: #bfdbfe; margin: 0.5em 0; padding-left: 1.5em;' }, [ + E('li', {}, 'OpenWrt 21.02 or later'), + E('li', {}, 'At least 128MB RAM'), + E('li', {}, '~5MB storage space'), + E('li', {}, 'Active network interfaces to monitor') + ]) + ]) + ]) + ]) + ]) + ]); + }, + + renderStep3: function(status) { + return E('div', { + 'id': 'step-3', + 'class': 'wizard-step', + 'style': 'display: ' + (this.currentStep === 3 ? 'block' : 'none') + ';' + }, [ + E('div', { 'style': 'background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 12px; padding: 2em; border: 1px solid #334155;' }, [ + E('h2', { 'style': 'color: #f1f5f9; margin-top: 0; display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', {}, '⚙️'), + 'Step 3: Configure Monitoring' + ]), + + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.5em; margin: 1.5em 0; border: 1px solid #1e293b;' }, [ + E('h3', { 'style': 'color: #f1f5f9; margin-top: 0;' }, 'Configure Monitored Interfaces'), + E('p', { 'style': 'color: #94a3b8;' }, 'Edit /etc/config/netifyd to specify which interfaces to monitor:'), + + E('pre', { 'style': 'background: #020617; color: #e2e8f0; padding: 1em; border-radius: 6px; overflow-x: auto; border: 1px solid #1e293b; margin: 1em 0;' }, + 'config netifyd\n' + + ' option enabled \'1\'\n' + + ' list internal_if \'br-lan\' # LAN bridge\n' + + ' list internal_if \'wlan0\' # WiFi\n' + + ' list external_if \'eth0\' # WAN interface' + ), + + E('p', { 'style': 'color: #64748b; font-size: 0.95em; font-style: italic;' }, + '💡 Tip: Internal interfaces are monitored for client traffic, external for WAN traffic.') + ]), + + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.5em; margin: 1.5em 0; border: 1px solid #1e293b;' }, [ + E('h3', { 'style': 'color: #f1f5f9; margin-top: 0;' }, 'Advanced Configuration (Optional)'), + E('p', { 'style': 'color: #94a3b8;' }, 'Edit /etc/netifyd.conf for advanced DPI options:'), + + E('pre', { 'style': 'background: #020617; color: #e2e8f0; padding: 1em; border-radius: 6px; overflow-x: auto; border: 1px solid #1e293b; margin: 1em 0;' }, + '# Enable deep packet inspection\n' + + 'enable_dpi=yes\n\n' + + '# Enable DNS resolution hints\n' + + 'enable_dns_hint=yes\n\n' + + '# Detection sensitivity (high, medium, low)\n' + + 'detection_sensitivity=high\n\n' + + '# Flow idle timeout in seconds\n' + + 'flow_idle_timeout=300' + ) + ]), + + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.5em; margin: 1.5em 0; border: 1px solid #1e293b;' }, [ + E('h3', { 'style': 'color: #f1f5f9; margin-top: 0;' }, 'Apply Configuration'), + E('p', { 'style': 'color: #94a3b8;' }, 'After making changes, restart netifyd:'), + + E('pre', { 'style': 'background: #020617; color: #e2e8f0; padding: 1em; border-radius: 6px; overflow-x: auto; border: 1px solid #1e293b; margin: 1em 0;' }, + '/etc/init.d/netifyd restart' + ) + ]) + ]) + ]); + }, + + renderStep4: function(status) { + return E('div', { + 'id': 'step-4', + 'class': 'wizard-step', + 'style': 'display: ' + (this.currentStep === 4 ? 'block' : 'none') + ';' + }, [ + E('div', { 'style': 'background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 12px; padding: 2em; border: 1px solid #334155;' }, [ + E('h2', { 'style': 'color: #f1f5f9; margin-top: 0; display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', {}, '🎉'), + 'Step 4: Verify & Explore' + ]), + + status.running ? E('div', { 'style': 'background: linear-gradient(135deg, #064e3b, #065f46); border-radius: 8px; padding: 2em; margin: 1.5em 0; border: 1px solid #10b981; text-align: center;' }, [ + E('div', { 'style': 'font-size: 4em; margin-bottom: 0.5em;' }, '✓'), + E('h3', { 'style': 'color: #d1fae5; margin: 0.5em 0; font-size: 1.5em;' }, 'Setup Complete!'), + E('p', { 'style': 'color: #a7f3d0; font-size: 1.1em; margin: 1em 0;' }, + 'Netifyd is running and monitoring your network traffic.'), + + E('div', { 'style': 'display: flex; gap: 1em; justify-content: center; flex-wrap: wrap; margin-top: 2em;' }, [ + E('div', { 'style': 'background: #0f172a; padding: 1em 1.5em; border-radius: 8px; border: 1px solid #10b981;' }, [ + E('div', { 'style': 'font-size: 2em; color: #10b981;' }, status.interfaces ? status.interfaces.length : 0), + E('div', { 'style': 'color: #a7f3d0; font-size: 0.9em; margin-top: 0.25em;' }, 'Interfaces') + ]), + status.version ? E('div', { 'style': 'background: #0f172a; padding: 1em 1.5em; border-radius: 8px; border: 1px solid #10b981;' }, [ + E('div', { 'style': 'font-size: 2em; color: #10b981;' }, status.version), + E('div', { 'style': 'color: #a7f3d0; font-size: 0.9em; margin-top: 0.25em;' }, 'Version') + ]) : null + ]) + ]) : E('div', { 'style': 'background: linear-gradient(135deg, #7f1d1d, #991b1b); border-radius: 8px; padding: 2em; margin: 1.5em 0; border: 1px solid #ef4444; text-align: center;' }, [ + E('div', { 'style': 'font-size: 4em; margin-bottom: 0.5em;' }, '⚠️'), + E('h3', { 'style': 'color: #fecaca; margin: 0.5em 0; font-size: 1.5em;' }, 'Service Not Running'), + E('p', { 'style': 'color: #fca5a5; font-size: 1.1em;' }, + 'Please complete Steps 2 and 3 to install and start Netifyd.') + ]), + + E('div', { 'style': 'background: #0f172a; border-radius: 8px; padding: 1.5em; margin: 1.5em 0; border: 1px solid #1e293b;' }, [ + E('h3', { 'style': 'color: #f1f5f9; margin-top: 0; display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', {}, '🚀'), + 'Next Steps' + ]), + E('ul', { 'style': 'color: #cbd5e1; line-height: 1.8; margin: 1em 0;' }, [ + E('li', {}, [ + E('strong', { 'style': 'color: #8b5cf6;' }, 'Overview:'), + ' Real-time statistics and protocol distribution' + ]), + E('li', {}, [ + E('strong', { 'style': 'color: #3b82f6;' }, 'Applications:'), + ' Detected applications with traffic breakdown' + ]), + E('li', {}, [ + E('strong', { 'style': 'color: #06b6d4;' }, 'Devices:'), + ' Network device discovery and identification' + ]), + E('li', {}, [ + E('strong', { 'style': 'color: #10b981;' }, 'Flows:'), + ' Live connection tracking with DPI data' + ]), + E('li', {}, [ + E('strong', { 'style': 'color: #f59e0b;' }, 'Top Talkers:'), + ' Bandwidth usage by host' + ]) + ]) + ]), + + E('div', { 'style': 'background: linear-gradient(135deg, #1e3a8a, #1e40af); border-radius: 8px; padding: 1.5em; margin-top: 1.5em; border: 1px solid #3b82f6;' }, [ + E('h3', { 'style': 'color: #dbeafe; margin-top: 0;' }, '📚 Learn More'), + E('div', { 'style': 'display: grid; gap: 0.75em;' }, [ + E('a', { + 'href': 'https://www.netify.ai/', + 'target': '_blank', + 'style': 'color: #93c5fd; text-decoration: none; display: flex; align-items: center; gap: 0.5em;' + }, [ + E('span', {}, '🔗'), + 'Official Netify Website' + ]), + E('a', { + 'href': 'https://www.netify.ai/documentation', + 'target': '_blank', + 'style': 'color: #93c5fd; text-decoration: none; display: flex; align-items: center; gap: 0.5em;' + }, [ + E('span', {}, '📖'), + 'Netify Documentation' + ]), + E('a', { + 'href': 'https://gitlab.com/netify.ai/public/netify-daemon', + 'target': '_blank', + 'style': 'color: #93c5fd; text-decoration: none; display: flex; align-items: center; gap: 0.5em;' + }, [ + E('span', {}, '💻'), + 'Netifyd GitLab Repository' + ]) + ]) + ]) + ]) + ]); + }, + + renderNavigation: function() { + var self = this; + + return E('div', { + 'style': 'display: flex; justify-content: space-between; margin-top: 3em; padding-top: 2em; border-top: 1px solid #334155;' + }, [ + E('button', { + 'class': 'cbi-button cbi-button-neutral', + 'style': 'padding: 0.75em 2em; font-size: 1em; background: #1e293b; border: 1px solid #334155; color: #cbd5e1; border-radius: 6px; cursor: pointer; display: ' + (this.currentStep === 1 ? 'none' : 'block') + ';', + 'click': function() { + if (self.currentStep > 1) { + self.currentStep--; + self.updateView(); + } + } + }, '← Previous'), + + E('div', { 'style': 'flex: 1;' }), + + this.currentStep < this.totalSteps ? E('button', { + 'class': 'cbi-button cbi-button-action', + 'style': 'padding: 0.75em 2em; font-size: 1em; background: linear-gradient(135deg, #8b5cf6, #3b82f6); border: none; color: white; border-radius: 6px; cursor: pointer; font-weight: bold;', + 'click': function() { + if (self.currentStep < self.totalSteps) { + self.currentStep++; + self.updateView(); + } + } + }, 'Next →') : E('a', { + 'href': L.url('admin/secubox/security/netifyd/overview'), + 'class': 'cbi-button cbi-button-positive', + 'style': 'padding: 0.75em 2em; font-size: 1em; background: linear-gradient(135deg, #10b981, #059669); border: none; color: white; border-radius: 6px; text-decoration: none; font-weight: bold; display: inline-block;' + }, 'Go to Dashboard →') + ]); + }, + + updateView: function() { + // Hide all steps + for (var i = 1; i <= this.totalSteps; i++) { + var step = document.getElementById('step-' + i); + if (step) step.style.display = 'none'; + } + + // Show current step + var currentStep = document.getElementById('step-' + this.currentStep); + if (currentStep) currentStep.style.display = 'block'; + + // Update progress bar + var progressFill = document.getElementById('progress-fill'); + if (progressFill) { + progressFill.style.width = ((this.currentStep - 1) / (this.totalSteps - 1) * 100) + '%'; + } + + // Update step circles + var circles = document.querySelectorAll('.wizard-step-circle'); + circles.forEach(function(circle, index) { + var stepNum = index + 1; + var isActive = stepNum === this.currentStep; + var isComplete = stepNum < this.currentStep; + + circle.style.borderColor = isComplete ? '#8b5cf6' : isActive ? '#3b82f6' : '#1e293b'; + circle.style.background = isComplete ? '#8b5cf6' : isActive ? '#1e293b' : '#0f172a'; + circle.style.color = isComplete || isActive ? 'white' : '#475569'; + circle.textContent = isComplete ? '✓' : stepNum; + }.bind(this)); + + // Re-render to update navigation buttons + var container = document.querySelector('.netifyd-wizard-container'); + if (container) { + var nav = container.querySelector('.netifyd-wizard-container > div:last-child'); + if (nav && nav.style.display === 'flex') { + var newNav = this.renderNavigation(); + nav.replaceWith(newNav); + } + } + }, + + handleSaveApply: null, + handleSave: null, + handleReset: null +}); diff --git a/luci-app-netifyd-dashboard/root/usr/share/luci/menu.d/luci-app-netifyd-dashboard.json b/luci-app-netifyd-dashboard/root/usr/share/luci/menu.d/luci-app-netifyd-dashboard.json index 3d70e914..5313f930 100644 --- a/luci-app-netifyd-dashboard/root/usr/share/luci/menu.d/luci-app-netifyd-dashboard.json +++ b/luci-app-netifyd-dashboard/root/usr/share/luci/menu.d/luci-app-netifyd-dashboard.json @@ -9,6 +9,14 @@ "acl": ["luci-app-netifyd-dashboard"] } }, + "admin/secubox/security/netifyd/wizard": { + "title": "Setup Wizard", + "order": 5, + "action": { + "type": "view", + "path": "netifyd-dashboard/wizard" + } + }, "admin/secubox/security/netifyd/overview": { "title": "Overview", "order": 10, diff --git a/luci-app-netifyd-dashboard/root/usr/share/rpcd/acl.d/luci-app-netifyd-dashboard.json b/luci-app-netifyd-dashboard/root/usr/share/rpcd/acl.d/luci-app-netifyd-dashboard.json index d8dd549e..f787990f 100644 --- a/luci-app-netifyd-dashboard/root/usr/share/rpcd/acl.d/luci-app-netifyd-dashboard.json +++ b/luci-app-netifyd-dashboard/root/usr/share/rpcd/acl.d/luci-app-netifyd-dashboard.json @@ -13,7 +13,8 @@ "risks", "category_bandwidth", "top_talkers", - "dns_queries" + "dns_queries", + "seccubox_logs" ], "system": [ "info", "board" ], "file": [ "read", "stat" ] diff --git a/luci-app-network-modes/htdocs/luci-static/resources/network-modes/api.js b/luci-app-network-modes/htdocs/luci-static/resources/network-modes/api.js index fc3ecbd0..43cb113f 100644 --- a/luci-app-network-modes/htdocs/luci-static/resources/network-modes/api.js +++ b/luci-app-network-modes/htdocs/luci-static/resources/network-modes/api.js @@ -396,15 +396,3 @@ return baseclass.extend({ return callEnableTcpBbr(); } }); - dmz: { - id: 'dmz', - name: 'Router + DMZ', - icon: '🛡️', - description: 'Traditional router with an additional DMZ interface isolated from LAN but allowed to reach WAN.', - features: [ - 'Dedicated DMZ subnet', - 'Separate firewall zone', - 'Optional DHCP for DMZ clients', - 'Quick rollback timer' - ] - }, diff --git a/luci-app-network-modes/htdocs/luci-static/resources/view/network-modes/settings.js b/luci-app-network-modes/htdocs/luci-static/resources/view/network-modes/settings.js index 0f89eb65..37ae9f4f 100644 --- a/luci-app-network-modes/htdocs/luci-static/resources/view/network-modes/settings.js +++ b/luci-app-network-modes/htdocs/luci-static/resources/view/network-modes/settings.js @@ -3,6 +3,7 @@ 'require form'; 'require ui'; 'require uci'; +'require network-modes/api as api'; 'require network-modes.helpers as helpers'; return view.extend({