feat(netifyd/network-modes): add wizard views
This commit is contained in:
parent
280dd91798
commit
4c70874fff
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
});
|
||||
@ -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,
|
||||
|
||||
@ -13,7 +13,8 @@
|
||||
"risks",
|
||||
"category_bandwidth",
|
||||
"top_talkers",
|
||||
"dns_queries"
|
||||
"dns_queries",
|
||||
"seccubox_logs"
|
||||
],
|
||||
"system": [ "info", "board" ],
|
||||
"file": [ "read", "stat" ]
|
||||
|
||||
@ -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'
|
||||
]
|
||||
},
|
||||
|
||||
@ -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({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user