mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
feat(webui): turn the Web UI into a single-page application
index.html now contains all pages as sections (overview, ports, stat, vlan, l2, mirror, lag, eee, bandwidth, system, update); the sidebar switches between them via the URL hash (#/ports, #/vlan, ...). login.html stays separate as the authentication gate. A section's initialisation runs when the section is shown, its polling intervals run only while it is visible, and re-entering a section refetches the data; the checkbox builders (lag/vlan/mirror) and the L2 scanner were made idempotent so re-initialising cannot duplicate rows. tools/minify.py: recognise regex literals - an escaped slash before the closing delimiter was previously stripped as a // comment. Measured (make MACHINE=KP_9000_6XHML_X2): 8 embedded files, 109,814 -> 97,730 -> 25,302 bytes gzip (23.0 %); the data block ends at 0x462d6 (~86 KB freed). On a real PCB-K0402WS-V3: cold load ~450 ms, section switches ~60-160 ms with no asset re-downloads, all sections render without JavaScript errors.
This commit is contained in:
1 parent
b651890a3a
commit
67ae4598d9
13 files changed
+384
-425
No files matched your search
@@ -1,18 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="bw_title">Ingress and Egress Bandwidth</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
|
||||||
<div id="ports"></div>
|
|
||||||
<h1 data-i18n="bw_heading">Ingress and Egress Bandwidth</h1>
|
|
||||||
<table id="bwtable">
|
|
||||||
<tr> <th> </th> <th colspan="3" data-i18n="bw_ingress"> Ingress </th> <th colspan="2" data-i18n="bw_egress">Egress</th> <th></th></tr>
|
|
||||||
<tr> <th data-i18n="bw_col_port">Port</th> <th data-i18n="bw_col_limit">Limit</th> <th data-i18n="bw_col_bandwidth">Bandwidth [kBit/s]</th> <th data-i18n="bw_col_flow">Flow Control</th> <th data-i18n="bw_col_limit">Limit</th> <th data-i18n="bw_col_bandwidth">Bandwidth [kBit/s]</th> <th data-i18n="bw_col_apply">Apply</th></tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="eee_title">EEE Configuration</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
|
||||||
<div id="ports"></div>
|
|
||||||
<h1 data-i18n="eee_heading">EEE Status</h1>
|
|
||||||
<table id="eeetable">
|
|
||||||
<tr> <th> </th> <th colspan="3" data-i18n="eee_advertising"> Advertising </th> <th colspan="3" data-i18n="eee_partner">Link-Partner advertises</th> <th></th></tr>
|
|
||||||
<tr> <th data-i18n="eee_port">Port</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th data-i18n="eee_active">Active?</th></tr>
|
|
||||||
</table>
|
|
||||||
<div>
|
|
||||||
<input style="width:20%;" class="action" id="eee_enable" onclick="eeeSub(0, 1);" type="button" data-i18n="eee_enable" value="Enable EEE">
|
|
||||||
<input style="width:20%;" class="action" id="eee_disable" onclick="eeeSub(0, 0);" type="button" data-i18n="eee_disable" value="Disable EEE">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
+255
-10
@@ -1,21 +1,41 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<script src="/main.js"></script>
|
<script src="/main.js"></script>
|
||||||
<script>
|
|
||||||
window.addEventListener("load", function() {
|
|
||||||
update( () => {
|
|
||||||
const interval = setInterval(update, 2000);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title data-i18n="index_title">FreeSwitchOS Main Page</title>
|
<title data-i18n="index_title">FreeSwitchOS Main Page</title>
|
||||||
|
<style>
|
||||||
|
.popup {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0; left: 0;
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.popup-content {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
height: 80%
|
||||||
|
}
|
||||||
|
.popup .popup-content {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
.tab-bar { display: flex; border-bottom: 2px solid #226; margin-bottom: 0; padding: 1px 16px; padding-bottom: 0; }
|
||||||
|
.tab-btn { padding: 10px 20px; background-color: #ddf; border: none; cursor: pointer; font-size: 1em; border-radius: 8px 8px 0 0; margin-right: 4px; }
|
||||||
|
.tab-btn:hover { background-color: #aaf; }
|
||||||
|
.tab-btn.active { background-color: #aaf; font-weight: bold; border-bottom: 2px solid #aaf; margin-bottom: -2px; }
|
||||||
|
.tab-content { display: none; }
|
||||||
|
.tab-content.active { display: block; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav id="sidebar"></nav>
|
<nav id="sidebar"></nav>
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
<div id="ports" style="margin-left:16%;padding:1px 16px"></div>
|
||||||
<div id="ports"></div>
|
|
||||||
|
<div class="page" id="page-overview" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
<h1 data-i18n="index_heading">Switch Configuration</h1>
|
<h1 data-i18n="index_heading">Switch Configuration</h1>
|
||||||
<table id="infoTable">
|
<table id="infoTable">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -25,5 +45,230 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-ports" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<h1 data-i18n="port_heading">Port Configuration</h1>
|
||||||
|
<table id="speedtable">
|
||||||
|
<tr> <th data-i18n="port_col_port">Port</th> <th data-i18n="port_col_name">Name</th> <th data-i18n="port_col_speed">Current Link Speed</th><th data-i18n="port_col_set_speed">Set Speed</th><th data-i18n="port_col_disabled">Disabled</th><th data-i18n="port_col_apply">Apply</th></tr>
|
||||||
|
</table>
|
||||||
|
<h2 style="margin-top:3em" data-i18n="port_mtu_heading">Configure Maximum Frame Size (MTU) forwarded at Port</h2>
|
||||||
|
<table id="mtutable" style="margin-top:1em">
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-stat" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<div id="popup" class="popup">
|
||||||
|
<div class="popup-content">
|
||||||
|
<h2 data-i18n="stat_detailed">Detailed Port Statistics</h2>
|
||||||
|
<div id="popup_text"></div>
|
||||||
|
<button id="closePopup" class="action" data-i18n="stat_close">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h1 data-i18n="stat_heading">Port Statistics</h1>
|
||||||
|
<table id="statstable">
|
||||||
|
<tr> <th data-i18n="stat_col_port">Port</th> <th data-i18n="stat_col_name">Name</th> <th data-i18n="stat_col_link">link</th> <th data-i18n="stat_col_tx_good">TX Good</th> <th data-i18n="stat_col_tx_bad">TX Bad</th> <th data-i18n="stat_col_rx_good">RX Good</th> <th data-i18n="stat_col_rx_bad">RX Bad</th> <th data-i18n="stat_col_all"> All Counters </th></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-vlan" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<h1 data-i18n="vlan_heading">VLAN Configuration</h1>
|
||||||
|
<form id="vform">
|
||||||
|
<div>
|
||||||
|
<label for="vlanSelect" data-i18n="vlan_select">VLAN Select:</label>
|
||||||
|
<select id="vlanSelect" style="margin: 0 0 0 8px">
|
||||||
|
<option value="" disabled selected data-i18n="vlan_choose">— VLAN Choose —</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<div>
|
||||||
|
<label for="vid" data-i18n="vlan_id">VLAN ID:</label>
|
||||||
|
<input type="number" min="1" max="4094" id="vid" name="vid">
|
||||||
|
<button type="button" style="margin: 0 0 0 24px" onclick="fetchVLAN();" data-i18n="vlan_get_config">Get Configuration</button>
|
||||||
|
</div>
|
||||||
|
<br/><br/>
|
||||||
|
<label for="vname" data-i18n="vlan_name">VLAN Name:</label>
|
||||||
|
<input type="text" id="vname" name="vname"><br><br>
|
||||||
|
<br/>
|
||||||
|
<h2 data-i18n="vlan_tagged">Tagged Ports</h2>
|
||||||
|
<div id="tPorts"><button type="button" style="transform: translateY(-100%);margin: 0 50px 0 0" onclick="utClicked(true);" data-i18n="vlan_select_all">Select all</button></div>
|
||||||
|
<h2 data-i18n="vlan_untagged">Untagged Ports</h2>
|
||||||
|
<div id="uPorts"><button type="button" style="transform: translateY(-100%); margin: 0 50px 0 0" onclick="utClicked(false);" data-i18n="vlan_select_all">Select all</button> </div>
|
||||||
|
<h2 data-i18n="vlan_pvid">Use as default VLAN for incoming traffic (PVID)</h2>
|
||||||
|
<div id="pPorts"><button type="button" style="transform: translateY(-100%); margin: 0 50px 0 0" onclick="pvClicked(true);" data-i18n="vlan_select_all">Select all</button> </div>
|
||||||
|
<br/> <input style="width:40%;" class="action" id="vlan_sub" onclick="vlanSub();" type="button" data-i18n="vlan_update" value="Update / Create">
|
||||||
|
</form>
|
||||||
|
<h2 data-i18n="vlan_configured">Configured VLANs</h2>
|
||||||
|
<table id="vlanTable" style="width:90%">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>VLAN</th>
|
||||||
|
<th data-i18n="vlan_col_name">Name</th>
|
||||||
|
<th data-i18n="vlan_col_member">Member Ports</th>
|
||||||
|
<th data-i18n="vlan_col_tagged">Tagged Ports</th>
|
||||||
|
<th data-i18n="vlan_col_untagged">Untagged Ports</th>
|
||||||
|
<th data-i18n="vlan_col_pvid">PVID Ports</th>
|
||||||
|
<th data-i18n="vlan_col_delete">Delete</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="vlanTableBody">
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-l2" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<h1 data-i18n="l2_heading">L2 Configuration</h1>
|
||||||
|
<p><span data-i18n="l2_shown">Shown:</span> <span id="l2count">-</span></p>
|
||||||
|
<table id="l2table">
|
||||||
|
<tr>
|
||||||
|
<th><span class="l2sort" onclick="l2SortBy('port')"><span data-i18n="l2_col_port">Port</span><span id="l2a_port" class="l2arrow"></span></span><br>
|
||||||
|
<input id="l2f_port" class="l2filter" oninput="l2FilterChanged()" size="5"></th>
|
||||||
|
<th><span class="l2sort" onclick="l2SortBy('mac')">MAC<span id="l2a_mac" class="l2arrow"></span></span><br>
|
||||||
|
<input id="l2f_mac" class="l2filter" oninput="l2FilterChanged()" size="14"></th>
|
||||||
|
<th><span class="l2sort" onclick="l2SortBy('vlan')">VLAN<span id="l2a_vlan" class="l2arrow"></span></span><br>
|
||||||
|
<input id="l2f_vlan" class="l2filter" oninput="l2FilterChanged()" size="5"></th>
|
||||||
|
<th><span class="l2sort" onclick="l2SortBy('type')"><span data-i18n="l2_col_type">Type</span><span id="l2a_type" class="l2arrow"></span></span><br>
|
||||||
|
<input id="l2f_type" class="l2filter" oninput="l2FilterChanged()" size="8"></th>
|
||||||
|
<th data-i18n="l2_col_remove">Remove Entry</th></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-mirror" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<h1 data-i18n="mirror_heading">Mirror Configuration</h1>
|
||||||
|
<label class="tswitch"><span data-i18n="mirror_enabled">Enabled:</span> <input id="me" type="checkbox"></label><br/>
|
||||||
|
<label for="mp"><span data-i18n="mirror_port">Mirroring Port:</span></label> <input type="number" id="mp" name="mp" min="1" max="9"/>
|
||||||
|
<h2 data-i18n="mirror_tx">Mirrored Ports (TX)</h2>
|
||||||
|
<div id="mPortsTX"></div>
|
||||||
|
<br />
|
||||||
|
<h2 data-i18n="mirror_rx">Mirrored Ports (RX)</h2>
|
||||||
|
<div id="mPortsRX"></div>
|
||||||
|
<br/> <input style="width:15%;" class="action" id="mirror_sub" onclick="mirrorSub();" type="button" data-i18n="mirror_update" value="Update / Create">
|
||||||
|
<input style="width:15%;" class="action" id="mirror_del" onclick="mirrorDel();" type="button" data-i18n="mirror_disable" value="Disable Mirroring">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-lag" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<h1 data-i18n="lag_heading">Link Aggregation Groups Configuration</h1>
|
||||||
|
<h2>LAG 1 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub0" onclick="lagSub(0);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
||||||
|
<div id="mLAG0"></div>
|
||||||
|
<br />
|
||||||
|
<h2>LAG 2 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub1" onclick="lagSub(1);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
||||||
|
<div id="mLAG1"></div>
|
||||||
|
<br />
|
||||||
|
<h2>LAG 3 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub2" onclick="lagSub(2);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
||||||
|
<div id="mLAG2"></div>
|
||||||
|
<br />
|
||||||
|
<h2>LAG 4 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub3" onclick="lagSub(3);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
||||||
|
<div id="mLAG3"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-eee" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<h1 data-i18n="eee_heading">EEE Status</h1>
|
||||||
|
<table id="eeetable">
|
||||||
|
<tr> <th> </th> <th colspan="3" data-i18n="eee_advertising"> Advertising </th> <th colspan="3" data-i18n="eee_partner">Link-Partner advertises</th> <th></th></tr>
|
||||||
|
<tr> <th data-i18n="eee_port">Port</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th>2.5G</th> <th>1G</th> <th>100M</th> <th data-i18n="eee_active">Active?</th></tr>
|
||||||
|
</table>
|
||||||
|
<div>
|
||||||
|
<input style="width:20%;" class="action" id="eee_enable" onclick="eeeSub(0, 1);" type="button" data-i18n="eee_enable" value="Enable EEE">
|
||||||
|
<input style="width:20%;" class="action" id="eee_disable" onclick="eeeSub(0, 0);" type="button" data-i18n="eee_disable" value="Disable EEE">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-bandwidth" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<h1 data-i18n="bw_heading">Ingress and Egress Bandwidth</h1>
|
||||||
|
<table id="bwtable">
|
||||||
|
<tr> <th> </th> <th colspan="3" data-i18n="bw_ingress"> Ingress </th> <th colspan="2" data-i18n="bw_egress">Egress</th> <th></th></tr>
|
||||||
|
<tr> <th data-i18n="bw_col_port">Port</th> <th data-i18n="bw_col_limit">Limit</th> <th data-i18n="bw_col_bandwidth">Bandwidth [kBit/s]</th> <th data-i18n="bw_col_flow">Flow Control</th> <th data-i18n="bw_col_limit">Limit</th> <th data-i18n="bw_col_bandwidth">Bandwidth [kBit/s]</th> <th data-i18n="bw_col_apply">Apply</th></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-system" style="margin-left:16%;padding:1px 16px;height:1000px;">
|
||||||
|
<div class="tab-bar">
|
||||||
|
<button class="tab-btn active" onclick="openTab(event, 'system-tab')" data-i18n="sys_tab_system">System</button>
|
||||||
|
<button class="tab-btn" onclick="openTab(event, 'advanced-tab')" data-i18n="sys_tab_advanced">Advanced</button>
|
||||||
|
<button class="tab-btn" onclick="openTab(event, 'console-tab')" data-i18n="sys_tab_console">Console</button>
|
||||||
|
</div>
|
||||||
|
<div id="system-tab" class="tab-content active">
|
||||||
|
<h1 data-i18n="sys_heading">System Settings</h1>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="hostname" data-i18n="sys_hostname">Hostname:</label></div>
|
||||||
|
<div class="rcol"> <input id="hostname" type="text" maxlength="23" size="20"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="ip" data-i18n="sys_ip">IP address:</label></div>
|
||||||
|
<div class="rcol"> <input id="ip" type="text" size="15"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="netmask" data-i18n="sys_netmask">Netmask:</label></div>
|
||||||
|
<div class="rcol"> <input id="netmask" type="text" size="15"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="gw" data-i18n="sys_gateway">Gateway:</label></div>
|
||||||
|
<div class="rcol"> <input id="gw" type="text" size="15"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="model" data-i18n="sys_model">Model:</label></div>
|
||||||
|
<div class="rcol"> <span id="model">-</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="lang-select" data-i18n="sys_language">Language:</label></div>
|
||||||
|
<div class="rcol">
|
||||||
|
<select id="lang-select">
|
||||||
|
<option value="en">English</option>
|
||||||
|
<option value="ja">日本語</option>
|
||||||
|
<option value="zh">中文</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="lcol"> <label for="mgmtvlan" data-i18n="sys_mgmt_vlan">Management VLAN:</label></div>
|
||||||
|
<div class="rcol">
|
||||||
|
<select id="mgmtvlan">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<span data-i18n="sys_ip_note">When updating the above settings, remember to point your browser to the new IP afterwards:</span><br/>
|
||||||
|
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" data-i18n="sys_update" value="Update Settings"><br/>
|
||||||
|
<br/>
|
||||||
|
<span data-i18n="sys_save_label">Save all current settings to Flash:</span><br/>
|
||||||
|
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" data-i18n="sys_save" value="Save Settings to Flash">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="advanced-tab" class="tab-content">
|
||||||
|
<h1 data-i18n="sys_advanced">Advanced Settings</h1>
|
||||||
|
<div class="lcol"> <label for="config_display" data-i18n="sys_startup_config">Startup configuration:</label></div>
|
||||||
|
<textarea id="config_display" rows="8" cols="60"></textarea>
|
||||||
|
<br/><br/>
|
||||||
|
<span data-i18n="sys_startup_warn">Be careful when saving the directly edited startup configuration, you can lock yourself out:</span><br/>
|
||||||
|
<input style="width:40%;" class="action" id="clear_config" onclick="clearConfig();" type="button" data-i18n="sys_clear_config" value="Clear Startup Config">
|
||||||
|
<br/>
|
||||||
|
<input style="width:40%;" class="action" id="flash_startup_sub" onclick="flashStartupSave();" type="button" data-i18n="sys_save_startup" value="Save Startup Settings to Flash">
|
||||||
|
<br/>
|
||||||
|
<input style="width:40%;" class="action" id="switch_reset" onclick="resetSwitch();" type="button" data-i18n="sys_reset" value="Reset Switch">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="console-tab" class="tab-content">
|
||||||
|
<h1 data-i18n="sys_console">Console Command</h1>
|
||||||
|
<label for="console_command" data-i18n="sys_enter_cmd">Enter command:</label>
|
||||||
|
<input type="text" id="console_cmd" name="console_cmd" style="width:40%;">
|
||||||
|
<input style="width:20%;" class="action" id="cmd_sub" onclick="cmdSub();" type="button" data-i18n="sys_send_cmd" value="Send Command"><br/>
|
||||||
|
<br/><br/>
|
||||||
|
<span data-i18n="sys_console_warn">Be careful when entering console commands, you can lock yourself out!</span><br/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page" id="page-update" style="margin-left:16%;padding:1px 16px;height:1000px;width:40%;">
|
||||||
|
<h1 data-i18n="update_heading">Firmware Update</h1>
|
||||||
|
<form enctype="multipart/form-data" action="/upload" method="POST">
|
||||||
|
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
|
||||||
|
<span data-i18n="update_instruction">Choose a firmware update file to upload:</span> <br/> <br/>
|
||||||
|
<input name="uploadedfile" type="file" accept=".bin" /><br />
|
||||||
|
<input style="margin-top:3em" type="submit" data-i18n="update_upload" value="Upload File" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="l2_title">FreeSwitchOS L2 Configuration</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
|
||||||
<div id="ports"></div>
|
|
||||||
<h1 data-i18n="l2_heading">L2 Configuration</h1>
|
|
||||||
<p><span data-i18n="l2_shown">Shown:</span> <span id="l2count">-</span></p>
|
|
||||||
<table id="l2table">
|
|
||||||
<tr>
|
|
||||||
<th><span class="l2sort" onclick="l2SortBy('port')"><span data-i18n="l2_col_port">Port</span><span id="l2a_port" class="l2arrow"></span></span><br>
|
|
||||||
<input id="l2f_port" class="l2filter" oninput="l2FilterChanged()" size="5"></th>
|
|
||||||
<th><span class="l2sort" onclick="l2SortBy('mac')">MAC<span id="l2a_mac" class="l2arrow"></span></span><br>
|
|
||||||
<input id="l2f_mac" class="l2filter" oninput="l2FilterChanged()" size="14"></th>
|
|
||||||
<th><span class="l2sort" onclick="l2SortBy('vlan')">VLAN<span id="l2a_vlan" class="l2arrow"></span></span><br>
|
|
||||||
<input id="l2f_vlan" class="l2filter" oninput="l2FilterChanged()" size="5"></th>
|
|
||||||
<th><span class="l2sort" onclick="l2SortBy('type')"><span data-i18n="l2_col_type">Type</span><span id="l2a_type" class="l2arrow"></span></span><br>
|
|
||||||
<input id="l2f_type" class="l2filter" oninput="l2FilterChanged()" size="8"></th>
|
|
||||||
<th data-i18n="l2_col_remove">Remove Entry</th></tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="lag_title">Link Aggregation Configuration</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
|
||||||
<div id="ports"></div>
|
|
||||||
<h1 data-i18n="lag_heading">Link Aggregation Groups Configuration</h1>
|
|
||||||
<h2>LAG 1 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub0" onclick="lagSub(0);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
|
||||||
<div id="mLAG0"></div>
|
|
||||||
<br />
|
|
||||||
<h2>LAG 2 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub1" onclick="lagSub(1);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
|
||||||
<div id="mLAG1"></div>
|
|
||||||
<br />
|
|
||||||
<h2>LAG 3 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub2" onclick="lagSub(2);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
|
||||||
<div id="mLAG2"></div>
|
|
||||||
<br />
|
|
||||||
<h2>LAG 4 <input style="width:15%;margin-left: 3em;" class="action" id="l_sub3" onclick="lagSub(3);" type="button" data-i18n="lag_update" value="Update / Create"></h2>
|
|
||||||
<div id="mLAG3"></div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
+97
-51
@@ -899,17 +899,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
var sidebarEl = document.getElementById('sidebar');
|
var sidebarEl = document.getElementById('sidebar');
|
||||||
if (sidebarEl)
|
if (sidebarEl)
|
||||||
sidebarEl.innerHTML =
|
sidebarEl.innerHTML =
|
||||||
"<ul><li><a href='index.html' data-i18n='nav_overview'>Overview</a></li>"
|
"<ul><li><a href='#/overview' data-i18n='nav_overview'>Overview</a></li>"
|
||||||
+ "<li><a href='ports.html' data-i18n='nav_port_config'>Port Configuration</a></li>"
|
+ "<li><a href='#/ports' data-i18n='nav_port_config'>Port Configuration</a></li>"
|
||||||
+ "<li><a href='stat.html' data-i18n='nav_port_stat'>Port Statistics</a></li>"
|
+ "<li><a href='#/stat' data-i18n='nav_port_stat'>Port Statistics</a></li>"
|
||||||
+ "<li><a href='vlan.html' >VLAN</a></li>"
|
+ "<li><a href='#/vlan' >VLAN</a></li>"
|
||||||
+ "<li><a href='l2.html' data-i18n='nav_l2'>L2 Configuration</a></li>"
|
+ "<li><a href='#/l2' data-i18n='nav_l2'>L2 Configuration</a></li>"
|
||||||
+ "<li><a href='mirror.html' data-i18n='nav_mirror'>Mirroring</a></li>"
|
+ "<li><a href='#/mirror' data-i18n='nav_mirror'>Mirroring</a></li>"
|
||||||
+ "<li><a href='lag.html' data-i18n='nav_lag'>Link Aggregation</a></li>"
|
+ "<li><a href='#/lag' data-i18n='nav_lag'>Link Aggregation</a></li>"
|
||||||
+ "<li><a href='eee.html' data-i18n='nav_eee'>EEE</a></li>"
|
+ "<li><a href='#/eee' data-i18n='nav_eee'>EEE</a></li>"
|
||||||
+ "<li><a href='bandwidth.html' data-i18n='nav_bandwidth'>Bandwidth Limits</a></li>"
|
+ "<li><a href='#/bandwidth' data-i18n='nav_bandwidth'>Bandwidth Limits</a></li>"
|
||||||
+ "<li><a href='system.html' data-i18n='nav_system'>System Settings</a></li>"
|
+ "<li><a href='#/system' data-i18n='nav_system'>System Settings</a></li>"
|
||||||
+ "<li><a href='update.html' data-i18n='nav_fw_update'>Firmware Update</a></li></ul>";
|
+ "<li><a href='#/update' data-i18n='nav_fw_update'>Firmware Update</a></li></ul>";
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
@@ -920,6 +920,54 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* Single-page navigation: the sidebar links set the URL hash
|
||||||
|
* ("#/ports" and friends) and the matching section in index.html is
|
||||||
|
* shown. Each section initialises on first display, and its polling
|
||||||
|
* intervals run only while the section is visible. */
|
||||||
|
var sectionIntervals = [];
|
||||||
|
var sectionInits = {};
|
||||||
|
|
||||||
|
function setSectionInterval(fn, ms) {
|
||||||
|
sectionIntervals.push(setInterval(fn, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearSectionIntervals() {
|
||||||
|
sectionIntervals.forEach(function(t) { clearInterval(t); });
|
||||||
|
sectionIntervals = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSection(name) {
|
||||||
|
document.querySelectorAll('.page').forEach(function(el) { el.style.display = 'none'; });
|
||||||
|
var sec = document.getElementById('page-' + name);
|
||||||
|
if (sec) sec.style.display = 'block';
|
||||||
|
clearSectionIntervals();
|
||||||
|
if (sectionInits[name])
|
||||||
|
sectionInits[name]();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('hashchange', function() {
|
||||||
|
showSection((location.hash || '#/overview').replace(/^#\//, ''));
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
showSection((location.hash || '#/overview').replace(/^#\//, ''));
|
||||||
|
});
|
||||||
|
|
||||||
|
sectionInits.overview = function() {
|
||||||
|
update( () => {
|
||||||
|
setSectionInterval(update, 2000);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* System page tabs (system.html section of index.html) */
|
||||||
|
function openTab(evt, tabId) {
|
||||||
|
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
||||||
|
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||||||
|
document.getElementById(tabId).classList.add('active');
|
||||||
|
evt.currentTarget.classList.add('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var configInterval = Number();
|
var configInterval = Number();
|
||||||
var configuration = [];
|
var configuration = [];
|
||||||
const conf_cmds = [
|
const conf_cmds = [
|
||||||
@@ -1195,12 +1243,11 @@ function resetSwitch() {
|
|||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
sectionInits.system = function() {
|
||||||
if (!document.getElementById('ip')) return;
|
|
||||||
var langSel = document.getElementById('lang-select');
|
var langSel = document.getElementById('lang-select');
|
||||||
if (langSel) langSel.value = rtlLang;
|
if (langSel) langSel.value = rtlLang;
|
||||||
systemInterval = setInterval(fetchIP, 1000);
|
systemInterval = setSectionInterval(fetchIP, 1000);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
|
||||||
var mgmtVlanCurrent = 0;
|
var mgmtVlanCurrent = 0;
|
||||||
@@ -1382,16 +1429,15 @@ function getMTUs() {
|
|||||||
xhttp.timeout = 1500; sendXHTTP(xhttp);
|
xhttp.timeout = 1500; sendXHTTP(xhttp);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
sectionInits.ports = function() {
|
||||||
if (!document.getElementById('speedtable')) return;
|
|
||||||
update( () => {
|
update( () => {
|
||||||
createPortTable();
|
createPortTable();
|
||||||
updatePortTable();
|
updatePortTable();
|
||||||
getMTUs()
|
getMTUs()
|
||||||
const interval = setInterval(update, 2000);
|
setSectionInterval(update, 2000);
|
||||||
const updatePortTableInterval = setInterval(updatePortTable, 1000);
|
setSectionInterval(updatePortTable, 1000);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const mib_counters = [
|
const mib_counters = [
|
||||||
"Interface in Octets", 8,
|
"Interface in Octets", 8,
|
||||||
@@ -1595,15 +1641,14 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
sectionInits.stat = function() {
|
||||||
if (!document.getElementById('statstable')) return;
|
|
||||||
update( () => {
|
update( () => {
|
||||||
update();
|
update();
|
||||||
fillStats();
|
fillStats();
|
||||||
const stat = setInterval(fillStats, 1000);
|
setSectionInterval(fillStats, 1000);
|
||||||
const interval = setInterval(update, 2000);
|
setSectionInterval(update, 2000);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var l2GetInterval;
|
var l2GetInterval;
|
||||||
var l2Entries = [];
|
var l2Entries = [];
|
||||||
@@ -1765,20 +1810,23 @@ function getL2() {
|
|||||||
xhttp.timeout = 1500; sendXHTTP(xhttp);
|
xhttp.timeout = 1500; sendXHTTP(xhttp);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
sectionInits.l2 = function() {
|
||||||
if (!document.getElementById('l2table')) return;
|
l2Entries = [];
|
||||||
|
l2CurrentEntry = 0;
|
||||||
update( () => {
|
update( () => {
|
||||||
getL2();
|
getL2();
|
||||||
const interval = setInterval(update, 2000);
|
setSectionInterval(update, 2000);
|
||||||
l2GetInterval = setInterval(getL2, 1000);
|
l2GetInterval = setSectionInterval(getL2, 1000);
|
||||||
});;
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var vlanInterval = Number();
|
var vlanInterval = Number();
|
||||||
|
|
||||||
function vlanForm() {
|
function vlanForm() {
|
||||||
if (!numPorts)
|
if (!numPorts)
|
||||||
return;
|
return;
|
||||||
|
document.querySelectorAll('#tPorts .cbgroup, #uPorts .cbgroup, #pPorts .cbgroup')
|
||||||
|
.forEach(function(el) { el.remove(); });
|
||||||
var t = document.getElementById('tPorts');
|
var t = document.getElementById('tPorts');
|
||||||
var u = document.getElementById('uPorts');
|
var u = document.getElementById('uPorts');
|
||||||
var p = document.getElementById('pPorts');
|
var p = document.getElementById('pPorts');
|
||||||
@@ -1974,8 +2022,7 @@ function loadVlanList() {
|
|||||||
sendXHTTP(xhttp);
|
sendXHTTP(xhttp);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
sectionInits.vlan = function() {
|
||||||
if (!document.getElementById('vlanSelect')) return;
|
|
||||||
update( () => {
|
update( () => {
|
||||||
vlanForm();
|
vlanForm();
|
||||||
refreshVlanViews();
|
refreshVlanViews();
|
||||||
@@ -1983,9 +2030,9 @@ window.addEventListener("load", function() {
|
|||||||
document.getElementById('vid').value = this.value;
|
document.getElementById('vid').value = this.value;
|
||||||
fetchVLAN();
|
fetchVLAN();
|
||||||
};
|
};
|
||||||
const interval = setInterval(update, 2000);
|
setSectionInterval(update, 2000);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
async function vlanSub() {
|
async function vlanSub() {
|
||||||
var commands = [];
|
var commands = [];
|
||||||
@@ -2028,6 +2075,8 @@ var lagInterval = Number();
|
|||||||
function lagForm() {
|
function lagForm() {
|
||||||
if (!numPorts)
|
if (!numPorts)
|
||||||
return;
|
return;
|
||||||
|
for (let j = 0; j < 4; j++)
|
||||||
|
document.getElementById("mLAG" + j).innerHTML = '';
|
||||||
for (let j=0; j < 4; j++) {
|
for (let j=0; j < 4; j++) {
|
||||||
var lag = "mLAG" + j
|
var lag = "mLAG" + j
|
||||||
console.log("Adding LAG " + lag)
|
console.log("Adding LAG " + lag)
|
||||||
@@ -2098,13 +2147,12 @@ async function lagSub(l) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
sectionInits.lag = function() {
|
||||||
if (!document.getElementById('mLAG0')) return;
|
|
||||||
update( () => {
|
update( () => {
|
||||||
lagForm();
|
lagForm();
|
||||||
const interval = setInterval(update, 2000);
|
setSectionInterval(update, 2000);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var mirrorInterval = Number();
|
var mirrorInterval = Number();
|
||||||
const mirrors = ["mPortsTX", "mPortsRX"];
|
const mirrors = ["mPortsTX", "mPortsRX"];
|
||||||
@@ -2112,6 +2160,7 @@ const mirrors = ["mPortsTX", "mPortsRX"];
|
|||||||
function mirrorForm() {
|
function mirrorForm() {
|
||||||
if (!numPorts)
|
if (!numPorts)
|
||||||
return;
|
return;
|
||||||
|
mirrors.forEach(function(m) { document.getElementById(m).innerHTML = ''; });
|
||||||
for (let j=0; j < mirrors.length; j++) {
|
for (let j=0; j < mirrors.length; j++) {
|
||||||
console.log("Adding Mirror " + j)
|
console.log("Adding Mirror " + j)
|
||||||
var m = document.getElementById(mirrors[j]);
|
var m = document.getElementById(mirrors[j]);
|
||||||
@@ -2164,13 +2213,12 @@ function fetchMirror() {
|
|||||||
sendXHTTP(xhttp);
|
sendXHTTP(xhttp);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
sectionInits.mirror = function() {
|
||||||
if (!document.getElementById('mPortsTX')) return;
|
|
||||||
update( () => {
|
update( () => {
|
||||||
mirrorForm();
|
mirrorForm();
|
||||||
const interval = setInterval(update, 2000);
|
setSectionInterval(update, 2000);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
async function mirrorSub() {
|
async function mirrorSub() {
|
||||||
var cmd = "mirror ";
|
var cmd = "mirror ";
|
||||||
@@ -2260,15 +2308,14 @@ function getEEE() {
|
|||||||
xhttp.timeout = 1500; sendXHTTP(xhttp);
|
xhttp.timeout = 1500; sendXHTTP(xhttp);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
sectionInits.eee = function() {
|
||||||
if (!document.getElementById('eeetable')) return;
|
|
||||||
update( () => {
|
update( () => {
|
||||||
createEEE();
|
createEEE();
|
||||||
getEEE();
|
getEEE();
|
||||||
const interval = setInterval(update, 2000);
|
setSectionInterval(update, 2000);
|
||||||
const iCount = setInterval(getEEE, 2000);
|
setSectionInterval(getEEE, 2000);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
async function eeeSub(port, enable) {
|
async function eeeSub(port, enable) {
|
||||||
var cmd = "eee ";
|
var cmd = "eee ";
|
||||||
@@ -2419,14 +2466,13 @@ function getBW() {
|
|||||||
xhttp.timeout = 1500; sendXHTTP(xhttp);
|
xhttp.timeout = 1500; sendXHTTP(xhttp);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", function() {
|
sectionInits.bandwidth = function() {
|
||||||
if (!document.getElementById('bwtable')) return;
|
|
||||||
update( () => {
|
update( () => {
|
||||||
createBW();
|
createBW();
|
||||||
getBW();
|
getBW();
|
||||||
const interval = setInterval(update, 2000);
|
setSectionInterval(update, 2000);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
if (!document.getElementById('infoTable')) return;
|
if (!document.getElementById('infoTable')) return;
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="mirror_title">Mirror Configuration</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
|
||||||
<div id="ports"></div>
|
|
||||||
<h1 data-i18n="mirror_heading">Mirror Configuration</h1>
|
|
||||||
<label class="tswitch"><span data-i18n="mirror_enabled">Enabled:</span> <input id="me" type="checkbox"></label><br/>
|
|
||||||
<label for="mp"><span data-i18n="mirror_port">Mirroring Port:</span></label> <input type="number" id="mp" name="mp" min="1" max="9"/>
|
|
||||||
<h2 data-i18n="mirror_tx">Mirrored Ports (TX)</h2>
|
|
||||||
<div id="mPortsTX"></div>
|
|
||||||
<br />
|
|
||||||
<h2 data-i18n="mirror_rx">Mirrored Ports (RX)</h2>
|
|
||||||
<div id="mPortsRX"></div>
|
|
||||||
<br/> <input style="width:15%;" class="action" id="mirror_sub" onclick="mirrorSub();" type="button" data-i18n="mirror_update" value="Update / Create">
|
|
||||||
<input style="width:15%;" class="action" id="mirror_del" onclick="mirrorDel();" type="button" data-i18n="mirror_disable" value="Disable Mirroring">
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="port_title">FreeSwitchOS Port Configuration</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
|
||||||
<div id="ports"></div>
|
|
||||||
<h1 data-i18n="port_heading">Port Configuration</h1>
|
|
||||||
<form id="vform" action="/vlan.html">
|
|
||||||
<table id="speedtable">
|
|
||||||
<tr> <th data-i18n="port_col_port">Port</th> <th data-i18n="port_col_name">Name</th> <th data-i18n="port_col_speed">Current Link Speed</th><th data-i18n="port_col_set_speed">Set Speed</th><th data-i18n="port_col_disabled">Disabled</th><th data-i18n="port_col_apply">Apply</th></tr>
|
|
||||||
</table>
|
|
||||||
<h2 style="margin-top:3em" data-i18n="port_mtu_heading">Configure Maximum Frame Size (MTU) forwarded at Port</h2>
|
|
||||||
<table id="mtutable" style="margin-top:1em">
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="stat_title">FreeSwitchOS Port Statistics</title>
|
|
||||||
<style>
|
|
||||||
.popup {
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
top: 0; left: 0;
|
|
||||||
width: 100%; height: 100%;
|
|
||||||
background: rgba(0, 0, 0, 0.5);
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.popup-content {
|
|
||||||
background: #fff;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 5px;
|
|
||||||
text-align: center;
|
|
||||||
height: 80%
|
|
||||||
}
|
|
||||||
.popup .popup-content {
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
|
||||||
<div id="ports"></div>
|
|
||||||
<div id="popup" class="popup">
|
|
||||||
<div class="popup-content">
|
|
||||||
<h2 data-i18n="stat_detailed">Detailed Port Statistics</h2>
|
|
||||||
<div id="popup_text"></div>
|
|
||||||
<button id="closePopup" class="action" data-i18n="stat_close">Close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<h1 data-i18n="stat_heading">Port Statistics</h1>
|
|
||||||
<table id="statstable">
|
|
||||||
<tr> <th data-i18n="stat_col_port">Port</th> <th data-i18n="stat_col_name">Name</th> <th data-i18n="stat_col_link">link</th> <th data-i18n="stat_col_tx_good">TX Good</th> <th data-i18n="stat_col_tx_bad">TX Bad</th> <th data-i18n="stat_col_rx_good">RX Good</th> <th data-i18n="stat_col_rx_bad">RX Bad</th> <th data-i18n="stat_col_all"> All Counters </th></tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="sys_title">System Settings</title>
|
|
||||||
<style>
|
|
||||||
.tab-bar { display: flex; border-bottom: 2px solid #226; margin-bottom: 0; margin-left: 16%; padding: 1px 16px; padding-bottom: 0; }
|
|
||||||
.tab-btn { padding: 10px 20px; background-color: #ddf; border: none; cursor: pointer; font-size: 1em; border-radius: 8px 8px 0 0; margin-right: 4px; }
|
|
||||||
.tab-btn:hover { background-color: #aaf; }
|
|
||||||
.tab-btn.active { background-color: #aaf; font-weight: bold; border-bottom: 2px solid #aaf; margin-bottom: -2px; }
|
|
||||||
.tab-content { display: none; }
|
|
||||||
.tab-content.active { display: block; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="tab-bar">
|
|
||||||
<button class="tab-btn active" onclick="openTab(event, 'system-tab')" data-i18n="sys_tab_system">System</button>
|
|
||||||
<button class="tab-btn" onclick="openTab(event, 'advanced-tab')" data-i18n="sys_tab_advanced">Advanced</button>
|
|
||||||
<button class="tab-btn" onclick="openTab(event, 'console-tab')" data-i18n="sys_tab_console">Console</button>
|
|
||||||
</div>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
|
||||||
<div id="ports"></div>
|
|
||||||
|
|
||||||
<div id="system-tab" class="tab-content active">
|
|
||||||
<h1 data-i18n="sys_heading">System Settings</h1>
|
|
||||||
<div class="row">
|
|
||||||
<div class="lcol"> <label for="hostname" data-i18n="sys_hostname">Hostname:</label></div>
|
|
||||||
<div class="rcol"> <input id="hostname" type="text" maxlength="23" size="20"/>
|
|
||||||
<button onclick="hostSub()" data-i18n="sys_apply">Apply</button></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="lcol"> <label data-i18n="sys_model">Model:</label></div>
|
|
||||||
<div class="rcol"><span id="model" class="rotext"></span></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="lcol"> <label for="ip" data-i18n="sys_ip">IP address:</label></div>
|
|
||||||
<div class="rcol"> <input id="ip" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="lcol"> <label for="netmask" data-i18n="sys_netmask">Netmask:</label></div>
|
|
||||||
<div class="rcol"><input id="netmask" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="lcol"> <label for="gw" data-i18n="sys_gateway">Gateway:</label></div>
|
|
||||||
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="lcol"> <label for="mgmtvlan" data-i18n="sys_mgmt_vlan">Management VLAN:</label></div>
|
|
||||||
<div class="rcol"><select id="mgmtvlan" class="ip" onchange="mgmtVlanChanged()"></select></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="lcol"> <label data-i18n="sys_language">Language:</label></div>
|
|
||||||
<div class="rcol">
|
|
||||||
<select id="lang-select" onchange="changeLang()">
|
|
||||||
<option value="en">English</option>
|
|
||||||
<option value="ja">日本語</option>
|
|
||||||
<option value="zh">中文</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<span data-i18n="sys_ip_note">When updating the above settings, remember to point your browser to the new IP afterwards:</span><br/>
|
|
||||||
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" data-i18n="sys_update" value="Update Settings"><br/>
|
|
||||||
<br/>
|
|
||||||
<span data-i18n="sys_save_label">Save all current settings to Flash:</span><br/>
|
|
||||||
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" data-i18n="sys_save" value="Save Settings to Flash">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="advanced-tab" class="tab-content">
|
|
||||||
<h1 data-i18n="sys_advanced">Advanced Settings</h1>
|
|
||||||
<div class="lcol"> <label for="config_display" data-i18n="sys_startup_config">Startup configuration:</label></div>
|
|
||||||
<textarea id="config_display" rows="8" cols="60"></textarea>
|
|
||||||
<br/><br/>
|
|
||||||
<span data-i18n="sys_startup_warn">Be careful when saving the directly edited startup configuration, you can lock yourself out:</span><br/>
|
|
||||||
<input style="width:40%;" class="action" id="clear_config" onclick="clearConfig();" type="button" data-i18n="sys_clear_config" value="Clear Startup Config">
|
|
||||||
<br/>
|
|
||||||
<input style="width:40%;" class="action" id="flash_startup_sub" onclick="flashStartupSave();" type="button" data-i18n="sys_save_startup" value="Save Startup Settings to Flash">
|
|
||||||
<br/>
|
|
||||||
<input style="width:40%;" class="action" id="switch_reset" onclick="resetSwitch();" type="button" data-i18n="sys_reset" value="Reset Switch">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="console-tab" class="tab-content">
|
|
||||||
<h1 data-i18n="sys_console">Console Command</h1>
|
|
||||||
<label for="console_command" data-i18n="sys_enter_cmd">Enter command:</label>
|
|
||||||
<input type="text" id="console_cmd" name="console_cmd" style="width:40%;">
|
|
||||||
<input style="width:20%;" class="action" id="cmd_sub" onclick="cmdSub();" type="button" data-i18n="sys_send_cmd" value="Send Command"><br/>
|
|
||||||
<br/><br/>
|
|
||||||
<span data-i18n="sys_console_warn">Be careful when entering console commands, you can lock yourself out!</span><br/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
function openTab(evt, tabId) {
|
|
||||||
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
|
||||||
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
|
||||||
document.getElementById(tabId).classList.add('active');
|
|
||||||
evt.currentTarget.classList.add('active');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="update_title">Firmware update</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;width:40%;">
|
|
||||||
<h1 data-i18n="update_heading">Firmware Update</h1>
|
|
||||||
<form enctype="multipart/form-data" action="/upload" method="POST">
|
|
||||||
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
|
|
||||||
<span data-i18n="update_instruction">Choose a firmware update file to upload:</span> <br/> <br/>
|
|
||||||
<input name="uploadedfile" type="file" accept=".bin" /><br />
|
|
||||||
<input style="margin-top:3em" type="submit" data-i18n="update_upload" value="Upload File" />
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<script src="/main.js"></script>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<title data-i18n="vlan_title">FreeSwitchOS VLAN Configuration</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav id="sidebar"></nav>
|
|
||||||
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
|
|
||||||
<div id="ports"></div>
|
|
||||||
<h1 data-i18n="vlan_heading">VLAN Configuration</h1>
|
|
||||||
<form id="vform" action="/vlan.html">
|
|
||||||
<div>
|
|
||||||
<label for="vlanSelect" data-i18n="vlan_select">VLAN Select:</label>
|
|
||||||
<select id="vlanSelect" style="margin: 0 0 0 8px">
|
|
||||||
<option value="" disabled selected data-i18n="vlan_choose">— VLAN Choose —</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<label for="vid" data-i18n="vlan_id">VLAN ID:</label>
|
|
||||||
<input type="number" min="1" max="4094" id="vid" name="vid">
|
|
||||||
<button type="button" style="margin: 0 0 0 24px" onclick="fetchVLAN();" data-i18n="vlan_get_config">Get Configuration</button>
|
|
||||||
</div>
|
|
||||||
<br/><br/>
|
|
||||||
<label for="vname" data-i18n="vlan_name">VLAN Name:</label>
|
|
||||||
<input type="text" id="vname" name="vname"><br><br>
|
|
||||||
<br/>
|
|
||||||
<h2 data-i18n="vlan_tagged">Tagged Ports</h2>
|
|
||||||
<div id="tPorts"><button type="button" style="transform: translateY(-100%);margin: 0 50px 0 0" onclick="utClicked(true);" data-i18n="vlan_select_all">Select all</button></div>
|
|
||||||
<h2 data-i18n="vlan_untagged">Untagged Ports</h2>
|
|
||||||
<div id="uPorts"><button type="button" style="transform: translateY(-100%); margin: 0 50px 0 0" onclick="utClicked(false);" data-i18n="vlan_select_all">Select all</button> </div>
|
|
||||||
<h2 data-i18n="vlan_pvid">Use as default VLAN for incoming traffic (PVID)</h2>
|
|
||||||
<div id="pPorts"><button type="button" style="transform: translateY(-100%); margin: 0 50px 0 0" onclick="pvClicked(true);" data-i18n="vlan_select_all">Select all</button> </div>
|
|
||||||
<br/> <input style="width:40%;" class="action" id="vlan_sub" onclick="vlanSub();" type="button" data-i18n="vlan_update" value="Update / Create">
|
|
||||||
</form>
|
|
||||||
<h2 data-i18n="vlan_configured">Configured VLANs</h2>
|
|
||||||
<table id="vlanTable" style="width:90%">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>VLAN</th>
|
|
||||||
<th data-i18n="vlan_col_name">Name</th>
|
|
||||||
<th data-i18n="vlan_col_member">Member Ports</th>
|
|
||||||
<th data-i18n="vlan_col_tagged">Tagged Ports</th>
|
|
||||||
<th data-i18n="vlan_col_untagged">Untagged Ports</th>
|
|
||||||
<th data-i18n="vlan_col_pvid">PVID Ports</th>
|
|
||||||
<th data-i18n="vlan_col_delete">Delete</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody id="vlanTableBody">
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
+32
-4
@@ -1,10 +1,10 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Safe minifier for the WebUI sources (HTML/JS).
|
"""Safe minifier for the WebUI sources (HTML/JS).
|
||||||
|
|
||||||
Removes comments and line-leading whitespace without touching string
|
Removes comments and line-leading whitespace without touching string or
|
||||||
literals, so the output is functionally identical to the input. Used
|
regex literals, so the output is functionally identical to the input.
|
||||||
by the firmware Makefile before the files are embedded in the flash;
|
Used by the firmware Makefile before the files are embedded in the
|
||||||
the raw sources in html/ stay untouched for development.
|
flash; the raw sources in html/ stay untouched for development.
|
||||||
|
|
||||||
Binary files (.ico) are copied through unchanged.
|
Binary files (.ico) are copied through unchanged.
|
||||||
|
|
||||||
@@ -19,6 +19,10 @@ def js_min(s):
|
|||||||
out = []
|
out = []
|
||||||
i = 0
|
i = 0
|
||||||
n = len(s)
|
n = len(s)
|
||||||
|
prev = '\n'
|
||||||
|
# Characters after which a '/' starts a regex literal rather than a
|
||||||
|
# division: operator / delimiter / statement-start contexts.
|
||||||
|
regex_start = set('([{=,:;!&|?+-*%^~<>')
|
||||||
while i < n:
|
while i < n:
|
||||||
c = s[i]
|
c = s[i]
|
||||||
if c == '"' or c == "'":
|
if c == '"' or c == "'":
|
||||||
@@ -29,6 +33,28 @@ def js_min(s):
|
|||||||
j += 1
|
j += 1
|
||||||
out.append(s[i:j + 1])
|
out.append(s[i:j + 1])
|
||||||
i = j + 1
|
i = j + 1
|
||||||
|
prev = c
|
||||||
|
elif c == '/' and (i + 1 >= n or s[i + 1] not in '/=*') and \
|
||||||
|
(prev in regex_start or prev == '\n'):
|
||||||
|
# Regex literal (e.g. /^#\// or /https?:\/\/x/g): copy through
|
||||||
|
# the closing '/', honouring escapes and character classes.
|
||||||
|
j = i + 1
|
||||||
|
in_class = False
|
||||||
|
while j < n:
|
||||||
|
ch = s[j]
|
||||||
|
if ch == '\\':
|
||||||
|
j += 2
|
||||||
|
continue
|
||||||
|
if ch == '[':
|
||||||
|
in_class = True
|
||||||
|
elif ch == ']':
|
||||||
|
in_class = False
|
||||||
|
elif ch == '/' and not in_class:
|
||||||
|
break
|
||||||
|
j += 1
|
||||||
|
out.append(s[i:j + 1])
|
||||||
|
i = j + 1
|
||||||
|
prev = '/'
|
||||||
elif c == '/' and i + 1 < n and s[i + 1] == '/':
|
elif c == '/' and i + 1 < n and s[i + 1] == '/':
|
||||||
j = s.find('\n', i)
|
j = s.find('\n', i)
|
||||||
i = j if j >= 0 else n
|
i = j if j >= 0 else n
|
||||||
@@ -38,6 +64,8 @@ def js_min(s):
|
|||||||
else:
|
else:
|
||||||
out.append(c)
|
out.append(c)
|
||||||
i += 1
|
i += 1
|
||||||
|
if c not in ' \t':
|
||||||
|
prev = c
|
||||||
lines = [l.strip() for l in ''.join(out).split('\n')]
|
lines = [l.strip() for l in ''.join(out).split('\n')]
|
||||||
return '\n'.join(l for l in lines if l) + '\n'
|
return '\n'.join(l for l in lines if l) + '\n'
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user