mirror of
https://github.com/openwrt/luci.git
synced 2026-04-15 19:01:56 +00:00
luci-mod: js linting fixes / ES6 treatment
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
This commit is contained in:
@@ -4,24 +4,24 @@
|
||||
'require poll';
|
||||
'require baseclass';
|
||||
|
||||
var callBatteryStatus = rpc.declare({
|
||||
const callBatteryStatus = rpc.declare({
|
||||
object: 'luci.battstatus',
|
||||
method: 'getBatteryStatus',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
var devices = {};
|
||||
const devices = {};
|
||||
|
||||
return baseclass.extend({
|
||||
__init__: function() {
|
||||
__init__() {
|
||||
this.updateIndicator();
|
||||
poll.add(L.bind(this.updateIndicator, this), 5);
|
||||
},
|
||||
|
||||
updateIndicator: function() {
|
||||
updateIndicator() {
|
||||
return callBatteryStatus().then(L.bind(function(devs) {
|
||||
for (var dev in devs) {
|
||||
var info = devs[dev];
|
||||
for (let dev in devs) {
|
||||
let info = devs[dev];
|
||||
if (info.valid) {
|
||||
info.status = (info.charging ? _('Charging') : _('Not Charging')) + ": " + info.percentage + "%";
|
||||
info.state = "active";
|
||||
@@ -44,7 +44,7 @@ return baseclass.extend({
|
||||
devices[dev] = info;
|
||||
}
|
||||
|
||||
for (var dev in devices) {
|
||||
for (let dev in devices) {
|
||||
if (!devs.hasOwnProperty(dev)) {
|
||||
ui.hideIndicator('battery-%s'.format(dev));
|
||||
delete devices[dev];
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Rendering of DSL spectrum graphs showing
|
||||
// US/DS SNR and US/DS bits/tone
|
||||
//
|
||||
// This version does depend on an ubus version that support DSL line stattiscis but
|
||||
// This version does depend on an ubus version that support DSL line statistics but
|
||||
// does not depend on chart.js or any other package
|
||||
|
||||
class DataSet {
|
||||
@@ -221,7 +221,7 @@ let hLogChart = {
|
||||
]
|
||||
};
|
||||
|
||||
function drawChart (info) {
|
||||
function drawChart(info) {
|
||||
drawAxisX(info.config, info.config.minX, info.config.maxX, info.config.stepX, info.config.titleX);
|
||||
drawAxisY(info.config, info.config.minY, info.config.maxY, info.config.stepY, info.config.titleY);
|
||||
|
||||
@@ -236,17 +236,10 @@ function drawChart (info) {
|
||||
}
|
||||
}
|
||||
|
||||
function drawBlocks(config, dataPoints, color, borders) {
|
||||
borders.map(drawBlock, {config, dataPoints, color, borders});
|
||||
}
|
||||
|
||||
function drawLines(config, dataPoints, color) {
|
||||
let ctx = config.ctx;
|
||||
let len = dataPoints.length;
|
||||
let minX = config.minX;
|
||||
let maxX = config.maxX;
|
||||
let minY = config.minY;
|
||||
let maxY = config.maxY;
|
||||
|
||||
ctx.strokeStyle = color;
|
||||
ctx.beginPath();
|
||||
@@ -292,7 +285,6 @@ function drawData(config, dataPoints, color) {
|
||||
function drawLegend(config, dataSet){
|
||||
let ctx = config.ctx;
|
||||
let graphWidth = config.graphWidth;
|
||||
let graphHeight = config.graphHeight;
|
||||
|
||||
ctx.font = "12px Arial";
|
||||
|
||||
@@ -329,7 +321,6 @@ function drawLegend(config, dataSet){
|
||||
function drawAxisX(config, minValue, maxValue, step, title) {
|
||||
let ctx = config.ctx;
|
||||
let graphWidth = config.graphWidth;
|
||||
let graphHeight = config.graphHeight;
|
||||
|
||||
ctx.font = "12px Arial";
|
||||
ctx.textAlign = "center";
|
||||
@@ -360,7 +351,6 @@ function drawAxisX(config, minValue, maxValue, step, title) {
|
||||
|
||||
function drawAxisY(config, minValue, maxValue, step, title) {
|
||||
let ctx = config.ctx
|
||||
let graphWidth = config.graphWidth;
|
||||
let graphHeight = config.graphHeight;
|
||||
|
||||
ctx.font = "12px Arial";
|
||||
|
||||
@@ -4,23 +4,23 @@
|
||||
'require ui';
|
||||
'require rpc';
|
||||
|
||||
var callDSLStatistics = rpc.declare({
|
||||
const callDSLStatistics = rpc.declare({
|
||||
object: 'dsl',
|
||||
method: 'statistics',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
callDSLStatistics()
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
render(data) {
|
||||
window.json = data[0];
|
||||
|
||||
var v = E('div', {'class': 'cbi-map'}, [
|
||||
const v = E('div', {'class': 'cbi-map'}, [
|
||||
E('h2', {'style': "height: 40px"}, [ _('DSL line spectrum') ]),
|
||||
E('div', {'class': 'cbi-map-descr'}, _('The following diagrams show graphically prepared DSL characteristics that are important for evaluating the DSL connection.')),
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
'require poll';
|
||||
'require rpc';
|
||||
|
||||
var callDSLMetrics = rpc.declare({
|
||||
const callDSLMetrics = rpc.declare({
|
||||
object: 'dsl',
|
||||
method: 'metrics',
|
||||
expect: { '': {} }
|
||||
@@ -19,11 +19,11 @@ function format_latency(val) {
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return L.resolveDefault(callDSLMetrics(), {});
|
||||
},
|
||||
|
||||
pollData: function(container) {
|
||||
pollData(container) {
|
||||
poll.add(L.bind(function() {
|
||||
return L.resolveDefault(callDSLMetrics(), {}).then(L.bind(function(data) {
|
||||
dom.content(container, this.renderContent(data));
|
||||
@@ -31,7 +31,7 @@ return view.extend({
|
||||
}, this));
|
||||
},
|
||||
|
||||
formatHelper: function(format, val) {
|
||||
formatHelper(format, val) {
|
||||
if (val != null) {
|
||||
if (format instanceof Function) {
|
||||
return format(val);
|
||||
@@ -44,14 +44,14 @@ return view.extend({
|
||||
return '-';
|
||||
},
|
||||
|
||||
renderSimpleTable: function(data) {
|
||||
var table = E('table', { 'class': 'table' });
|
||||
renderSimpleTable(data) {
|
||||
const table = E('table', { 'class': 'table' });
|
||||
|
||||
for (var [i, item] of data.entries()) {
|
||||
var label = item[0];
|
||||
var val = item[1];
|
||||
for (let [i, item] of data.entries()) {
|
||||
const label = item[0];
|
||||
const val = item[1];
|
||||
|
||||
var rowstyle = (i % 2 == 0) ? 'cbi-rowstyle-1' : 'cbi-rowstyle-2';
|
||||
const rowstyle = (i % 2 == 0) ? 'cbi-rowstyle-1' : 'cbi-rowstyle-2';
|
||||
|
||||
table.appendChild(E('tr', { 'class': 'tr ' + rowstyle }, [
|
||||
E('td', { 'class': 'td left', 'width': '33%' }, [ label ]),
|
||||
@@ -62,16 +62,16 @@ return view.extend({
|
||||
return E('div', { 'class': 'cbi-section' }, table);
|
||||
},
|
||||
|
||||
renderTable: function(data) {
|
||||
var table = E('table', { 'class': 'table' });
|
||||
renderTable(data) {
|
||||
const table = E('table', { 'class': 'table' });
|
||||
|
||||
for (var [i, item] of data.entries()) {
|
||||
var label = item[0];
|
||||
var format = item[1];
|
||||
var val1 = item[2];
|
||||
var val2 = item[3];
|
||||
for (let [i, item] of data.entries()) {
|
||||
const label = item[0];
|
||||
const format = item[1];
|
||||
const val1 = item[2];
|
||||
const val2 = item[3];
|
||||
|
||||
var rowstyle = (i % 2 == 0) ? 'cbi-rowstyle-1' : 'cbi-rowstyle-2';
|
||||
const rowstyle = (i % 2 == 0) ? 'cbi-rowstyle-1' : 'cbi-rowstyle-2';
|
||||
|
||||
table.appendChild(E('tr', { 'class': 'tr ' + rowstyle }, [
|
||||
E('td', { 'class': 'td left', 'width': '33%' }, [ label ]),
|
||||
@@ -83,7 +83,7 @@ return view.extend({
|
||||
return E('div', { 'class': 'cbi-section' }, table);
|
||||
},
|
||||
|
||||
renderContent: function(data) {
|
||||
renderContent(data) {
|
||||
return E([], [
|
||||
|
||||
E('h3', {}, [ _('Connection State') ]),
|
||||
@@ -169,13 +169,13 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var v = E([], [
|
||||
render(data) {
|
||||
const v = E([], [
|
||||
E('h2', {}, [ _('DSL stats') ]),
|
||||
E('div')
|
||||
]);
|
||||
|
||||
var container = v.lastElementChild;
|
||||
const container = v.lastElementChild;
|
||||
dom.content(container, this.renderContent(data));
|
||||
this.pollData(container);
|
||||
|
||||
|
||||
@@ -146,10 +146,11 @@ return baseclass.extend({
|
||||
},
|
||||
|
||||
encodeSvcParamValue(key, value) {
|
||||
const seen = new Set();
|
||||
let keys, port;
|
||||
switch (key) {
|
||||
case 'mandatory':
|
||||
const seen = new Set();
|
||||
const keys = value.split(',')
|
||||
keys = value.split(',')
|
||||
.map(k => k.trim())
|
||||
.filter(k => {
|
||||
if (seen.has(k)) return false; // D3 Figure 16
|
||||
@@ -176,7 +177,7 @@ return baseclass.extend({
|
||||
return []; // zero-length value - D3 Figure 13
|
||||
|
||||
case 'port': // D2 Figure 4
|
||||
const port = parseInt(value, 10);
|
||||
port = parseInt(value, 10);
|
||||
return [(port >> 8) & 0xff, port & 0xff];
|
||||
|
||||
case 'ipv4hint':
|
||||
@@ -311,9 +312,11 @@ return baseclass.extend({
|
||||
},
|
||||
|
||||
decodeSvcParamValue(key, buf) {
|
||||
const keys = [];
|
||||
const addrs = [];
|
||||
|
||||
switch (key) {
|
||||
case 'mandatory':
|
||||
const keys = [];
|
||||
for (let i = 0; i + 1 < buf.length; i += 2) {
|
||||
const k = (buf[i] << 8) | buf[i + 1];
|
||||
keys.push(this.svcParamKeyFromNumber(k));
|
||||
@@ -351,7 +354,6 @@ return baseclass.extend({
|
||||
// return Array.from(buf).map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
|
||||
case 'ipv6hint':
|
||||
const addrs = [];
|
||||
for (let i = 0; i + 15 <= buf.length; i += 16) {
|
||||
let addr = [];
|
||||
for (let j = 0; j < 16; j += 2) {
|
||||
|
||||
@@ -9,21 +9,11 @@
|
||||
'require validation';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
function validateAddr(section_id, value) {
|
||||
if (value == '')
|
||||
return true;
|
||||
|
||||
var ipv6 = /6$/.test(this.section.formvalue(section_id, 'mode')),
|
||||
addr = ipv6 ? validation.parseIPv6(value) : validation.parseIPv4(value);
|
||||
|
||||
return addr ? true : (ipv6 ? _('Expecting a valid IPv6 address') : _('Expecting a valid IPv4 address'));
|
||||
}
|
||||
|
||||
function validateQoSMap(section_id, value) {
|
||||
if (value == '')
|
||||
return true;
|
||||
|
||||
var m = value.match(/^(\d+):(\d+)$/);
|
||||
const m = value.match(/^(\d+):(\d+)$/);
|
||||
|
||||
if (!m || +m[1] > 0xFFFFFFFF || +m[2] > 0xFFFFFFFF)
|
||||
return _('Expecting two priority values separated by a colon');
|
||||
@@ -32,7 +22,7 @@ function validateQoSMap(section_id, value) {
|
||||
}
|
||||
|
||||
function deviceSectionExists(section_id, devname) {
|
||||
var exists = false;
|
||||
let exists = false;
|
||||
|
||||
uci.sections('network', 'device', function(ss) {
|
||||
exists = exists || (
|
||||
@@ -51,7 +41,7 @@ function isBridgePort(dev) {
|
||||
if (dev.isBridgePort())
|
||||
return true;
|
||||
|
||||
var isPort = false;
|
||||
let isPort = false;
|
||||
|
||||
uci.sections('network', null, function(s) {
|
||||
if (s['.type'] != 'interface' && s['.type'] != 'device')
|
||||
@@ -65,8 +55,8 @@ function isBridgePort(dev) {
|
||||
}
|
||||
|
||||
function updateDevBadge(node, dev) {
|
||||
var type = dev.getType(),
|
||||
up = dev.getCarrier();
|
||||
const type = dev.getType();
|
||||
const up = dev.getCarrier();
|
||||
|
||||
dom.content(node, [
|
||||
E('img', {
|
||||
@@ -88,10 +78,10 @@ function renderDevBadge(dev) {
|
||||
}
|
||||
|
||||
function updatePortStatus(node, dev) {
|
||||
var carrier = dev.getCarrier(),
|
||||
duplex = dev.getDuplex(),
|
||||
speed = dev.getSpeed(),
|
||||
desc, title;
|
||||
const carrier = dev.getCarrier();
|
||||
const duplex = dev.getDuplex();
|
||||
const speed = dev.getSpeed();
|
||||
let desc, title;
|
||||
|
||||
if (carrier && speed > 0 && duplex != null) {
|
||||
desc = '%d%s'.format(speed, duplex == 'full' ? 'FD' : 'HD');
|
||||
@@ -130,7 +120,7 @@ function renderPortStatus(dev) {
|
||||
function updatePlaceholders(opt, section_id) {
|
||||
var dev = network.instantiateDevice(opt.getUIElement(section_id).getValue());
|
||||
|
||||
for (var i = 0, co; (co = opt.section.children[i]) != null; i++) {
|
||||
for (let i = 0, co; (co = opt.section.children[i]) != null; i++) {
|
||||
if (co !== opt) {
|
||||
switch (co.option) {
|
||||
case 'mtu':
|
||||
@@ -151,14 +141,14 @@ function updatePlaceholders(opt, section_id) {
|
||||
}
|
||||
|
||||
var cbiFlagTristate = form.ListValue.extend({
|
||||
__init__: function(/* ... */) {
|
||||
__init__(/* ... */) {
|
||||
this.super('__init__', arguments);
|
||||
this.keylist = [ '', '0!', '1!' ];
|
||||
this.vallist = [ _('automatic'), _('disabled'), _('enabled') ];
|
||||
},
|
||||
|
||||
load: function(section_id) {
|
||||
var invert = false, sysfs = this.sysfs;
|
||||
load(section_id) {
|
||||
let invert = false, sysfs = this.sysfs;
|
||||
|
||||
if (sysfs) {
|
||||
if (sysfs.charAt(0) == '!') {
|
||||
@@ -181,7 +171,7 @@ var cbiFlagTristate = form.ListValue.extend({
|
||||
return this.super('load', [section_id]);
|
||||
},
|
||||
|
||||
write: function(section_id, formvalue) {
|
||||
write(section_id, formvalue) {
|
||||
if (formvalue == '1!')
|
||||
return this.super('write', [section_id, '1']);
|
||||
else if (formvalue == '0!')
|
||||
@@ -190,8 +180,8 @@ var cbiFlagTristate = form.ListValue.extend({
|
||||
return this.super('remove', [section_id]);
|
||||
},
|
||||
|
||||
renderWidget: function(section_id, option_index, cfgvalue) {
|
||||
var sysdef = this.sysfs_default;
|
||||
renderWidget(section_id, option_index, cfgvalue) {
|
||||
const sysdef = this.sysfs_default;
|
||||
|
||||
if (this.sysfs_default !== null) {
|
||||
this.keylist[0] = sysdef ? '1' : '0';
|
||||
@@ -203,9 +193,9 @@ var cbiFlagTristate = form.ListValue.extend({
|
||||
});
|
||||
|
||||
|
||||
var cbiTagValue = form.Value.extend({
|
||||
renderWidget: function(section_id, option_index, cfgvalue) {
|
||||
var widget = new ui.Dropdown(cfgvalue || ['-'], {
|
||||
const cbiTagValue = form.Value.extend({
|
||||
renderWidget(section_id, option_index, cfgvalue) {
|
||||
const widget = new ui.Dropdown(cfgvalue || ['-'], {
|
||||
'-': E([], [
|
||||
E('span', { 'class': 'hide-open', 'style': 'font-family:monospace' }, [ '—' ]),
|
||||
E('span', { 'class': 'hide-close' }, [ _('Not Member', 'VLAN port state') ])
|
||||
@@ -229,11 +219,11 @@ var cbiTagValue = form.Value.extend({
|
||||
multiple: true
|
||||
});
|
||||
|
||||
var field = this;
|
||||
const field = this;
|
||||
|
||||
widget.toggleItem = function(sb, li, force_state) {
|
||||
var lis = li.parentNode.querySelectorAll('li'),
|
||||
toggle = ui.Dropdown.prototype.toggleItem;
|
||||
const lis = li.parentNode.querySelectorAll('li');
|
||||
const toggle = ui.Dropdown.prototype.toggleItem;
|
||||
|
||||
toggle.apply(this, [sb, li, force_state]);
|
||||
|
||||
@@ -244,7 +234,7 @@ var cbiTagValue = form.Value.extend({
|
||||
{
|
||||
case '-':
|
||||
if (li.hasAttribute('selected')) {
|
||||
for (var i = 0; i < lis.length; i++) {
|
||||
for (let i = 0; i < lis.length; i++) {
|
||||
switch (lis[i].getAttribute('data-value')) {
|
||||
case '-':
|
||||
break;
|
||||
@@ -264,7 +254,7 @@ var cbiTagValue = form.Value.extend({
|
||||
case 't':
|
||||
case 'u':
|
||||
if (li.hasAttribute('selected')) {
|
||||
for (var i = 0; i < lis.length; i++) {
|
||||
for (let i = 0; i < lis.length; i++) {
|
||||
switch (lis[i].getAttribute('data-value')) {
|
||||
case li.getAttribute('data-value'):
|
||||
break;
|
||||
@@ -285,16 +275,16 @@ var cbiTagValue = form.Value.extend({
|
||||
|
||||
case '*':
|
||||
if (li.hasAttribute('selected')) {
|
||||
var section_ids = field.section.cfgsections();
|
||||
const section_ids = field.section.cfgsections();
|
||||
|
||||
for (var i = 0; i < section_ids.length; i++) {
|
||||
var other_widget = field.getUIElement(section_ids[i]),
|
||||
other_value = L.toArray(other_widget.getValue());
|
||||
for (let i = 0; i < section_ids.length; i++) {
|
||||
const other_widget = field.getUIElement(section_ids[i]);
|
||||
const other_value = L.toArray(other_widget.getValue());
|
||||
|
||||
if (other_widget === this)
|
||||
continue;
|
||||
|
||||
var new_value = other_value.filter(function(v) { return v != '*' });
|
||||
const new_value = other_value.filter(function(v) { return v != '*' });
|
||||
|
||||
if (new_value.length == other_value.length)
|
||||
continue;
|
||||
@@ -306,7 +296,7 @@ var cbiTagValue = form.Value.extend({
|
||||
}
|
||||
};
|
||||
|
||||
var node = widget.render();
|
||||
const node = widget.render();
|
||||
|
||||
node.style.minWidth = '4em';
|
||||
|
||||
@@ -316,16 +306,16 @@ var cbiTagValue = form.Value.extend({
|
||||
return E('div', { 'style': 'display:inline-block' }, node);
|
||||
},
|
||||
|
||||
cfgvalue: function(section_id) {
|
||||
var ports = L.toArray(uci.get('network', section_id, 'ports'));
|
||||
cfgvalue(section_id) {
|
||||
const ports = L.toArray(uci.get('network', section_id, 'ports'));
|
||||
|
||||
for (var i = 0; i < ports.length; i++) {
|
||||
var s = ports[i].split(/:/);
|
||||
for (let i = 0; i < ports.length; i++) {
|
||||
const s = ports[i].split(/:/);
|
||||
|
||||
if (s[0] != this.port)
|
||||
continue;
|
||||
|
||||
var t = /t/.test(s[1] || '') ? 't' : 'u';
|
||||
const t = /t/.test(s[1] || '') ? 't' : 'u';
|
||||
|
||||
return /\x2a/.test(s[1] || '') ? [t, '*'] : [t];
|
||||
}
|
||||
@@ -333,12 +323,10 @@ var cbiTagValue = form.Value.extend({
|
||||
return ['-'];
|
||||
},
|
||||
|
||||
write: function(section_id, value) {
|
||||
var ports = [];
|
||||
|
||||
for (var i = 0; i < this.section.children.length; i++) {
|
||||
var opt = this.section.children[i];
|
||||
write(section_id, value) {
|
||||
const ports = [];
|
||||
|
||||
for (let opt of this.section.children) {
|
||||
if (opt.port) {
|
||||
var val = L.toArray(opt.formvalue(section_id)).join('');
|
||||
|
||||
@@ -360,7 +348,7 @@ var cbiTagValue = form.Value.extend({
|
||||
uci.set('network', section_id, 'ports', ports.length ? ports : null);
|
||||
},
|
||||
|
||||
remove: function() {}
|
||||
remove() {}
|
||||
});
|
||||
|
||||
return baseclass.extend({
|
||||
@@ -422,8 +410,8 @@ return baseclass.extend({
|
||||
{ n: 'rohc', i: 142, d: 'ROHC' },
|
||||
],
|
||||
|
||||
replaceOption: function(s, tabName, optionClass, optionName, optionTitle, optionDescription) {
|
||||
var o = s.getOption(optionName);
|
||||
replaceOption(s, tabName, optionClass, optionName, optionTitle, optionDescription) {
|
||||
const o = s.getOption(optionName);
|
||||
|
||||
if (o) {
|
||||
if (o.tab) {
|
||||
@@ -440,10 +428,10 @@ return baseclass.extend({
|
||||
return s.taboption(tabName, optionClass, optionName, optionTitle, optionDescription);
|
||||
},
|
||||
|
||||
addDeviceOptions: function(s, dev, isNew, rtTables, hasPSE) {
|
||||
var parent_dev = dev ? dev.getParent() : null,
|
||||
devname = dev ? dev.getName() : null,
|
||||
o, ss;
|
||||
addDeviceOptions(s, dev, isNew, rtTables, hasPSE) {
|
||||
const parent_dev = dev ? dev.getParent() : null;
|
||||
const devname = dev ? dev.getName() : null;
|
||||
let o, ss;
|
||||
|
||||
s.tab('devgeneral', _('General device options'));
|
||||
s.tab('devadvanced', _('Advanced device options'));
|
||||
@@ -693,7 +681,7 @@ return baseclass.extend({
|
||||
o.value('encap2+3', _('Encap 2+3'));
|
||||
o.value('encap3+4', _('Encap 3+4'));
|
||||
o.cfgvalue = function(/* ... */) {
|
||||
var val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
const val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
|
||||
switch (val || '') {
|
||||
case 'layer2':
|
||||
@@ -742,7 +730,7 @@ return baseclass.extend({
|
||||
o.value('bandwidth', _('Bandwidth'));
|
||||
o.value('count', _('Count'));
|
||||
o.cfgvalue = function(/* ... */) {
|
||||
var val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
const val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
|
||||
switch (val || '') {
|
||||
case 'stable':
|
||||
@@ -769,7 +757,7 @@ return baseclass.extend({
|
||||
o.value('slow', _('Slow (every 30 seconds)'));
|
||||
o.value('fast', _('Fast (every second)'));
|
||||
o.cfgvalue = function(/* ... */) {
|
||||
var val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
const val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
|
||||
switch (val || '') {
|
||||
case 'slow':
|
||||
@@ -827,7 +815,7 @@ return baseclass.extend({
|
||||
o.value('better', _('Better'));
|
||||
o.value('failure', _('Failure'));
|
||||
o.cfgvalue = function(/* ... */) {
|
||||
var val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
const val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
|
||||
switch (val || '') {
|
||||
case 'always':
|
||||
@@ -854,7 +842,7 @@ return baseclass.extend({
|
||||
o.value('active', _('Active'));
|
||||
o.value('follow', _('Follow'));
|
||||
o.cfgvalue = function(/* ... */) {
|
||||
var val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
const val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
|
||||
switch (val || '') {
|
||||
case 'none':
|
||||
@@ -882,7 +870,7 @@ return baseclass.extend({
|
||||
o.value('arp', _('ARP link monitoring'));
|
||||
o.value('mii', _('MII link monitoring'));
|
||||
o.cfgvalue = function(/* ... */) {
|
||||
var val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
const val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
|
||||
switch (val || '') {
|
||||
case 'arp':
|
||||
@@ -923,7 +911,7 @@ return baseclass.extend({
|
||||
o.value('filter_active', _('Filter active'));
|
||||
o.value('filter_backup', _('Filter backup'));
|
||||
o.cfgvalue = function(/* ... */) {
|
||||
var val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
const val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
|
||||
switch (val || '') {
|
||||
case 'none':
|
||||
@@ -988,16 +976,16 @@ return baseclass.extend({
|
||||
o.ucioption = 'ports';
|
||||
o.default = L.toArray(dev ? dev.getPorts() : null).filter(function(p) { return p.getType() != 'wifi' }).map(function(p) { return p.getName() });
|
||||
o.filter = function(section_id, device_name) {
|
||||
var bridge_name = uci.get('network', section_id, 'name'),
|
||||
const bridge_name = uci.get('network', section_id, 'name'),
|
||||
choice_dev = network.instantiateDevice(device_name),
|
||||
parent_dev = choice_dev.getParent();
|
||||
|
||||
/* only show wifi networks which are already present in "option ifname" */
|
||||
if (choice_dev.getType() == 'wifi') {
|
||||
var ifnames = L.toArray(uci.get('network', section_id, 'ports'));
|
||||
const ifnames = L.toArray(uci.get('network', section_id, 'ports'));
|
||||
|
||||
for (var i = 0; i < ifnames.length; i++)
|
||||
if (ifnames[i] == device_name)
|
||||
for (let ifn of ifnames)
|
||||
if (ifn == device_name)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -1084,8 +1072,8 @@ return baseclass.extend({
|
||||
o.placeholder = '1000';
|
||||
o.datatype = 'uinteger';
|
||||
o.validate = function(section_id, value) {
|
||||
var qiopt = L.toArray(this.map.lookupOption('query_interval', section_id))[0],
|
||||
qival = qiopt ? (qiopt.formvalue(section_id) || qiopt.placeholder) : '';
|
||||
const qiopt = L.toArray(this.map.lookupOption('query_interval', section_id))[0];
|
||||
const qival = qiopt ? (qiopt.formvalue(section_id) || qiopt.placeholder) : '';
|
||||
|
||||
if (value != '' && qival != '' && +value >= +qival)
|
||||
return _('The query response interval must be lower than the query interval value');
|
||||
@@ -1102,7 +1090,7 @@ return baseclass.extend({
|
||||
o = this.replaceOption(s, 'devgeneral', form.Value, 'mtu', _('MTU'));
|
||||
o.datatype = 'range(576, 9200)';
|
||||
o.validate = function(section_id, value) {
|
||||
var parent_mtu = (dev && dev.getType() == 'vlan') ? (parent_dev ? parent_dev.getMTU() : null) : null;
|
||||
const parent_mtu = (dev && dev.getType() == 'vlan') ? (parent_dev ? parent_dev.getMTU() : null) : null;
|
||||
|
||||
if (parent_mtu !== null && +value > parent_mtu)
|
||||
return _('The MTU must not exceed the parent device MTU of %d bytes').format(parent_mtu);
|
||||
@@ -1118,13 +1106,13 @@ return baseclass.extend({
|
||||
o.datatype = 'maxlength(15)';
|
||||
o.depends('type', 'veth');
|
||||
o.load = function(section_id) {
|
||||
var sections = uci.sections('network', 'device'),
|
||||
idx = 0;
|
||||
const sections = uci.sections('network', 'device');
|
||||
let idx = 0;
|
||||
|
||||
for (var i = 0; i < sections.length; i++)
|
||||
if (sections[i]['.name'] == section_id)
|
||||
for (let s of sections)
|
||||
if (s['.name'] == section_id)
|
||||
break;
|
||||
else if (sections[i].type == 'veth')
|
||||
else if (s.type == 'veth')
|
||||
idx++;
|
||||
|
||||
this.placeholder = 'veth%d'.format(idx);
|
||||
@@ -1178,7 +1166,7 @@ return baseclass.extend({
|
||||
o.value('loose', _('Loose filtering'));
|
||||
o.value('strict', _('Strict filtering'));
|
||||
o.cfgvalue = function(/* ... */) {
|
||||
var val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
const val = form.ListValue.prototype.cfgvalue.apply(this, arguments);
|
||||
|
||||
switch (val || '') {
|
||||
case 'loose':
|
||||
@@ -1291,9 +1279,9 @@ return baseclass.extend({
|
||||
o = this.replaceOption(s, 'bridgevlan', form.Flag, 'vlan_filtering', _('Enable VLAN filtering'));
|
||||
o.depends('type', 'bridge');
|
||||
o.updateDefaultValue = function(section_id) {
|
||||
var device = uci.get('network', s.section, 'name'),
|
||||
uielem = this.getUIElement(section_id),
|
||||
has_vlans = false;
|
||||
const device = uci.get('network', s.section, 'name');
|
||||
const uielem = this.getUIElement(section_id);
|
||||
let has_vlans = false;
|
||||
|
||||
uci.sections('network', 'bridge-vlan', function(bvs) {
|
||||
has_vlans = has_vlans || (bvs.device == device);
|
||||
@@ -1313,7 +1301,7 @@ return baseclass.extend({
|
||||
ss.anonymous = true;
|
||||
|
||||
ss.renderHeaderRows = function(/* ... */) {
|
||||
var node = form.TableSection.prototype.renderHeaderRows.apply(this, arguments);
|
||||
const node = form.TableSection.prototype.renderHeaderRows.apply(this, arguments);
|
||||
|
||||
node.querySelectorAll('.th').forEach(function(th) {
|
||||
th.classList.add('left');
|
||||
@@ -1324,7 +1312,7 @@ return baseclass.extend({
|
||||
};
|
||||
|
||||
ss.filter = function(section_id) {
|
||||
var devname = uci.get('network', s.section, 'name');
|
||||
const devname = uci.get('network', s.section, 'name');
|
||||
return (uci.get('network', section_id, 'device') == devname);
|
||||
};
|
||||
|
||||
@@ -1347,7 +1335,7 @@ return baseclass.extend({
|
||||
};
|
||||
|
||||
ss.updatePorts = function(ports) {
|
||||
var devices = ports.map(function(port) {
|
||||
const devices = ports.map(function(port) {
|
||||
return network.instantiateDevice(port)
|
||||
}).filter(function(dev) {
|
||||
return dev.getType() != 'wifi' || dev.isUp();
|
||||
@@ -1357,35 +1345,35 @@ return baseclass.extend({
|
||||
|
||||
this.children = this.children.filter(function(opt) { return !opt.option.match(/^port_/) });
|
||||
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
o = ss.option(cbiTagValue, 'port_%s'.format(sfh(devices[i].getName())), renderDevBadge(devices[i]), renderPortStatus(devices[i]));
|
||||
o.port = devices[i].getName();
|
||||
for (let d of devices) {
|
||||
o = ss.option(cbiTagValue, 'port_%s'.format(sfh(d.getName())), renderDevBadge(d), renderPortStatus(d));
|
||||
o.port = d.getName();
|
||||
}
|
||||
|
||||
var section_ids = this.cfgsections(),
|
||||
device_names = devices.reduce(function(names, dev) { names[dev.getName()] = true; return names }, {});
|
||||
const section_ids = this.cfgsections();
|
||||
const device_names = devices.reduce(function(names, dev) { names[dev.getName()] = true; return names }, {});
|
||||
|
||||
for (var i = 0; i < section_ids.length; i++) {
|
||||
var old_spec = L.toArray(uci.get('network', section_ids[i], 'ports')),
|
||||
new_spec = old_spec.filter(function(spec) { return device_names[spec.replace(/:[ut*]+$/, '')] });
|
||||
for (let s of section_ids) {
|
||||
const old_spec = L.toArray(uci.get('network', s, 'ports'));
|
||||
const new_spec = old_spec.filter(function(spec) { return device_names[spec.replace(/:[ut*]+$/, '')] });
|
||||
|
||||
if (old_spec.length != new_spec.length)
|
||||
uci.set('network', section_ids[i], 'ports', new_spec.length ? new_spec : null);
|
||||
uci.set('network', s, 'ports', new_spec.length ? new_spec : null);
|
||||
}
|
||||
};
|
||||
|
||||
ss.handleAdd = function(ev) {
|
||||
return s.parse().then(L.bind(function() {
|
||||
var device = uci.get('network', s.section, 'name'),
|
||||
section_ids = this.cfgsections(),
|
||||
section_id = null,
|
||||
max_vlan_id = 0;
|
||||
const device = uci.get('network', s.section, 'name');
|
||||
const section_ids = this.cfgsections();
|
||||
let section_id = null;
|
||||
let max_vlan_id = 0;
|
||||
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
for (var i = 0; i < section_ids.length; i++) {
|
||||
var vid = +uci.get('network', section_ids[i], 'vlan');
|
||||
for (let s of section_ids) {
|
||||
var vid = +uci.get('network', s, 'vlan');
|
||||
|
||||
if (vid > max_vlan_id)
|
||||
max_vlan_id = vid;
|
||||
@@ -1428,7 +1416,7 @@ return baseclass.extend({
|
||||
o.datatype = 'range(1, 4094)';
|
||||
|
||||
o.renderWidget = function(/* ... */) {
|
||||
var node = form.Value.prototype.renderWidget.apply(this, arguments);
|
||||
const node = form.Value.prototype.renderWidget.apply(this, arguments);
|
||||
|
||||
node.style.width = '5em';
|
||||
|
||||
@@ -1436,13 +1424,13 @@ return baseclass.extend({
|
||||
};
|
||||
|
||||
o.validate = function(section_id, value) {
|
||||
var section_ids = this.section.cfgsections();
|
||||
const section_ids = this.section.cfgsections();
|
||||
|
||||
for (var i = 0; i < section_ids.length; i++) {
|
||||
if (section_ids[i] == section_id)
|
||||
for (let s of section_ids) {
|
||||
if (s == section_id)
|
||||
continue;
|
||||
|
||||
if (uci.get('network', section_ids[i], 'vlan') == value)
|
||||
if (uci.get('network', s, 'vlan') == value)
|
||||
return _('The VLAN ID must be unique');
|
||||
}
|
||||
|
||||
|
||||
@@ -534,7 +534,6 @@ return view.extend({
|
||||
else
|
||||
return _('Address families of "Relay from" and "Relay to address" must match.')
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
so = ss.option(widgets.NetworkSelect, 'interface', _('Only accept replies via'));
|
||||
|
||||
@@ -90,14 +90,14 @@ function validateServerSpec(sid, s) {
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
callHostHints(),
|
||||
uci.load('firewall')
|
||||
]);
|
||||
},
|
||||
|
||||
render: function([hosts]) {
|
||||
render([hosts]) {
|
||||
let m, s, o, ss, so, dnss;
|
||||
|
||||
let noi18nstrings = {
|
||||
@@ -524,6 +524,7 @@ return view.extend({
|
||||
let target = this.section.formvalue(section_id, '_svc_target') || '.';
|
||||
let params = value.trim().split('\n').map(l => l.trim()).filter(Boolean);
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const hex = drh.buildSvcbHex(priority, target, params);
|
||||
uci.set('dhcp', section_id, 'hexdata', hex);
|
||||
};
|
||||
@@ -533,6 +534,7 @@ return view.extend({
|
||||
if (rrnum !== '65') return null;
|
||||
|
||||
let hexdata = uci.get('dhcp', section_id, 'hexdata');
|
||||
// eslint-disable-next-line no-undef
|
||||
return drh.parseSvcbHex(hexdata);
|
||||
};
|
||||
|
||||
|
||||
@@ -28,12 +28,12 @@ function count_changes(section_id) {
|
||||
return n;
|
||||
|
||||
if (Array.isArray(changes.network))
|
||||
for (var i = 0; i < changes.network.length; i++)
|
||||
n += (changes.network[i][1] == section_id);
|
||||
for (let c of changes.network)
|
||||
n += (c[1] == section_id);
|
||||
|
||||
if (Array.isArray(changes.dhcp))
|
||||
for (var i = 0; i < changes.dhcp.length; i++)
|
||||
n += (changes.dhcp[i][1] == section_id);
|
||||
for (let c of changes.dhcp)
|
||||
n += (c[1] == section_id);
|
||||
|
||||
return n;
|
||||
}
|
||||
@@ -62,7 +62,7 @@ function render_iface(dev, alias) {
|
||||
}
|
||||
|
||||
function render_status(node, ifc, with_device) {
|
||||
var desc = null, c = [];
|
||||
let desc = null;
|
||||
|
||||
if (ifc.isDynamic())
|
||||
desc = _('Virtual dynamic interface');
|
||||
@@ -125,9 +125,9 @@ function render_modal_status(node, ifc) {
|
||||
}
|
||||
|
||||
function render_ifacebox_status(node, ifc) {
|
||||
var dev = ifc.getL3Device() || ifc.getDevice(),
|
||||
subdevs = dev ? dev.getPorts() : null,
|
||||
c = [ render_iface(dev, ifc.isAlias()) ];
|
||||
const dev = ifc.getL3Device() || ifc.getDevice();
|
||||
const subdevs = dev ? dev.getPorts() : null;
|
||||
const c = [ render_iface(dev, ifc.isAlias()) ];
|
||||
|
||||
if (subdevs && subdevs.length) {
|
||||
var sifs = [ ' (' ];
|
||||
@@ -142,7 +142,7 @@ function render_ifacebox_status(node, ifc) {
|
||||
|
||||
c.push(E('br'));
|
||||
c.push(E('small', {}, ifc.isAlias() ? _('Alias of "%s"').format(ifc.isAlias())
|
||||
: (dev ? dev.getName() : E('em', _('Not present')))));
|
||||
: (dev ? dev.getName() : E('em', _('Not present')))));
|
||||
|
||||
dom.content(node, c);
|
||||
|
||||
@@ -153,9 +153,9 @@ function render_ifacebox_status(node, ifc) {
|
||||
}
|
||||
|
||||
function iface_updown(up, id, ev, force) {
|
||||
var row = document.querySelector('.cbi-section-table-row[data-sid="%s"]'.format(id)),
|
||||
dsc = row.querySelector('[data-name="_ifacestat"] > div'),
|
||||
btns = row.querySelectorAll('.cbi-section-actions .reconnect, .cbi-section-actions .down');
|
||||
const row = document.querySelector('.cbi-section-table-row[data-sid="%s"]'.format(id));
|
||||
const dsc = row.querySelector('[data-name="_ifacestat"] > div');
|
||||
const btns = row.querySelectorAll('.cbi-section-actions .reconnect, .cbi-section-actions .down');
|
||||
|
||||
btns[+!up].blur();
|
||||
btns[+!up].classList.add('spinning');
|
||||
@@ -176,7 +176,7 @@ function iface_updown(up, id, ev, force) {
|
||||
E('div', { 'class': 'button-row' }, [
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cbi-button-neutral',
|
||||
'click': function(ev) {
|
||||
'click': function (ev) {
|
||||
btns[1].classList.remove('spinning');
|
||||
btns[1].disabled = false;
|
||||
btns[0].disabled = false;
|
||||
@@ -187,7 +187,7 @@ function iface_updown(up, id, ev, force) {
|
||||
' ',
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cbi-button-negative important',
|
||||
'click': function(ev) {
|
||||
'click': function (ev) {
|
||||
dsc.setAttribute('disconnect', '');
|
||||
dom.content(dsc, E('em', _('Interface is shutting down...')));
|
||||
|
||||
@@ -210,15 +210,15 @@ function iface_updown(up, id, ev, force) {
|
||||
}
|
||||
|
||||
function get_netmask(s, use_cfgvalue) {
|
||||
var readfn = use_cfgvalue ? 'cfgvalue' : 'formvalue',
|
||||
addrs = L.toArray(s[readfn](s.section, 'ipaddr')),
|
||||
mask = s[readfn](s.section, 'netmask'),
|
||||
firstsubnet = mask ? addrs[0] + '/' + mask : addrs.filter(function(a) { return a.indexOf('/') > 0 })[0];
|
||||
const readfn = use_cfgvalue ? 'cfgvalue' : 'formvalue';
|
||||
const addrs = L.toArray(s[readfn](s.section, 'ipaddr'));
|
||||
const mask = s[readfn](s.section, 'netmask');
|
||||
const firstsubnet = mask ? addrs[0] + '/' + mask : addrs.filter(function(a) { return a.indexOf('/') > 0 })[0];
|
||||
|
||||
if (firstsubnet == null)
|
||||
return null;
|
||||
|
||||
var subnetmask = firstsubnet.split('/')[1];
|
||||
let subnetmask = firstsubnet.split('/')[1];
|
||||
|
||||
if (!isNaN(subnetmask))
|
||||
subnetmask = network.prefixToMask(+subnetmask);
|
||||
@@ -263,25 +263,24 @@ function has_sourcefilter(proto) {
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
poll_status: function(map, networks) {
|
||||
var resolveZone = null;
|
||||
poll_status(map, networks) {
|
||||
let resolveZone = null;
|
||||
|
||||
for (var i = 0; i < networks.length; i++) {
|
||||
var ifc = networks[i],
|
||||
row = map.querySelector('.cbi-section-table-row[data-sid="%s"]'.format(ifc.getName()));
|
||||
for (let ifc of networks) {
|
||||
const row = map.querySelector('.cbi-section-table-row[data-sid="%s"]'.format(ifc.getName()));
|
||||
|
||||
if (row == null)
|
||||
continue;
|
||||
|
||||
var dsc = row.querySelector('[data-name="_ifacestat"] > div'),
|
||||
box = row.querySelector('[data-name="_ifacebox"] .ifacebox-body'),
|
||||
btn1 = row.querySelector('.cbi-section-actions .reconnect'),
|
||||
btn2 = row.querySelector('.cbi-section-actions .down'),
|
||||
stat = document.querySelector('[id="%s-ifc-status"]'.format(ifc.getName())),
|
||||
resolveZone = render_ifacebox_status(box, ifc),
|
||||
disabled = ifc ? !ifc.isUp() : true,
|
||||
dynamic = ifc ? ifc.isDynamic() : false,
|
||||
pending = ifc ? ifc.isPending() : false;
|
||||
const dsc = row.querySelector('[data-name="_ifacestat"] > div');
|
||||
const box = row.querySelector('[data-name="_ifacebox"] .ifacebox-body');
|
||||
const btn1 = row.querySelector('.cbi-section-actions .reconnect');
|
||||
const btn2 = row.querySelector('.cbi-section-actions .down');
|
||||
const stat = document.querySelector('[id="%s-ifc-status"]'.format(ifc.getName()));
|
||||
resolveZone = render_ifacebox_status(box, ifc);
|
||||
const disabled = ifc ? !ifc.isUp() : true;
|
||||
const dynamic = ifc ? ifc.isDynamic() : false;
|
||||
const pending = ifc ? ifc.isPending() : false;
|
||||
|
||||
if (dsc.hasAttribute('reconnect')) {
|
||||
dom.content(dsc, E('em', _('Interface is starting...')));
|
||||
@@ -293,10 +292,10 @@ return view.extend({
|
||||
render_status(dsc, ifc, false);
|
||||
}
|
||||
else if (!ifc.getProtocol()) {
|
||||
var e = map.querySelector('[id="cbi-network-%s"] .cbi-button-edit'.format(ifc.getName()));
|
||||
const e = map.querySelector('[id="cbi-network-%s"] .cbi-button-edit'.format(ifc.getName()));
|
||||
if (e) e.disabled = true;
|
||||
|
||||
var link = L.url('admin/system/package-manager') + '?query=luci-proto';
|
||||
const link = L.url('admin/system/package-manager') + '?query=luci-proto';
|
||||
dom.content(dsc, [
|
||||
E('em', _('Unsupported protocol type.')), E('br'),
|
||||
E('a', { href: link }, _('Install protocol extensions...'))
|
||||
@@ -354,7 +353,7 @@ return view.extend({
|
||||
return Promise.all([ resolveZone, network.flushCache() ]);
|
||||
},
|
||||
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
network.getDSLModemType(),
|
||||
network.getDevices(),
|
||||
@@ -363,29 +362,29 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
interfaceBridgeWithIfnameSections: function() {
|
||||
interfaceBridgeWithIfnameSections() {
|
||||
return uci.sections('network', 'interface').filter(function(ns) {
|
||||
return ns.type == 'bridge' && !ns.ports && ns.ifname;
|
||||
});
|
||||
},
|
||||
|
||||
deviceWithIfnameSections: function() {
|
||||
deviceWithIfnameSections() {
|
||||
return uci.sections('network', 'device').filter(function(ns) {
|
||||
return ns.type == 'bridge' && !ns.ports && ns.ifname;
|
||||
});
|
||||
},
|
||||
|
||||
interfaceWithIfnameSections: function() {
|
||||
interfaceWithIfnameSections() {
|
||||
return uci.sections('network', 'interface').filter(function(ns) {
|
||||
return !ns.device && ns.ifname;
|
||||
});
|
||||
},
|
||||
|
||||
handleBridgeMigration: function(ev) {
|
||||
var tasks = [];
|
||||
handleBridgeMigration(ev) {
|
||||
const tasks = [];
|
||||
|
||||
this.interfaceBridgeWithIfnameSections().forEach(function(ns) {
|
||||
var device_name = 'br-' + ns['.name'];
|
||||
const device_name = 'br-' + ns['.name'];
|
||||
|
||||
tasks.push(uci.callAdd('network', 'device', null, {
|
||||
'name': device_name,
|
||||
@@ -411,7 +410,7 @@ return view.extend({
|
||||
.then(L.bind(ui.changes.apply, ui.changes));
|
||||
},
|
||||
|
||||
renderBridgeMigration: function() {
|
||||
renderBridgeMigration() {
|
||||
ui.showModal(_('Network bridge configuration migration'), [
|
||||
E('p', _('The existing network configuration needs to be changed for LuCI to function properly.')),
|
||||
E('p', _('Upon pressing "Continue", bridges configuration will be updated and the network will be restarted to apply the updated configuration.')),
|
||||
@@ -423,8 +422,8 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
handleIfnameMigration: function(ev) {
|
||||
var tasks = [];
|
||||
handleIfnameMigration(ev) {
|
||||
const tasks = [];
|
||||
|
||||
this.deviceWithIfnameSections().forEach(function(ds) {
|
||||
tasks.push(uci.callSet('network', ds['.name'], {
|
||||
@@ -445,7 +444,7 @@ return view.extend({
|
||||
.then(L.bind(ui.changes.apply, ui.changes));
|
||||
},
|
||||
|
||||
renderIfnameMigration: function() {
|
||||
renderIfnameMigration() {
|
||||
ui.showModal(_('Network ifname configuration migration'), [
|
||||
E('p', _('The existing network configuration needs to be changed for LuCI to function properly.')),
|
||||
E('p', _('Upon pressing "Continue", ifname options will get renamed and the network will be restarted to apply the updated configuration.')),
|
||||
@@ -457,19 +456,17 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
render([dslModemType, netDevs, rtTables]) {
|
||||
|
||||
if (this.interfaceBridgeWithIfnameSections().length)
|
||||
return this.renderBridgeMigration();
|
||||
else if (this.deviceWithIfnameSections().length || this.interfaceWithIfnameSections().length)
|
||||
return this.renderIfnameMigration();
|
||||
|
||||
var dslModemType = data[0],
|
||||
netDevs = data[1],
|
||||
m, s, o;
|
||||
let m, s, o;
|
||||
|
||||
var rtTables = data[2].map(function(l) {
|
||||
var m = l.trim().match(/^(\d+)\s+(\S+)$/);
|
||||
rtTables = rtTables.map(function(l) {
|
||||
const m = l.trim().match(/^(\d+)\s+(\S+)$/);
|
||||
return m ? [ +m[1], m[2] ] : null;
|
||||
}).filter(function(e) {
|
||||
return e && e[0] > 0;
|
||||
@@ -570,11 +567,11 @@ return view.extend({
|
||||
};
|
||||
|
||||
s.addModalOptions = function(s) {
|
||||
var protoval = uci.get('network', s.section, 'proto') || 'none',
|
||||
o, proto_select, proto_switch, type, stp, igmp, ss, so;
|
||||
const protoval = uci.get('network', s.section, 'proto') || 'none';
|
||||
let o, proto_select, proto_switch, ss, so;
|
||||
|
||||
return network.getNetwork(s.section).then(L.bind(function(ifc) {
|
||||
var protocols = network.getProtocols();
|
||||
const protocols = network.getProtocols();
|
||||
|
||||
protocols.sort(function(a, b) {
|
||||
return L.naturalCompare(a.getProtocol(), b.getProtocol());
|
||||
@@ -583,7 +580,7 @@ return view.extend({
|
||||
o = s.taboption('general', form.DummyValue, '_ifacestat_modal', _('Status'));
|
||||
o.modalonly = true;
|
||||
o.cfgvalue = L.bind(function(section_id) {
|
||||
var net = this.networks.filter(function(n) { return n.getName() == section_id })[0];
|
||||
const net = this.networks.filter(function(n) { return n.getName() == section_id })[0];
|
||||
|
||||
return render_modal_status(E('div', {
|
||||
'id': '%s-ifc-status'.format(section_id),
|
||||
@@ -638,10 +635,7 @@ return view.extend({
|
||||
return Promise.all([
|
||||
firewall.getZoneByNetwork(ifc.getName()),
|
||||
(value != null) ? firewall.getZone(value) : null
|
||||
]).then(function(data) {
|
||||
var old_zone = data[0],
|
||||
new_zone = data[1];
|
||||
|
||||
]).then(function([old_zone, new_zone]) {
|
||||
if (old_zone == null && new_zone == null && (value == null || value == ''))
|
||||
return;
|
||||
|
||||
@@ -661,11 +655,11 @@ return view.extend({
|
||||
};
|
||||
}
|
||||
|
||||
for (var i = 0; i < protocols.length; i++) {
|
||||
proto_select.value(protocols[i].getProtocol(), protocols[i].getI18n());
|
||||
for (let p of protocols) {
|
||||
proto_select.value(p.getProtocol(), p.getI18n());
|
||||
|
||||
if (protocols[i].getProtocol() != protoval)
|
||||
proto_switch.depends('proto', protocols[i].getProtocol());
|
||||
if (p.getProtocol() != protoval)
|
||||
proto_switch.depends('proto', p.getProtocol());
|
||||
}
|
||||
|
||||
if (L.hasSystemFeature('dnsmasq') || L.hasSystemFeature('odhcpd')) {
|
||||
@@ -787,7 +781,7 @@ return view.extend({
|
||||
return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]);
|
||||
};
|
||||
so.validate = function(section_id, value) {
|
||||
var uielem = this.getUIElement(section_id);
|
||||
const uielem = this.getUIElement(section_id);
|
||||
if (uielem)
|
||||
uielem.setPlaceholder(get_netmask(s, false));
|
||||
return form.Value.prototype.validate.apply(this, [ section_id, value ]);
|
||||
@@ -796,7 +790,7 @@ return view.extend({
|
||||
}
|
||||
|
||||
|
||||
var has_other_master = uci.sections('dhcp', 'dhcp').filter(function(s) {
|
||||
const has_other_master = uci.sections('dhcp', 'dhcp').filter(function(s) {
|
||||
return (s.interface != ifc.getName() && s.master == '1');
|
||||
})[0];
|
||||
|
||||
@@ -808,14 +802,14 @@ return view.extend({
|
||||
;
|
||||
|
||||
so.validate = function(section_id, value) {
|
||||
var hybrid_downstream_desc = _('Operate in <em>relay mode</em> if a designated master interface is configured and active, otherwise fall back to <em>server mode</em>.'),
|
||||
ndp_downstream_desc = _('Operate in <em>relay mode</em> if a designated master interface is configured and active, otherwise disable <abbr title="Neighbour Discovery Protocol">NDP</abbr> proxying.'),
|
||||
hybrid_master_desc = _('Operate in <em>relay mode</em> if an upstream IPv6 prefix is present, otherwise disable service.'),
|
||||
ra_server_allowed = true,
|
||||
checked = this.formvalue(section_id),
|
||||
dhcpv6 = this.section.getOption('dhcpv6').getUIElement(section_id),
|
||||
ndp = this.section.getOption('ndp').getUIElement(section_id),
|
||||
ra = this.section.getOption('ra').getUIElement(section_id);
|
||||
const hybrid_downstream_desc = _('Operate in <em>relay mode</em> if a designated master interface is configured and active, otherwise fall back to <em>server mode</em>.');
|
||||
const ndp_downstream_desc = _('Operate in <em>relay mode</em> if a designated master interface is configured and active, otherwise disable <abbr title="Neighbour Discovery Protocol">NDP</abbr> proxying.');
|
||||
const hybrid_master_desc = _('Operate in <em>relay mode</em> if an upstream IPv6 prefix is present, otherwise disable service.');
|
||||
let ra_server_allowed = true;
|
||||
const checked = this.formvalue(section_id);
|
||||
const dhcpv6 = this.section.getOption('dhcpv6').getUIElement(section_id);
|
||||
const ndp = this.section.getOption('ndp').getUIElement(section_id);
|
||||
const ra = this.section.getOption('ra').getUIElement(section_id);
|
||||
|
||||
/* Assume that serving RAs by default is fine, but disallow it for certain
|
||||
interface protocols such as DHCP, DHCPv6 or the various PPP flavors.
|
||||
@@ -923,11 +917,11 @@ return view.extend({
|
||||
so.depends('ra', 'server');
|
||||
so.depends({ ra: 'hybrid', master: '0' });
|
||||
so.cfgvalue = function(section_id) {
|
||||
var flags = L.toArray(uci.get('dhcp', section_id, 'ra_flags'));
|
||||
const flags = L.toArray(uci.get('dhcp', section_id, 'ra_flags'));
|
||||
return flags.length ? flags : [ 'other-config' ];
|
||||
};
|
||||
so.remove = function(section_id) {
|
||||
var existing = L.toArray(uci.get('dhcp', section_id, 'ra_flags'));
|
||||
const existing = L.toArray(uci.get('dhcp', section_id, 'ra_flags'));
|
||||
if (this.isActive(section_id)) {
|
||||
if (existing.length != 1 || existing[0] != 'none')
|
||||
uci.set('dhcp', section_id, 'ra_flags', [ 'none' ]);
|
||||
@@ -1034,8 +1028,8 @@ return view.extend({
|
||||
so.depends('ra', 'server');
|
||||
so.depends({ ra: 'hybrid', master: '0' });
|
||||
so.load = function(section_id) {
|
||||
var dev = ifc.getL3Device(),
|
||||
path = dev ? "/proc/sys/net/ipv6/conf/%s/mtu".format(dev.getName()) : null;
|
||||
const dev = ifc.getL3Device();
|
||||
const path = dev ? "/proc/sys/net/ipv6/conf/%s/mtu".format(dev.getName()) : null;
|
||||
|
||||
return Promise.all([
|
||||
dev ? L.resolveDefault(fs.read(path), dev.getMTU()) : null,
|
||||
@@ -1053,8 +1047,8 @@ return view.extend({
|
||||
so.depends('ra', 'server');
|
||||
so.depends({ ra: 'hybrid', master: '0' });
|
||||
so.load = function(section_id) {
|
||||
var dev = ifc.getL3Device(),
|
||||
path = dev ? "/proc/sys/net/ipv6/conf/%s/hop_limit".format(dev.getName()) : null;
|
||||
const dev = ifc.getL3Device();
|
||||
const path = dev ? "/proc/sys/net/ipv6/conf/%s/hop_limit".format(dev.getName()) : null;
|
||||
|
||||
return Promise.all([
|
||||
dev ? L.resolveDefault(fs.read(path), 64) : null,
|
||||
@@ -1155,14 +1149,14 @@ return view.extend({
|
||||
so = ss.taboption('dhcpv6', form.DynamicList, 'ntp', _('NTP Servers'),
|
||||
_('DHCPv6 option 56. %s.', 'DHCPv6 option 56. RFC5908 link').format('<a href="%s" target="_blank">RFC5908</a>').format('https://www.rfc-editor.org/rfc/rfc5908#section-4'));
|
||||
so.datatype = 'host(0)';
|
||||
for(var x of uci.get('system', 'ntp', 'server') || '') {
|
||||
for(let x of uci.get('system', 'ntp', 'server') || '') {
|
||||
so.value(x);
|
||||
}
|
||||
var local_nets = this.networks.filter(function(n) { return n.getName() != 'loopback' });
|
||||
const local_nets = this.networks.filter(function(n) { return n.getName() != 'loopback' });
|
||||
if(local_nets) {
|
||||
// If ntpd is set up, suggest our IP(v6) also
|
||||
if(uci.get('system', 'ntp', 'enable_server')) {
|
||||
local_nets.forEach(function(n){
|
||||
local_nets.forEach(function(n) {
|
||||
n.getIPAddrs().forEach(function(i4) {
|
||||
so.value(i4.split('/')[0]);
|
||||
});
|
||||
@@ -1224,13 +1218,13 @@ return view.extend({
|
||||
|
||||
o = nettools.replaceOption(s, 'advanced', form.Value, 'ip4table', _('Override IPv4 routing table'));
|
||||
o.datatype = 'or(uinteger, string)';
|
||||
for (var i = 0; i < rtTables.length; i++)
|
||||
o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][1], rtTables[i][0]));
|
||||
for (let rt of rtTables)
|
||||
o.value(rt[1], '%s (%d)'.format(rt[1], rt[0]));
|
||||
|
||||
o = nettools.replaceOption(s, 'advanced', form.Value, 'ip6table', _('Override IPv6 routing table'));
|
||||
o.datatype = 'or(uinteger, string)';
|
||||
for (var i = 0; i < rtTables.length; i++)
|
||||
o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][1], rtTables[i][0]));
|
||||
for (let rt of rtTables)
|
||||
o.value(rt[1], '%s (%d)'.format(rt[1], rt[0]));
|
||||
|
||||
if (has_sourcefilter(protoval)) {
|
||||
o = nettools.replaceOption(s, 'advanced', form.Flag, 'sourcefilter', _('IPv6 source routing'), _('Automatically handle multiple uplink interfaces using source-based policy routing.'));
|
||||
@@ -1251,24 +1245,24 @@ return view.extend({
|
||||
if (value == null || value == '')
|
||||
return true;
|
||||
|
||||
var n = parseInt(value, 16);
|
||||
const n = parseInt(value, 16);
|
||||
|
||||
if (!/^(0x)?[0-9a-fA-F]+$/.test(value) || isNaN(n) || n >= 0xffffffff)
|
||||
return _('Expecting a hexadecimal assignment hint');
|
||||
|
||||
return true;
|
||||
};
|
||||
for (var i = 33; i <= 64; i++)
|
||||
for (let i = 33; i <= 64; i++)
|
||||
o.depends('ip6assign', String(i));
|
||||
|
||||
|
||||
o = nettools.replaceOption(s, 'advanced', form.DynamicList, 'ip6class', _('IPv6 prefix filter'), _('If set, downstream subnets are only allocated from the given IPv6 prefix classes.'));
|
||||
o.value('local', 'local (%s)'.format(_('Local ULA')));
|
||||
|
||||
var prefixClasses = {};
|
||||
const prefixClasses = {};
|
||||
|
||||
this.networks.forEach(function(net) {
|
||||
var prefixes = net._ubus('ipv6-prefix');
|
||||
const prefixes = net._ubus('ipv6-prefix');
|
||||
if (Array.isArray(prefixes)) {
|
||||
prefixes.forEach(function(pfx) {
|
||||
if (L.isObject(pfx) && typeof(pfx['class']) == 'string') {
|
||||
@@ -1280,7 +1274,7 @@ return view.extend({
|
||||
});
|
||||
|
||||
Object.keys(prefixClasses).sort().forEach(function(c) {
|
||||
var networks = Object.keys(prefixClasses[c]).sort().join(', ');
|
||||
const networks = Object.keys(prefixClasses[c]).sort().join(', ');
|
||||
o.value(c, (c != networks) ? '%s (%s)'.format(c, networks) : c);
|
||||
});
|
||||
|
||||
@@ -1293,9 +1287,8 @@ return view.extend({
|
||||
o.datatype = 'uinteger';
|
||||
o.placeholder = '0';
|
||||
|
||||
for (var i = 0; i < s.children.length; i++) {
|
||||
o = s.children[i];
|
||||
|
||||
for (let o of s.children) {
|
||||
const deps = [];
|
||||
switch (o.option) {
|
||||
case 'proto':
|
||||
case 'auto':
|
||||
@@ -1309,14 +1302,13 @@ return view.extend({
|
||||
case 'stp':
|
||||
case 'type':
|
||||
case '_net_device':
|
||||
var deps = [];
|
||||
for (var j = 0; j < protocols.length; j++) {
|
||||
if (!protocols[j].isVirtual()) {
|
||||
for (let p of protocols) {
|
||||
if (!p.isVirtual()) {
|
||||
if (o.deps.length)
|
||||
for (var k = 0; k < o.deps.length; k++)
|
||||
deps.push(Object.assign({ proto: protocols[j].getProtocol() }, o.deps[k]));
|
||||
for (let od of o.deps)
|
||||
deps.push(Object.assign({ proto: p.getProtocol() }, od));
|
||||
else
|
||||
deps.push({ proto: protocols[j].getProtocol() });
|
||||
deps.push({ proto: p.getProtocol() });
|
||||
}
|
||||
}
|
||||
o.deps = deps;
|
||||
@@ -1324,8 +1316,8 @@ return view.extend({
|
||||
|
||||
default:
|
||||
if (o.deps.length)
|
||||
for (var j = 0; j < o.deps.length; j++)
|
||||
o.deps[j].proto = protoval;
|
||||
for (let od of o.deps)
|
||||
od.proto = protoval;
|
||||
else
|
||||
o.depends('proto', protoval);
|
||||
}
|
||||
@@ -1336,8 +1328,8 @@ return view.extend({
|
||||
};
|
||||
|
||||
s.handleModalCancel = function(/* ... */) {
|
||||
var type = uci.get('network', this.activeSection || this.addedSection, 'type'),
|
||||
device = (type == 'bridge') ? 'br-%s'.format(this.activeSection || this.addedSection) : null;
|
||||
const type = uci.get('network', this.activeSection || this.addedSection, 'type');
|
||||
const device = (type == 'bridge') ? 'br-%s'.format(this.activeSection || this.addedSection) : null;
|
||||
|
||||
uci.sections('network', 'bridge-vlan', function(bvs) {
|
||||
if (device != null && bvs.device == device)
|
||||
@@ -1348,10 +1340,10 @@ return view.extend({
|
||||
};
|
||||
|
||||
s.handleAdd = function(ev) {
|
||||
var m2 = new form.Map('network'),
|
||||
s2 = m2.section(form.NamedSection, '_new_'),
|
||||
protocols = network.getProtocols(),
|
||||
proto, name, device;
|
||||
const m2 = new form.Map('network');
|
||||
const s2 = m2.section(form.NamedSection, '_new_');
|
||||
const protocols = network.getProtocols();
|
||||
let proto, name, device;
|
||||
|
||||
protocols.sort(function(a, b) {
|
||||
return L.naturalCompare(a.getProtocol(), b.getProtocol());
|
||||
@@ -1372,10 +1364,10 @@ return view.extend({
|
||||
if (uci.get('network', value) != null)
|
||||
return _('The interface name is already used');
|
||||
|
||||
var pr = network.getProtocol(proto.formvalue(section_id), value),
|
||||
ifname = pr.isVirtual() ? '%s-%s'.format(pr.getProtocol(), value) : 'br-%s'.format(value);
|
||||
const pr = network.getProtocol(proto.formvalue(section_id), value);
|
||||
const ifname = pr.isVirtual() ? '%s-%s'.format(pr.getProtocol(), value) : 'br-%s'.format(value);
|
||||
|
||||
if (value.length > 15)
|
||||
if (ifname.length > 15)
|
||||
return _('The interface name is too long');
|
||||
|
||||
return true;
|
||||
@@ -1383,7 +1375,7 @@ return view.extend({
|
||||
|
||||
proto = s2.option(form.ListValue, 'proto', _('Protocol'));
|
||||
proto.onchange = function(ev, section_id, value) {
|
||||
var elem = name.getUIElement(section_id);
|
||||
const elem = name.getUIElement(section_id);
|
||||
elem.triggerValidation();
|
||||
};
|
||||
|
||||
@@ -1391,11 +1383,11 @@ return view.extend({
|
||||
device.noaliases = false;
|
||||
device.optional = false;
|
||||
|
||||
for (var i = 0; i < protocols.length; i++) {
|
||||
proto.value(protocols[i].getProtocol(), protocols[i].getI18n());
|
||||
for (let p of protocols) {
|
||||
proto.value(p.getProtocol(), p.getI18n());
|
||||
|
||||
if (!protocols[i].isVirtual())
|
||||
device.depends('proto', protocols[i].getProtocol());
|
||||
if (!p.isVirtual())
|
||||
device.depends('proto', p.getProtocol());
|
||||
}
|
||||
|
||||
m2.render().then(L.bind(function(nodes) {
|
||||
@@ -1409,9 +1401,9 @@ return view.extend({
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-positive important',
|
||||
'click': ui.createHandlerFn(this, function(ev) {
|
||||
var nameval = name.isValid('_new_') ? name.formvalue('_new_') : null,
|
||||
protoval = proto.isValid('_new_') ? proto.formvalue('_new_') : null,
|
||||
protoclass = protoval ? network.getProtocol(protoval, nameval) : null;
|
||||
const nameval = name.isValid('_new_') ? name.formvalue('_new_') : null;
|
||||
const protoval = proto.isValid('_new_') ? proto.formvalue('_new_') : null;
|
||||
const protoclass = protoval ? network.getProtocol(protoval, nameval) : null;
|
||||
|
||||
if (nameval == null || protoval == null || nameval == '' || protoval == '')
|
||||
return;
|
||||
@@ -1425,7 +1417,7 @@ return view.extend({
|
||||
}
|
||||
|
||||
return m.save(function() {
|
||||
var section_id = uci.add('network', 'interface', nameval);
|
||||
const section_id = uci.add('network', 'interface', nameval);
|
||||
|
||||
protoclass.set('proto', protoval);
|
||||
protoclass.addDevice(device.formvalue('_new_'));
|
||||
@@ -1454,13 +1446,13 @@ return view.extend({
|
||||
o = s.option(form.DummyValue, '_ifacebox');
|
||||
o.modalonly = false;
|
||||
o.textvalue = function(section_id) {
|
||||
var net = this.section.networks.filter(function(n) { return n.getName() == section_id })[0],
|
||||
zone = net ? this.section.zones.filter(function(z) { return !!z.getNetworks().filter(function(n) { return n == section_id })[0] })[0] : null;
|
||||
const net = this.section.networks.filter(function(n) { return n.getName() == section_id })[0];
|
||||
const zone = net ? this.section.zones.filter(function(z) { return !!z.getNetworks().filter(function(n) { return n == section_id })[0] })[0] : null;
|
||||
|
||||
if (!net)
|
||||
return;
|
||||
|
||||
var node = E('div', { 'class': 'ifacebox' }, [
|
||||
const node = E('div', { 'class': 'ifacebox' }, [
|
||||
E('div', {
|
||||
'class': 'ifacebox-head',
|
||||
'style': firewall.getZoneColorStyle(zone),
|
||||
@@ -1487,12 +1479,12 @@ return view.extend({
|
||||
o = s.option(form.DummyValue, '_ifacestat');
|
||||
o.modalonly = false;
|
||||
o.textvalue = function(section_id) {
|
||||
var net = this.section.networks.filter(function(n) { return n.getName() == section_id })[0];
|
||||
const net = this.section.networks.filter(function(n) { return n.getName() == section_id })[0];
|
||||
|
||||
if (!net)
|
||||
return;
|
||||
|
||||
var node = E('div', { 'id': '%s-ifc-description'.format(section_id) });
|
||||
const node = E('div', { 'id': '%s-ifc-description'.format(section_id) });
|
||||
|
||||
render_status(node, net, false);
|
||||
|
||||
@@ -1518,36 +1510,36 @@ return view.extend({
|
||||
s.addbtntitle = _('Add device configuration…');
|
||||
|
||||
s.cfgsections = function() {
|
||||
var sections = uci.sections('network', 'device'),
|
||||
section_ids = sections.sort(function(a, b) { return L.naturalCompare(a.name, b.name) }).map(function(s) { return s['.name'] });
|
||||
const sections = uci.sections('network', 'device');
|
||||
const section_ids = sections.sort(function(a, b) { return L.naturalCompare(a.name, b.name) }).map(function(s) { return s['.name'] });
|
||||
|
||||
for (var i = 0; i < netDevs.length; i++) {
|
||||
if (sections.filter(function(s) { return s.name == netDevs[i].getName() }).length)
|
||||
for (let nd of netDevs) {
|
||||
if (sections.filter(function(s) { return s.name == nd.getName() }).length)
|
||||
continue;
|
||||
|
||||
if (netDevs[i].getType() == 'wifi' && !netDevs[i].isUp())
|
||||
if (nd.getType() == 'wifi' && !nd.isUp())
|
||||
continue;
|
||||
|
||||
/* Unless http://lists.openwrt.org/pipermail/openwrt-devel/2020-July/030397.html is implemented,
|
||||
we cannot properly redefine bridges as devices, so filter them away for now... */
|
||||
|
||||
var m = netDevs[i].isBridge() ? netDevs[i].getName().match(/^br-([A-Za-z0-9_]+)$/) : null,
|
||||
s = m ? uci.get('network', m[1]) : null;
|
||||
const m = nd.isBridge() ? nd.getName().match(/^br-([A-Za-z0-9_]+)$/) : null;
|
||||
const s = m ? uci.get('network', m[1]) : null;
|
||||
|
||||
if (s && s['.type'] == 'interface' && s.type == 'bridge')
|
||||
continue;
|
||||
|
||||
section_ids.push('dev:%s'.format(netDevs[i].getName()));
|
||||
section_ids.push('dev:%s'.format(nd.getName()));
|
||||
}
|
||||
|
||||
return section_ids;
|
||||
};
|
||||
|
||||
s.renderMoreOptionsModal = function(section_id, ev) {
|
||||
var m = section_id.match(/^dev:(.+)$/);
|
||||
const m = section_id.match(/^dev:(.+)$/);
|
||||
|
||||
if (m) {
|
||||
var devtype = getDevType(section_id);
|
||||
const devtype = getDevType(section_id);
|
||||
|
||||
section_id = uci.add('network', 'device');
|
||||
|
||||
@@ -1561,8 +1553,8 @@ return view.extend({
|
||||
};
|
||||
|
||||
s.renderRowActions = function(section_id) {
|
||||
var trEl = this.super('renderRowActions', [ section_id, _('Configure…') ]),
|
||||
deleteBtn = trEl.querySelector('button:last-child');
|
||||
const trEl = this.super('renderRowActions', [ section_id, _('Configure…') ]);
|
||||
const deleteBtn = trEl.querySelector('button:last-child');
|
||||
|
||||
deleteBtn.firstChild.data = _('Unconfigure');
|
||||
deleteBtn.setAttribute('title', _('Remove related device settings from the configuration'));
|
||||
@@ -1572,16 +1564,16 @@ return view.extend({
|
||||
};
|
||||
|
||||
s.modaltitle = function(section_id) {
|
||||
var m = section_id.match(/^dev:(.+)$/),
|
||||
name = m ? m[1] : uci.get('network', section_id, 'name');
|
||||
const m = section_id.match(/^dev:(.+)$/);
|
||||
const name = m ? m[1] : uci.get('network', section_id, 'name');
|
||||
|
||||
return name ? '%s: %q'.format(getDevTypeDesc(section_id), name) : _('Add device configuration');
|
||||
};
|
||||
|
||||
s.addModalOptions = function(s) {
|
||||
const isNew = (uci.get('network', s.section, 'name') == null),
|
||||
dev = getDevice(s.section),
|
||||
devName = dev ? dev.getName() : null;
|
||||
const isNew = (uci.get('network', s.section, 'name') == null);
|
||||
const dev = getDevice(s.section);
|
||||
const devName = dev ? dev.getName() : null;
|
||||
|
||||
/* Query PSE status from netifd to determine if device has PSE capability */
|
||||
if (devName) {
|
||||
@@ -1596,7 +1588,7 @@ return view.extend({
|
||||
};
|
||||
|
||||
s.handleModalCancel = function(map /*, ... */) {
|
||||
var name = uci.get('network', this.addedSection, 'name')
|
||||
const name = uci.get('network', this.addedSection, 'name');
|
||||
|
||||
uci.sections('network', 'bridge-vlan', function(bvs) {
|
||||
if (name != null && bvs.device == name)
|
||||
@@ -1604,8 +1596,8 @@ return view.extend({
|
||||
});
|
||||
|
||||
if (map.addedVLANs)
|
||||
for (var i = 0; i < map.addedVLANs.length; i++)
|
||||
uci.remove('network', map.addedVLANs[i]);
|
||||
for (let mav of map.addedVLANs)
|
||||
uci.remove('network', mav);
|
||||
|
||||
if (this.addedSection)
|
||||
uci.remove('network', this.addedSection);
|
||||
@@ -1614,8 +1606,8 @@ return view.extend({
|
||||
};
|
||||
|
||||
s.handleRemove = function(section_id /*, ... */) {
|
||||
var name = uci.get('network', section_id, 'name'),
|
||||
type = uci.get('network', section_id, 'type');
|
||||
const name = uci.get('network', section_id, 'name');
|
||||
const type = uci.get('network', section_id, 'type');
|
||||
|
||||
if (name != null && type == 'bridge') {
|
||||
uci.sections('network', 'bridge-vlan', function(bvs) {
|
||||
@@ -1628,16 +1620,16 @@ return view.extend({
|
||||
};
|
||||
|
||||
function getDevice(section_id) {
|
||||
var m = section_id.match(/^dev:(.+)$/),
|
||||
name = m ? m[1] : uci.get('network', section_id, 'name');
|
||||
const m = section_id.match(/^dev:(.+)$/);
|
||||
const name = m ? m[1] : uci.get('network', section_id, 'name');
|
||||
|
||||
return netDevs.filter(function(d) { return d.getName() == name })[0];
|
||||
}
|
||||
|
||||
function getDevType(section_id) {
|
||||
var dev = getDevice(section_id),
|
||||
cfg = uci.get('network', section_id),
|
||||
type = cfg ? (uci.get('network', section_id, 'type') || 'ethernet') : (dev ? dev.getType() : '');
|
||||
const dev = getDevice(section_id);
|
||||
const cfg = uci.get('network', section_id);
|
||||
const type = cfg ? (uci.get('network', section_id, 'type') || 'ethernet') : (dev ? dev.getType() : '');
|
||||
|
||||
switch (type) {
|
||||
case '':
|
||||
@@ -1714,9 +1706,9 @@ return view.extend({
|
||||
o = s.option(form.DummyValue, 'name', _('Device'));
|
||||
o.modalonly = false;
|
||||
o.textvalue = function(section_id) {
|
||||
var dev = getDevice(section_id),
|
||||
ext = section_id.match(/^dev:/),
|
||||
icon = render_iface(dev);
|
||||
const dev = getDevice(section_id);
|
||||
const ext = section_id.match(/^dev:/);
|
||||
const icon = render_iface(dev);
|
||||
|
||||
if (ext)
|
||||
icon.querySelector('img').style.opacity = '.5';
|
||||
@@ -1736,9 +1728,9 @@ return view.extend({
|
||||
o = s.option(form.DummyValue, 'macaddr', _('MAC Address'));
|
||||
o.modalonly = false;
|
||||
o.textvalue = function(section_id) {
|
||||
var dev = getDevice(section_id),
|
||||
val = uci.get('network', section_id, 'macaddr'),
|
||||
mac = dev ? dev.getMAC() : null;
|
||||
const dev = getDevice(section_id);
|
||||
const val = uci.get('network', section_id, 'macaddr');
|
||||
const mac = dev ? dev.getMAC() : null;
|
||||
|
||||
return val ? E('strong', {
|
||||
'data-tooltip': _('The value is overridden by configuration.')
|
||||
@@ -1748,9 +1740,9 @@ return view.extend({
|
||||
o = s.option(form.DummyValue, 'mtu', _('MTU'));
|
||||
o.modalonly = false;
|
||||
o.textvalue = function(section_id) {
|
||||
var dev = getDevice(section_id),
|
||||
val = uci.get('network', section_id, 'mtu'),
|
||||
mtu = dev ? dev.getMTU() : null;
|
||||
const dev = getDevice(section_id);
|
||||
const val = uci.get('network', section_id, 'mtu');
|
||||
const mtu = dev ? dev.getMTU() : null;
|
||||
|
||||
return val ? E('strong', {
|
||||
'data-tooltip': _('The value is overridden by configuration.')
|
||||
@@ -1790,7 +1782,7 @@ return view.extend({
|
||||
o.default = '1';
|
||||
o.optional = true;
|
||||
|
||||
var steer_flow = uci.get('network', 'globals', 'steering_flows');
|
||||
const steer_flow = uci.get('network', 'globals', 'steering_flows');
|
||||
|
||||
o = s.option(form.Value, 'steering_flows', _('Steering flows (<abbr title="Receive Packet Steering">RPS</abbr>)'),
|
||||
_('Directs packet flows to specific CPUs where the local socket owner listens (the local service).') + ' ' +
|
||||
@@ -1851,7 +1843,7 @@ return view.extend({
|
||||
o = s.option(form.ListValue, 'ds_snr_offset', _('Downstream SNR offset'));
|
||||
o.default = '0';
|
||||
|
||||
for (var i = -100; i <= 100; i += 5)
|
||||
for (let i = -100; i <= 100; i += 5)
|
||||
o.value(i, _('%.1f dB').format(i / 10));
|
||||
}
|
||||
|
||||
@@ -1868,18 +1860,18 @@ return view.extend({
|
||||
s.addbtntitle = _('Add ATM Bridge');
|
||||
|
||||
s.handleAdd = function(ev) {
|
||||
var sections = uci.sections('network', 'atm-bridge'),
|
||||
max_unit = -1;
|
||||
const sections = uci.sections('network', 'atm-bridge');
|
||||
let max_unit = -1;
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
var unit = +sections[i].unit;
|
||||
for (let s of sections) {
|
||||
const unit = +s.unit;
|
||||
|
||||
if (!isNaN(unit) && unit > max_unit)
|
||||
max_unit = unit;
|
||||
}
|
||||
|
||||
return this.map.save(function() {
|
||||
var sid = uci.add('network', 'atm-bridge');
|
||||
const sid = uci.add('network', 'atm-bridge');
|
||||
|
||||
uci.set('network', sid, 'unit', max_unit + 1);
|
||||
uci.set('network', sid, 'atmdev', 0);
|
||||
@@ -1911,24 +1903,24 @@ return view.extend({
|
||||
|
||||
return m.render().then(L.bind(function(m, nodes) {
|
||||
poll.add(L.bind(function() {
|
||||
var section_ids = m.children[0].cfgsections(),
|
||||
tasks = [];
|
||||
const section_ids = m.children[0].cfgsections();
|
||||
const tasks = [];
|
||||
|
||||
for (var i = 0; i < section_ids.length; i++) {
|
||||
var row = nodes.querySelector('.cbi-section-table-row[data-sid="%s"]'.format(section_ids[i])),
|
||||
dsc = row.querySelector('[data-name="_ifacestat"] > div'),
|
||||
btn1 = row.querySelector('.cbi-section-actions .reconnect'),
|
||||
btn2 = row.querySelector('.cbi-section-actions .down');
|
||||
for (let sid of section_ids) {
|
||||
const row = nodes.querySelector('.cbi-section-table-row[data-sid="%s"]'.format(sid));
|
||||
const dsc = row.querySelector('[data-name="_ifacestat"] > div');
|
||||
const btn1 = row.querySelector('.cbi-section-actions .reconnect');
|
||||
const btn2 = row.querySelector('.cbi-section-actions .down');
|
||||
|
||||
if (dsc.getAttribute('reconnect') == '') {
|
||||
dsc.setAttribute('reconnect', '1');
|
||||
tasks.push(fs.exec('/sbin/ifup', [section_ids[i]]).catch(function(e) {
|
||||
tasks.push(fs.exec('/sbin/ifup', [sid]).catch(function(e) {
|
||||
ui.addNotification(null, E('p', e.message));
|
||||
}));
|
||||
}
|
||||
else if (dsc.getAttribute('disconnect') == '') {
|
||||
dsc.setAttribute('disconnect', '1');
|
||||
tasks.push(fs.exec('/sbin/ifdown', [section_ids[i]]).catch(function(e) {
|
||||
tasks.push(fs.exec('/sbin/ifdown', [sid]).catch(function(e) {
|
||||
ui.addNotification(null, E('p', e.message));
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -5,22 +5,21 @@
|
||||
'require form';
|
||||
'require network';
|
||||
'require tools.widgets as widgets';
|
||||
'require tools.network as tn';
|
||||
'require tools.network as nettools';
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
network.getDevices(),
|
||||
fs.lines('/etc/iproute2/rt_tables')
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var netDevs = data[0],
|
||||
m, s, o;
|
||||
render([netDevs, rtTables]) {
|
||||
let m, s, o;
|
||||
|
||||
var rtTables = data[1].map(function(l) {
|
||||
var m = l.trim().match(/^(\d+)\s+(\S+)$/);
|
||||
rtTables = rtTables.map(function(l) {
|
||||
const m = l.trim().match(/^(\d+)\s+(\S+)$/);
|
||||
return m ? [ +m[1], m[2] ] : null;
|
||||
}).filter(function(e) {
|
||||
return e && e[0] > 0;
|
||||
@@ -31,7 +30,7 @@ return view.extend({
|
||||
'<br/>' + _('Rules determine which routing table to use, based on conditions like source address or interface.'));
|
||||
m.tabbed = true;
|
||||
|
||||
for (var family = 4; family <= 6; family += 2) {
|
||||
for (let family = 4; family <= 6; family += 2) {
|
||||
s = m.section(form.GridSection, (family == 6) ? 'route6' : 'route', (family == 6) ? _('Static IPv6 Routes') : _('Static IPv4 Routes'));
|
||||
s.anonymous = true;
|
||||
s.addremove = true;
|
||||
@@ -64,11 +63,11 @@ return view.extend({
|
||||
o.datatype = (family == 6) ? 'cidr6' : 'cidr4';
|
||||
o.placeholder = (family == 6) ? '::/0' : '0.0.0.0/0';
|
||||
o.cfgvalue = function(section_id) {
|
||||
var section_type = uci.get('network', section_id, '.type'),
|
||||
target = uci.get('network', section_id, 'target'),
|
||||
mask = uci.get('network', section_id, 'netmask'),
|
||||
v6 = (section_type == 'route6') ? true : false,
|
||||
bits = mask ? network.maskToPrefix(mask, v6) : (v6 ? 128 : 32);
|
||||
const section_type = uci.get('network', section_id, '.type');
|
||||
const target = uci.get('network', section_id, 'target');
|
||||
const mask = uci.get('network', section_id, 'netmask');
|
||||
const v6 = (section_type == 'route6') ? true : false;
|
||||
const bits = mask ? network.maskToPrefix(mask, v6) : (v6 ? 128 : 32);
|
||||
if (target) {
|
||||
return target.split('/')[1] ? target : target + '/' + bits;
|
||||
}
|
||||
@@ -98,8 +97,8 @@ return view.extend({
|
||||
_('A numeric table index, or symbol alias declared in %s. Special aliases local (255), main (254) and default (253) are also valid').format('<code>/etc/iproute2/rt_tables</code>')
|
||||
+ '<br/>' + _('Only interfaces using this table (via override) will use this route.'));
|
||||
o.datatype = 'or(uinteger, string)';
|
||||
for (var i = 0; i < rtTables.length; i++)
|
||||
o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][1], rtTables[i][0]));
|
||||
for (let rt of rtTables)
|
||||
o.value(rt[1], '%s (%d)'.format(rt[1], rt[0]));
|
||||
o.textvalue = function(section_id) {
|
||||
return this.cfgvalue(section_id) || E('em', _('auto'));
|
||||
};
|
||||
@@ -108,10 +107,10 @@ return view.extend({
|
||||
+ '<br/>' + _('This is only used if no default route matches the destination gateway'));
|
||||
o.modalonly = true;
|
||||
o.datatype = (family == 6) ? 'ip6addr' : 'ip4addr';
|
||||
for (var i = 0; i < netDevs.length; i++) {
|
||||
var addrs = (family == 6) ? netDevs[i].getIP6Addrs() : netDevs[i].getIPAddrs();
|
||||
for (var j = 0; j < addrs.length; j++)
|
||||
o.value(addrs[j].split('/')[0]);
|
||||
for (let nd of netDevs) {
|
||||
const addrs = (family == 6) ? nd.getIP6Addrs() : nd.getIPAddrs();
|
||||
for (let a of addrs)
|
||||
o.value(a.split('/')[0]);
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'onlink', _('On-link'), _('When enabled, gateway is on-link even if the gateway does not match any interface prefix'));
|
||||
@@ -124,7 +123,7 @@ return view.extend({
|
||||
o.default = o.disabled;
|
||||
}
|
||||
|
||||
for (var family = 4; family <= 6; family += 2) {
|
||||
for (let family = 4; family <= 6; family += 2) {
|
||||
s = m.section(form.GridSection, (family == 6) ? 'rule6' : 'rule', (family == 6) ? _('IPv6 Rules') : _('IPv4 Rules'));
|
||||
s.anonymous = true;
|
||||
s.addremove = true;
|
||||
@@ -163,7 +162,7 @@ return view.extend({
|
||||
|
||||
o = s.taboption('general', form.Value, 'ipproto', _('IP Protocol'), _('Match traffic IP protocol type'));
|
||||
o.datatype = 'range(0,255)';
|
||||
tn.protocols.forEach(function(p) {
|
||||
nettools.protocols.forEach(function(p) {
|
||||
o.value(p.i, p.d);
|
||||
});
|
||||
|
||||
@@ -182,8 +181,8 @@ return view.extend({
|
||||
_('A numeric table index, or symbol alias declared in %s. Special aliases local (255), main (254) and default (253) are also valid').format('<code>/etc/iproute2/rt_tables</code>')
|
||||
+ '<br/>' + _('Matched traffic re-targets to an interface using this table.'));
|
||||
o.datatype = 'or(uinteger, string)';
|
||||
for (var i = 0; i < rtTables.length; i++)
|
||||
o.value(rtTables[i][1], '%s (%d)'.format(rtTables[i][1], rtTables[i][0]));
|
||||
for (let rt of rtTables)
|
||||
o.value(rt[1], '%s (%d)'.format(rt[1], rt[0]));
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'goto', _('Jump to rule'), _('Jumps to another rule specified by its priority value'));
|
||||
o.modalonly = true;
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
'require network';
|
||||
|
||||
function parse_portvalue(section_id) {
|
||||
var ports = L.toArray(uci.get('network', section_id, 'ports'));
|
||||
const ports = L.toArray(uci.get('network', section_id, 'ports'));
|
||||
|
||||
for (var i = 0; i < ports.length; i++) {
|
||||
var m = ports[i].match(/^(\d+)([tu]?)/);
|
||||
for (let p of ports) {
|
||||
const m = p.match(/^(\d+)([tu]?)/);
|
||||
|
||||
if (m && m[1] == this.option)
|
||||
return m[2] || 'u';
|
||||
@@ -25,13 +25,13 @@ function validate_portvalue(section_id, value) {
|
||||
if (value != 'u')
|
||||
return true;
|
||||
|
||||
var sections = this.section.cfgsections();
|
||||
const sections = this.section.cfgsections();
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == section_id)
|
||||
for (let s of sections) {
|
||||
if (s == section_id)
|
||||
continue;
|
||||
|
||||
if (this.formvalue(sections[i]) == 'u')
|
||||
if (this.formvalue(s) == 'u')
|
||||
return _('%s is untagged in multiple VLANs!').format(this.title);
|
||||
}
|
||||
|
||||
@@ -39,28 +39,28 @@ function validate_portvalue(section_id, value) {
|
||||
}
|
||||
|
||||
function update_interfaces(old_ifname, new_ifname) {
|
||||
var interfaces = uci.sections('network', 'interface');
|
||||
const interfaces = uci.sections('network', 'interface');
|
||||
|
||||
for (var i = 0; i < interfaces.length; i++) {
|
||||
var old_ifnames = L.toArray(interfaces[i].ifname),
|
||||
new_ifnames = [],
|
||||
changed = false;
|
||||
for (let intf of interfaces) {
|
||||
const old_ifnames = L.toArray(intf.ifname);
|
||||
const new_ifnames = [];
|
||||
let changed = false;
|
||||
|
||||
for (var j = 0; j < old_ifnames.length; j++) {
|
||||
if (old_ifnames[j] == old_ifname) {
|
||||
for (let oif of old_ifnames) {
|
||||
if (oif == old_ifname) {
|
||||
new_ifnames.push(new_ifname);
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
new_ifnames.push(old_ifnames[j]);
|
||||
new_ifnames.push(oif);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
uci.set('network', interfaces[i]['.name'], 'ifname', new_ifnames.join(' '));
|
||||
uci.set('network', intf['.name'], 'ifname', new_ifnames.join(' '));
|
||||
|
||||
ui.addNotification(null, E('p', _('Interface %q device auto-migrated from %q to %q.')
|
||||
.replace(/%q/g, '"%s"').format(interfaces[i]['.name'], old_ifname, new_ifname)));
|
||||
.replace(/%q/g, '"%s"').format(intf['.name'], old_ifname, new_ifname)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,27 +88,27 @@ function render_port_status(node, portstate) {
|
||||
}
|
||||
|
||||
function update_port_status(topologies) {
|
||||
var tasks = [];
|
||||
const tasks = [];
|
||||
|
||||
for (var switch_name in topologies)
|
||||
for (let switch_name in topologies)
|
||||
tasks.push(callSwconfigPortState(switch_name).then(L.bind(function(switch_name, ports) {
|
||||
for (var i = 0; i < ports.length; i++) {
|
||||
var node = document.querySelector('[data-switch="%s"][data-port="%d"]'.format(switch_name, ports[i].port));
|
||||
render_port_status(node, ports[i]);
|
||||
for (let p of ports) {
|
||||
const node = document.querySelector('[data-switch="%s"][data-port="%d"]'.format(switch_name, p.port));
|
||||
render_port_status(node, p);
|
||||
}
|
||||
}, topologies[switch_name], switch_name)));
|
||||
|
||||
return Promise.all(tasks);
|
||||
}
|
||||
|
||||
var callSwconfigFeatures = rpc.declare({
|
||||
const callSwconfigFeatures = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getSwconfigFeatures',
|
||||
params: [ 'switch' ],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
var callSwconfigPortState = rpc.declare({
|
||||
const callSwconfigPortState = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getSwconfigPortState',
|
||||
params: [ 'switch' ],
|
||||
@@ -116,11 +116,11 @@ var callSwconfigPortState = rpc.declare({
|
||||
});
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return network.getSwitchTopologies().then(function(topologies) {
|
||||
var tasks = [];
|
||||
const tasks = [];
|
||||
|
||||
for (var switch_name in topologies) {
|
||||
for (let switch_name in topologies) {
|
||||
tasks.push(callSwconfigFeatures(switch_name).then(L.bind(function(features) {
|
||||
this.features = features;
|
||||
}, topologies[switch_name])));
|
||||
@@ -133,18 +133,17 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
render: function(topologies) {
|
||||
var m, s, o;
|
||||
render(topologies) {
|
||||
let m, s, o;
|
||||
|
||||
m = new form.Map('network', _('Switch'), _('The network ports on this device can be combined to several <abbr title=\"Virtual Local Area Network\">VLAN</abbr>s in which computers can communicate directly with each other. <abbr title=\"Virtual Local Area Network\">VLAN</abbr>s are often used to separate different network segments. Often there is by default one Uplink port for a connection to the next greater network like the internet and other ports for a local network.'));
|
||||
m = new form.Map('network', _('Switch'), _("The network ports on this device can be combined to several <abbr title='Virtual Local Area Network'>VLAN</abbr>s in which computers can communicate directly with each other. <abbr title='Virtual Local Area Network'>VLAN</abbr>s are often used to separate different network segments. Often there is by default one Uplink port for a connection to the next greater network like the internet and other ports for a local network."));
|
||||
|
||||
var switchSections = uci.sections('network', 'switch');
|
||||
const switchSections = uci.sections('network', 'switch');
|
||||
|
||||
for (var i = 0; i < switchSections.length; i++) {
|
||||
var switchSection = switchSections[i],
|
||||
sid = switchSection['.name'],
|
||||
switch_name = switchSection.name || sid,
|
||||
topology = topologies[switch_name];
|
||||
for (let switchSection of switchSections) {
|
||||
const sid = switchSection['.name'];
|
||||
const switch_name = switchSection.name || sid;
|
||||
let topology = topologies[switch_name];
|
||||
|
||||
if (!topology) {
|
||||
ui.addNotification(null, _('Switch %q has an unknown topology - the VLAN settings might not be accurate.').replace(/%q/, switch_name));
|
||||
@@ -165,12 +164,11 @@ return view.extend({
|
||||
};
|
||||
}
|
||||
|
||||
var feat = topology.features,
|
||||
min_vid = feat.min_vid || 0,
|
||||
max_vid = feat.max_vid || 16,
|
||||
num_vlans = feat.num_vlans || 16,
|
||||
switch_title = _('Switch %q').replace(/%q/, '"%s"'.format(switch_name)),
|
||||
vlan_title = _('VLANs on %q').replace(/%q/, '"%s"'.format(switch_name));
|
||||
const feat = topology.features;
|
||||
const min_vid = feat.min_vid || 0;
|
||||
const num_vlans = feat.num_vlans || 16;
|
||||
let switch_title = _('Switch %q').replace(/%q/, '"%s"'.format(switch_name));
|
||||
let vlan_title = _('VLANs on %q').replace(/%q/, '"%s"'.format(switch_name));
|
||||
|
||||
if (feat.switch_title) {
|
||||
switch_title += ' (%s)'.format(feat.switch_title);
|
||||
@@ -200,8 +198,8 @@ return view.extend({
|
||||
s.option(form.Flag, 'enable_mirror_rx', _('Enable mirroring of incoming packets'));
|
||||
s.option(form.Flag, 'enable_mirror_tx', _('Enable mirroring of outgoing packets'));
|
||||
|
||||
var sp = s.option(form.ListValue, 'mirror_source_port', _('Mirror source port')),
|
||||
mp = s.option(form.ListValue, 'mirror_monitor_port', _('Mirror monitor port'));
|
||||
const sp = s.option(form.ListValue, 'mirror_source_port', _('Mirror source port'));
|
||||
const mp = s.option(form.ListValue, 'mirror_monitor_port', _('Mirror monitor port'));
|
||||
|
||||
sp.depends('enable_mirror_rx', '1');
|
||||
sp.depends('enable_mirror_tx', '1');
|
||||
@@ -209,9 +207,9 @@ return view.extend({
|
||||
mp.depends('enable_mirror_rx', '1');
|
||||
mp.depends('enable_mirror_tx', '1');
|
||||
|
||||
for (var j = 0; j < topology.ports.length; j++) {
|
||||
sp.value(topology.ports[j].num, topology.ports[j].label);
|
||||
mp.value(topology.ports[j].num, topology.ports[j].label);
|
||||
for (let tp of topology.ports) {
|
||||
sp.value(tp.num, tp.label);
|
||||
mp.value(tp.num, tp.label);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,16 +221,16 @@ return view.extend({
|
||||
s.device = switch_name;
|
||||
|
||||
s.filter = function(section_id) {
|
||||
var device = uci.get('network', section_id, 'device');
|
||||
const device = uci.get('network', section_id, 'device');
|
||||
return (device == this.device);
|
||||
};
|
||||
|
||||
s.cfgsections = function() {
|
||||
var sections = form.TableSection.prototype.cfgsections.apply(this);
|
||||
const sections = form.TableSection.prototype.cfgsections.apply(this);
|
||||
|
||||
return sections.sort(function(a, b) {
|
||||
var vidA = feat.vid_option ? uci.get('network', a, feat.vid_option) : null,
|
||||
vidB = feat.vid_option ? uci.get('network', b, feat.vid_option) : null;
|
||||
let vidA = feat.vid_option ? uci.get('network', a, feat.vid_option) : null;
|
||||
let vidB = feat.vid_option ? uci.get('network', b, feat.vid_option) : null;
|
||||
|
||||
vidA = +(vidA != null ? vidA : uci.get('network', a, 'vlan') || 9999);
|
||||
vidB = +(vidB != null ? vidB : uci.get('network', b, 'vlan') || 9999);
|
||||
@@ -242,17 +240,17 @@ return view.extend({
|
||||
};
|
||||
|
||||
s.handleAdd = function(ev) {
|
||||
var sections = uci.sections('network', 'switch_vlan'),
|
||||
section_id = uci.add('network', 'switch_vlan'),
|
||||
max_vlan = 0,
|
||||
max_vid = 0;
|
||||
const sections = uci.sections('network', 'switch_vlan');
|
||||
const section_id = uci.add('network', 'switch_vlan');
|
||||
let max_vlan = 0;
|
||||
let max_vid = 0;
|
||||
|
||||
for (var j = 0; j < sections.length; j++) {
|
||||
if (sections[j].device != this.device)
|
||||
for (let s of sections) {
|
||||
if (s.device != this.device)
|
||||
continue;
|
||||
|
||||
var vlan = +sections[j].vlan,
|
||||
vid = feat.vid_option ? +sections[j][feat.vid_option] : null;
|
||||
const vlan = +s.vlan;
|
||||
const vid = feat.vid_option ? +s[feat.vid_option] : null;
|
||||
|
||||
if (vlan > max_vlan)
|
||||
max_vlan = vlan;
|
||||
@@ -278,34 +276,34 @@ return view.extend({
|
||||
o.description = _('Port status:');
|
||||
|
||||
o.validate = function(section_id, value) {
|
||||
var v = +value,
|
||||
m = feat.vid_option ? 4094 : num_vlans - 1;
|
||||
const v = +value;
|
||||
const m = feat.vid_option ? 4094 : num_vlans - 1;
|
||||
|
||||
if (isNaN(v) || v < min_vid || v > m)
|
||||
return _('Invalid VLAN ID given! Only IDs between %d and %d are allowed.').format(min_vid, m);
|
||||
|
||||
var sections = this.section.cfgsections();
|
||||
const sections = this.section.cfgsections();
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i] == section_id)
|
||||
for (let s of sections) {
|
||||
if (s == section_id)
|
||||
continue;
|
||||
|
||||
if (this.formvalue(sections[i]) == v)
|
||||
if (this.formvalue(s) == v)
|
||||
return _('Invalid VLAN ID given! Only unique IDs are allowed');
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var port_opts = o.port_opts = [];
|
||||
const port_opts = o.port_opts = [];
|
||||
|
||||
o.write = function(section_id, value) {
|
||||
var topology = this.section.topology,
|
||||
values = [];
|
||||
const topology = this.section.topology;
|
||||
const values = [];
|
||||
|
||||
for (var i = 0; i < this.port_opts.length; i++) {
|
||||
var tagging = this.port_opts[i].formvalue(section_id),
|
||||
portspec = Array.isArray(topology.ports) ? topology.ports[i] : null;
|
||||
for (let i = 0; i < this.port_opts.length; i++) {
|
||||
const tagging = this.port_opts[i].formvalue(section_id);
|
||||
const portspec = Array.isArray(topology.ports) ? topology.ports[i] : null;
|
||||
|
||||
if (tagging == 't')
|
||||
values.push(this.port_opts[i].option + tagging);
|
||||
@@ -313,12 +311,12 @@ return view.extend({
|
||||
values.push(this.port_opts[i].option);
|
||||
|
||||
if (portspec && portspec.device) {
|
||||
var old_tag = this.port_opts[i].cfgvalue(section_id),
|
||||
old_vid = this.cfgvalue(section_id);
|
||||
const old_tag = this.port_opts[i].cfgvalue(section_id);
|
||||
const old_vid = this.cfgvalue(section_id);
|
||||
|
||||
if (old_tag != tagging || old_vid != value) {
|
||||
var old_ifname = portspec.device + (old_tag != 'u' ? '.' + old_vid : ''),
|
||||
new_ifname = portspec.device + (tagging != 'u' ? '.' + value : '');
|
||||
const old_ifname = portspec.device + (old_tag != 'u' ? '.' + old_vid : '');
|
||||
const new_ifname = portspec.device + (tagging != 'u' ? '.' + value : '');
|
||||
|
||||
if (old_ifname != new_ifname)
|
||||
update_interfaces(old_ifname, new_ifname);
|
||||
@@ -335,15 +333,15 @@ return view.extend({
|
||||
};
|
||||
|
||||
o.cfgvalue = function(section_id) {
|
||||
var value = feat.vid_option ? uci.get('network', section_id, feat.vid_option) : null;
|
||||
const value = feat.vid_option ? uci.get('network', section_id, feat.vid_option) : null;
|
||||
return (value || uci.get('network', section_id, 'vlan'));
|
||||
};
|
||||
|
||||
s.option(form.Value, 'description', _('Description'));
|
||||
|
||||
for (var j = 0; Array.isArray(topology.ports) && j < topology.ports.length; j++) {
|
||||
var portspec = topology.ports[j],
|
||||
portstate = Array.isArray(topology.portstate) ? topology.portstate[portspec.num] : null;
|
||||
for (let j = 0; Array.isArray(topology.ports) && j < topology.ports.length; j++) {
|
||||
const portspec = topology.ports[j];
|
||||
const portstate = Array.isArray(topology.portstate) ? topology.portstate[portspec.num] : null;
|
||||
|
||||
o = s.option(form.ListValue, String(portspec.num), portspec.label);
|
||||
o.value('', _('off'));
|
||||
|
||||
@@ -1867,7 +1867,7 @@ return view.extend({
|
||||
const has_80211r = L.hasSystemFeature('hostapd', '11r') || L.hasSystemFeature('hostapd', 'eap');
|
||||
|
||||
o = ss.taboption('roaming', form.Flag, 'ieee80211r', _('802.11r Fast Transition'), _('Enables fast roaming among access points that belong to the same Mobility Domain'));
|
||||
add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa2', 'wpa3', 'wpa3-mixed', , 'wpa3-192'] });
|
||||
add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['wpa2', 'wpa3', 'wpa3-mixed', 'wpa3-192'] });
|
||||
if (has_80211r)
|
||||
add_dependency_permutations(o, { mode: ['ap', 'ap-wds'], encryption: ['psk2', 'psk-mixed', 'sae', 'sae-mixed'] });
|
||||
o.rmempty = true;
|
||||
|
||||
@@ -44,7 +44,6 @@ return view.extend({
|
||||
const data_wanted = Math.floor(width / step);
|
||||
|
||||
const data_values = [];
|
||||
const line_elements = [];
|
||||
|
||||
for (const line of lines)
|
||||
if (line)
|
||||
@@ -244,10 +243,10 @@ return view.extend({
|
||||
|
||||
render([svg, devs]) {
|
||||
|
||||
var v = E('div', { 'class': 'cbi-map', 'id': 'map' }, E('div'));
|
||||
const v = E('div', { 'class': 'cbi-map', 'id': 'map' }, E('div'));
|
||||
|
||||
for (const dev of devs) {
|
||||
var ifname = dev.getName();
|
||||
const ifname = dev.getName();
|
||||
const ssid = dev.wif?.getSSID?.() || null;
|
||||
|
||||
if (!ifname || !dev.isUp() || dev.wif?.isDisabled())
|
||||
|
||||
@@ -8,22 +8,22 @@
|
||||
'require tools.prng as random';
|
||||
|
||||
return view.extend({
|
||||
callFrequencyList : rpc.declare({
|
||||
callFrequencyList: rpc.declare({
|
||||
object: 'iwinfo',
|
||||
method: 'freqlist',
|
||||
params: [ 'device' ],
|
||||
expect: { results: [] }
|
||||
}),
|
||||
|
||||
callInfo : rpc.declare({
|
||||
callInfo: rpc.declare({
|
||||
object: 'iwinfo',
|
||||
method: 'info',
|
||||
params: [ 'device' ],
|
||||
expect: { }
|
||||
}),
|
||||
|
||||
render_signal_badge: function(signalPercent, signalValue) {
|
||||
var icon, title, value;
|
||||
render_signal_badge(signalPercent, signalValue) {
|
||||
let icon, title, value;
|
||||
|
||||
if (signalPercent < 0)
|
||||
icon = L.resource('icons/signal-none.svg');
|
||||
@@ -51,7 +51,7 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
add_wifi_to_graph: function(chan_analysis, res, scanCache, channels, channel_width) {
|
||||
add_wifi_to_graph(chan_analysis, res, scanCache, channels, channel_width) {
|
||||
const offset_tbl = chan_analysis.offset_tbl;
|
||||
const height = chan_analysis.graph.offsetHeight - 2;
|
||||
const step = chan_analysis.col_width;
|
||||
@@ -112,15 +112,15 @@ return view.extend({
|
||||
})
|
||||
},
|
||||
|
||||
create_channel_graph: function(chan_analysis, freq_tbl, band) {
|
||||
var columns = (band != 2) ? freq_tbl.length * 4 : freq_tbl.length + 3,
|
||||
chan_graph = chan_analysis.graph,
|
||||
G = chan_graph.firstElementChild,
|
||||
step = (chan_graph.offsetWidth - 2) / columns,
|
||||
curr_offset = step;
|
||||
create_channel_graph(chan_analysis, freq_tbl, band) {
|
||||
const columns = (band != 2) ? freq_tbl.length * 4 : freq_tbl.length + 3;
|
||||
const chan_graph = chan_analysis.graph;
|
||||
const G = chan_graph.firstElementChild;
|
||||
const step = (chan_graph.offsetWidth - 2) / columns;
|
||||
let curr_offset = step;
|
||||
|
||||
function createGraphHLine(graph, pos, width, dash) {
|
||||
var elem = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
const elem = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
elem.setAttribute('x1', pos);
|
||||
elem.setAttribute('y1', 0);
|
||||
elem.setAttribute('x2', pos);
|
||||
@@ -130,7 +130,7 @@ return view.extend({
|
||||
}
|
||||
|
||||
function createGraphText(graph, pos, text) {
|
||||
var elem = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
const elem = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
elem.setAttribute('y', 15);
|
||||
elem.setAttribute('style', 'fill:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
elem.setAttribute('x', pos + 5);
|
||||
@@ -141,8 +141,8 @@ return view.extend({
|
||||
chan_analysis.col_width = step;
|
||||
|
||||
createGraphHLine(G,curr_offset, 0.1, 1);
|
||||
for (var i=0; i< freq_tbl.length;i++) {
|
||||
var channel = freq_tbl[i]
|
||||
for (let i=0; i< freq_tbl.length;i++) {
|
||||
const channel = freq_tbl[i]
|
||||
chan_analysis.offset_tbl[channel] = curr_offset+step;
|
||||
|
||||
if (band != 2) {
|
||||
@@ -158,10 +158,10 @@ return view.extend({
|
||||
curr_offset += step;
|
||||
|
||||
if ((band != 2) && freq_tbl[i+1]) {
|
||||
var next_channel = freq_tbl[i+1];
|
||||
const next_channel = freq_tbl[i+1];
|
||||
/* Check if we are transitioning to another 5/6Ghz band range */
|
||||
if ((next_channel - channel) == 4) {
|
||||
for (var j=1; j < 4; j++) {
|
||||
for (let j=1; j < 4; j++) {
|
||||
chan_analysis.offset_tbl[channel+j] = curr_offset+step;
|
||||
if (j == 2)
|
||||
createGraphHLine(G,curr_offset+step, 0.1, 0);
|
||||
@@ -193,31 +193,30 @@ return view.extend({
|
||||
}, this));
|
||||
},
|
||||
|
||||
handleScanRefresh: function() {
|
||||
handleScanRefresh() {
|
||||
if (!this.active_tab)
|
||||
return;
|
||||
|
||||
var radio = this.radios[this.active_tab];
|
||||
const radio = this.radios[this.active_tab];
|
||||
let q;
|
||||
|
||||
return Promise.all([
|
||||
radio.dev.getScanList(),
|
||||
this.callInfo(radio.dev.getName())
|
||||
]).then(L.bind(function(data) {
|
||||
var results = data[0],
|
||||
local_wifi = data[1],
|
||||
table = radio.table,
|
||||
chan_analysis = radio.graph,
|
||||
scanCache = radio.scanCache,
|
||||
band = radio.band;
|
||||
]).then(L.bind(function([results, local_wifi]) {
|
||||
const table = radio.table;
|
||||
const chan_analysis = radio.graph;
|
||||
const scanCache = radio.scanCache;
|
||||
const band = radio.band;
|
||||
|
||||
var rows = [];
|
||||
const rows = [];
|
||||
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
if (scanCache[results[i].bssid] == null)
|
||||
scanCache[results[i].bssid] = {};
|
||||
for (let res of results) {
|
||||
if (scanCache[res.bssid] == null)
|
||||
scanCache[res.bssid] = {};
|
||||
|
||||
scanCache[results[i].bssid].data = results[i];
|
||||
scanCache[results[i].bssid].data.stale = false;
|
||||
scanCache[res.bssid].data = res;
|
||||
scanCache[res.bssid].data.stale = false;
|
||||
}
|
||||
|
||||
if (band + 'g' == radio.dev.get('band')) {
|
||||
@@ -227,9 +226,9 @@ return view.extend({
|
||||
scanCache[local_wifi.bssid].data = local_wifi;
|
||||
|
||||
if (chan_analysis.offset_tbl[local_wifi.channel] != null && local_wifi.center_chan1) {
|
||||
var center_channels = [local_wifi.center_chan1],
|
||||
chan_width_text = local_wifi.htmode.replace(/[EV]*H[TE]/,''), /* Handle HT VHT HE EHT */
|
||||
chan_width = parseInt(chan_width_text)/10;
|
||||
const center_channels = [local_wifi.center_chan1];
|
||||
const chan_width_text = local_wifi.htmode.replace(/[EV]*H[TE]/,''); /* Handle HT VHT HE EHT */
|
||||
let chan_width = parseInt(chan_width_text)/10;
|
||||
|
||||
if (local_wifi.center_chan2) {
|
||||
center_channels.push(local_wifi.center_chan2);
|
||||
@@ -254,7 +253,7 @@ return view.extend({
|
||||
}
|
||||
}
|
||||
|
||||
for (var k in scanCache)
|
||||
for (let k in scanCache)
|
||||
if (scanCache[k].data.stale)
|
||||
results.push(scanCache[k].data);
|
||||
|
||||
@@ -273,14 +272,13 @@ return view.extend({
|
||||
return 1;
|
||||
});
|
||||
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
var res = results[i],
|
||||
qv = res.quality || 0,
|
||||
qm = res.quality_max || 0,
|
||||
q = (qv > 0 && qm > 0) ? Math.floor((100 / qm) * qv) : 0,
|
||||
s = res.stale ? 'opacity:0.5' : '',
|
||||
center_channels = [res.channel],
|
||||
chan_width = 2;
|
||||
for (let res of results) {
|
||||
const qv = res.quality || 0;
|
||||
const qm = res.quality_max || 0;
|
||||
q = (qv > 0 && qm > 0) ? Math.floor((100 / qm) * qv) : 0;
|
||||
const s = res.stale ? 'opacity:0.5' : '';
|
||||
const center_channels = [res.channel];
|
||||
let chan_width = 2;
|
||||
|
||||
/* Skip WiFi not supported by the current band */
|
||||
if (band != res.band)
|
||||
@@ -319,7 +317,7 @@ return view.extend({
|
||||
|
||||
/* If needed, adjust based on the 802.11ac Wave 2 interop workaround. */
|
||||
if (res.vht_operation.center_freq_2) {
|
||||
var diff = Math.abs(res.vht_operation.center_freq_2 -
|
||||
const diff = Math.abs(res.vht_operation.center_freq_2 -
|
||||
res.vht_operation.center_freq_1);
|
||||
|
||||
if (diff == 8) {
|
||||
@@ -370,7 +368,7 @@ return view.extend({
|
||||
rows.push([
|
||||
E('span', { 'style': s }, this.render_signal_badge(q, res.signal)),
|
||||
E('span', { 'style': s }, [
|
||||
E('span', { 'style': 'color:'+scanCache[results[i].bssid].color }, '⬤ '),
|
||||
E('span', { 'style': 'color:'+scanCache[res.bssid].color }, '⬤ '),
|
||||
(res.ssid != null) ? '%h'.format(res.ssid) : E('em', _('hidden'))
|
||||
]),
|
||||
E('span', { 'style': s }, '%d'.format(res.channel)),
|
||||
@@ -379,7 +377,7 @@ return view.extend({
|
||||
E('span', { 'style': s }, '%h'.format(res.bssid))
|
||||
]);
|
||||
|
||||
scanCache[results[i].bssid].data.stale = true;
|
||||
scanCache[res.bssid].data.stale = true;
|
||||
}
|
||||
|
||||
cbi_update_table(table, rows);
|
||||
@@ -391,9 +389,9 @@ return view.extend({
|
||||
}, this))
|
||||
},
|
||||
|
||||
radios : {},
|
||||
radios: {},
|
||||
|
||||
loadSVG : function(src) {
|
||||
loadSVG(src) {
|
||||
return request.get(src).then(function(response) {
|
||||
if (!response.ok)
|
||||
throw new Error(response.statusText);
|
||||
@@ -405,19 +403,19 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
this.loadSVG(L.resource('svg/channel_analysis.svg')),
|
||||
network.getWifiDevices().then(L.bind(function(data) {
|
||||
var tasks = [], ret = [];
|
||||
const tasks = [], ret = [];
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
ret[data[i].getName()] = { dev : data[i] };
|
||||
for (let d of data) {
|
||||
ret[d.getName()] = { dev : d };
|
||||
|
||||
tasks.push(this.callFrequencyList(data[i].getName())
|
||||
tasks.push(this.callFrequencyList(d.getName())
|
||||
.then(L.bind(function(radio, data) {
|
||||
ret[radio.getName()].freq = data;
|
||||
}, this, data[i])));
|
||||
}, this, d)));
|
||||
}
|
||||
|
||||
return Promise.all(tasks).then(function() { return ret; })
|
||||
@@ -425,11 +423,8 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var svg = data[0],
|
||||
wifiDevs = data[1];
|
||||
|
||||
var h2 = E('div', {'class' : 'cbi-title-section'}, [
|
||||
render([svg, wifiDevs]) {
|
||||
const h2 = E('div', {'class' : 'cbi-title-section'}, [
|
||||
E('h2', {'class': 'cbi-title-field'}, [ _('Channel Analysis') ]),
|
||||
E('div', {'class': 'cbi-title-buttons' }, [
|
||||
E('button', {
|
||||
@@ -438,10 +433,10 @@ return view.extend({
|
||||
}, [ _('Refresh Channels') ])])
|
||||
]);
|
||||
|
||||
var tabs = E('div', {}, E('div'));
|
||||
const tabs = E('div', {}, E('div'));
|
||||
|
||||
for (var ifname in wifiDevs) {
|
||||
var bands = {
|
||||
for (let ifname in wifiDevs) {
|
||||
const bands = {
|
||||
[2] : { title: '2.4GHz', channels: [] },
|
||||
[5] : { title: '5GHz', channels: [] },
|
||||
[6] : { title: '6GHz', channels: [] },
|
||||
@@ -453,12 +448,12 @@ return view.extend({
|
||||
bands[freq.band].channels.push(freq.channel);
|
||||
});
|
||||
|
||||
for (var band in bands) {
|
||||
for (let band in bands) {
|
||||
if (bands[band].channels.length == 0)
|
||||
continue;
|
||||
|
||||
var csvg = svg.cloneNode(true),
|
||||
table = E('table', { 'class': 'table' }, [
|
||||
const csvg = svg.cloneNode(true);
|
||||
const table = E('table', { 'class': 'table' }, [
|
||||
E('tr', { 'class': 'tr table-titles' }, [
|
||||
E('th', { 'class': 'th col-2 middle center' }, _('Signal')),
|
||||
E('th', { 'class': 'th col-4 middle left' }, _('SSID')),
|
||||
|
||||
@@ -5,107 +5,106 @@
|
||||
'require rpc';
|
||||
'require fs';
|
||||
|
||||
var callLuciRealtimeStats = rpc.declare({
|
||||
const callLuciRealtimeStats = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getRealtimeStats',
|
||||
params: [ 'mode', 'device' ],
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
var callLuciConntrackList = rpc.declare({
|
||||
const callLuciConntrackList = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getConntrackList',
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
var callNetworkRrdnsLookup = rpc.declare({
|
||||
const callNetworkRrdnsLookup = rpc.declare({
|
||||
object: 'network.rrdns',
|
||||
method: 'lookup',
|
||||
params: [ 'addrs', 'timeout', 'limit' ],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
var callLuciRpcGetHostHints = rpc.declare({
|
||||
const callLuciRpcGetHostHints = rpc.declare({
|
||||
object: 'luci-rpc',
|
||||
method: 'getHostHints',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
var callLuciRpcGetNetworkDevices = rpc.declare({
|
||||
const callLuciRpcGetNetworkDevices = rpc.declare({
|
||||
object: 'luci-rpc',
|
||||
method: 'getNetworkDevices',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
var callLuciRpcGetDHCPLeases = rpc.declare({
|
||||
const callLuciRpcGetDHCPLeases = rpc.declare({
|
||||
object: 'luci-rpc',
|
||||
method: 'getDHCPLeases',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
var graphPolls = [],
|
||||
pollInterval = 3,
|
||||
dns_cache = Object.create(null),
|
||||
service_cache = Object.create(null),
|
||||
ethers_cache = Object.create(null),
|
||||
ethers_cache_is_loaded = false,
|
||||
enableLookups = false,
|
||||
filterText = '';
|
||||
const graphPolls = [];
|
||||
const pollInterval = 3;
|
||||
const dns_cache = Object.create(null);
|
||||
const service_cache = Object.create(null);
|
||||
const ethers_cache = Object.create(null);
|
||||
let ethers_cache_is_loaded = false;
|
||||
let enableLookups = false;
|
||||
let filterText = '';
|
||||
|
||||
var recheck_lookup_queue = {};
|
||||
const recheck_lookup_queue = {};
|
||||
|
||||
Math.log2 = Math.log2 || function(x) { return Math.log(x) * Math.LOG2E; };
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
this.loadSVG(L.resource('svg/connections.svg'))
|
||||
]);
|
||||
},
|
||||
|
||||
updateGraph: function(svg, lines, cb) {
|
||||
var G = svg.firstElementChild;
|
||||
updateGraph(svg, lines, cb) {
|
||||
const G = svg.firstElementChild;
|
||||
|
||||
var view = document.querySelector('#view');
|
||||
const view = document.querySelector('#view');
|
||||
|
||||
var width = view.offsetWidth - 2;
|
||||
var height = 300 - 2;
|
||||
var step = 5;
|
||||
const width = view.offsetWidth - 2;
|
||||
const height = 300 - 2;
|
||||
const step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
const data_wanted = Math.floor(width / step);
|
||||
|
||||
var data_values = [],
|
||||
line_elements = [];
|
||||
const data_values = [];
|
||||
|
||||
for (var i = 0; i < lines.length; i++)
|
||||
if (lines[i] != null)
|
||||
for (let line of lines)
|
||||
if (line != null)
|
||||
data_values.push([]);
|
||||
|
||||
var info = {
|
||||
const info = {
|
||||
line_current: [],
|
||||
line_average: [],
|
||||
line_peak: []
|
||||
};
|
||||
|
||||
/* prefill datasets */
|
||||
for (var i = 0; i < data_values.length; i++)
|
||||
for (var j = 0; j < data_wanted; j++)
|
||||
data_values[i][j] = 0;
|
||||
for (let dv of data_values)
|
||||
for (let j = 0; j < data_wanted; j++)
|
||||
dv[j] = 0;
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (step * 60); i < width; i += step * 60) {
|
||||
var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', i);
|
||||
line.setAttribute('y1', 0);
|
||||
line.setAttribute('x2', i);
|
||||
line.setAttribute('y2', '100%');
|
||||
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
for (let i = width % (step * 60); i < width; i += step * 60) {
|
||||
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', i);
|
||||
line.setAttribute('y1', 0);
|
||||
line.setAttribute('x2', i);
|
||||
line.setAttribute('y2', '100%');
|
||||
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
|
||||
var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text.setAttribute('x', i + 5);
|
||||
text.setAttribute('y', 15);
|
||||
text.setAttribute('style', 'fill:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
text.appendChild(document.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text.setAttribute('x', i + 5);
|
||||
text.setAttribute('y', 15);
|
||||
text.setAttribute('style', 'fill:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
text.appendChild(document.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
|
||||
G.appendChild(line);
|
||||
G.appendChild(text);
|
||||
@@ -128,7 +127,7 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
updateConntrack: async function(conn) {
|
||||
async updateConntrack(conn) {
|
||||
async function fetchServices() {
|
||||
if (!enableLookups) return;
|
||||
if (Object.keys(service_cache).length > 0) return;
|
||||
@@ -283,38 +282,37 @@ return view.extend({
|
||||
}
|
||||
},
|
||||
|
||||
pollData: async function() {
|
||||
async pollData() {
|
||||
poll.add(L.bind(async function() {
|
||||
var tasks = [
|
||||
const tasks = [
|
||||
L.resolveDefault(callLuciConntrackList(), [])
|
||||
];
|
||||
|
||||
for (var i = 0; i < graphPolls.length; i++) {
|
||||
var ctx = graphPolls[i];
|
||||
graphPolls.forEach(() => {
|
||||
tasks.push(L.resolveDefault(callLuciRealtimeStats('conntrack'), []));
|
||||
}
|
||||
});
|
||||
|
||||
const datasets = await Promise.all(tasks);
|
||||
await this.updateConntrack(datasets[0]);
|
||||
for (var gi = 0; gi < graphPolls.length; gi++) {
|
||||
var ctx = graphPolls[gi],
|
||||
data = datasets[gi + 1],
|
||||
values = ctx.values,
|
||||
lines = ctx.lines,
|
||||
info = ctx.info;
|
||||
for (let gi = 0; gi < graphPolls.length; gi++) {
|
||||
const ctx = graphPolls[gi];
|
||||
const data = datasets[gi + 1];
|
||||
const values = ctx.values;
|
||||
const lines = ctx.lines;
|
||||
const info = ctx.info;
|
||||
|
||||
var data_scale = 0;
|
||||
var data_wanted = Math.floor(ctx.width / ctx.step);
|
||||
var last_timestamp = NaN;
|
||||
let data_scale = 0;
|
||||
let data_wanted = Math.floor(ctx.width / ctx.step);
|
||||
let last_timestamp = NaN;
|
||||
|
||||
for (var i = 0, di = 0; di < lines.length; di++) {
|
||||
for (let i = 0, di = 0; di < lines.length; di++) {
|
||||
if (lines[di] == null)
|
||||
continue;
|
||||
|
||||
var multiply = (lines[di].multiply != null) ? lines[di].multiply : 1,
|
||||
offset = (lines[di].offset != null) ? lines[di].offset : 0;
|
||||
const multiply = (lines[di].multiply != null) ? lines[di].multiply : 1;
|
||||
const offset = (lines[di].offset != null) ? lines[di].offset : 0;
|
||||
|
||||
for (var j = ctx.timestamp ? 0 : 1; j < data.length; j++) {
|
||||
for (let j = ctx.timestamp ? 0 : 1; j < data.length; j++) {
|
||||
/* skip overlapping entries */
|
||||
if (data[j][0] <= ctx.timestamp)
|
||||
continue;
|
||||
@@ -335,15 +333,15 @@ return view.extend({
|
||||
/* cut off outdated entries */
|
||||
ctx.fill = Math.min(ctx.fill, data_wanted);
|
||||
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var len = values[i].length;
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
const len = values[i].length;
|
||||
values[i] = values[i].slice(len - data_wanted, len);
|
||||
|
||||
/* find peaks, averages */
|
||||
info.line_peak[i] = NaN;
|
||||
info.line_average[i] = 0;
|
||||
|
||||
for (var j = 0; j < values[i].length; j++) {
|
||||
for (let j = 0; j < values[i].length; j++) {
|
||||
info.line_peak[i] = isNaN(info.line_peak[i]) ? values[i][j] : Math.max(info.line_peak[i], values[i][j]);
|
||||
info.line_average[i] += values[i][j];
|
||||
}
|
||||
@@ -357,29 +355,29 @@ return view.extend({
|
||||
if (!isNaN(last_timestamp))
|
||||
ctx.timestamp = last_timestamp;
|
||||
|
||||
var size = Math.floor(Math.log2(info.peak)),
|
||||
div = Math.pow(2, size - (size % 10)),
|
||||
mult = info.peak / div,
|
||||
mult = (mult < 5) ? 2 : ((mult < 50) ? 10 : ((mult < 500) ? 100 : 1000));
|
||||
const size = Math.floor(Math.log2(info.peak));
|
||||
const div = Math.pow(2, size - (size % 10));
|
||||
let mult = info.peak / div;
|
||||
mult = (mult < 5) ? 2 : ((mult < 50) ? 10 : ((mult < 500) ? 100 : 1000));
|
||||
|
||||
info.peak = info.peak + (mult * div) - (info.peak % (mult * div));
|
||||
|
||||
data_scale = ctx.height / info.peak;
|
||||
|
||||
/* plot data */
|
||||
for (var i = 0, di = 0; di < lines.length; di++) {
|
||||
for (let i = 0, di = 0; di < lines.length; di++) {
|
||||
if (lines[di] == null)
|
||||
continue;
|
||||
|
||||
var el = ctx.svg.firstElementChild.getElementById(lines[di].line),
|
||||
pt = '0,' + ctx.height,
|
||||
y = 0;
|
||||
const el = ctx.svg.firstElementChild.getElementById(lines[di].line);
|
||||
let pt = '0,' + ctx.height;
|
||||
let y = 0;
|
||||
|
||||
if (!el)
|
||||
continue;
|
||||
|
||||
for (var j = 0; j < values[i].length; j++) {
|
||||
var x = j * ctx.step;
|
||||
for (let j = 0; j < values[i].length; j++) {
|
||||
let x = j * ctx.step;
|
||||
|
||||
y = ctx.height - Math.floor(values[i][j] * data_scale);
|
||||
//y -= Math.floor(y % (1 / data_scale));
|
||||
@@ -406,7 +404,7 @@ return view.extend({
|
||||
}, this), pollInterval);
|
||||
},
|
||||
|
||||
loadSVG: function(src) {
|
||||
loadSVG(src) {
|
||||
return request.get(src).then(function(response) {
|
||||
if (!response.ok)
|
||||
throw new Error(response.statusText);
|
||||
@@ -417,10 +415,9 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var svg = data[0];
|
||||
render([svg]) {
|
||||
|
||||
var v = E('div', { 'class': 'cbi-map', 'id': 'map' }, [
|
||||
const v = E('div', { 'class': 'cbi-map', 'id': 'map' }, [
|
||||
E('h2', _('Connections')),
|
||||
E('div', {'class': 'cbi-map-descr'}, _('This page displays the active connections via this device.')),
|
||||
E('div', { 'class': 'cbi-section' }, [
|
||||
@@ -527,7 +524,7 @@ return view.extend({
|
||||
]);
|
||||
|
||||
this.updateGraph(svg, [ { line: 'udp' }, { line: 'tcp' }, { line: 'other' } ], function(svg, info) {
|
||||
var G = svg.firstElementChild, tab = svg.parentNode;
|
||||
const G = svg.firstElementChild, tab = svg.parentNode;
|
||||
|
||||
G.getElementById('label_25').firstChild.data = '%d'.format(info.label_25);
|
||||
G.getElementById('label_50').firstChild.data = '%d'.format(info.label_50);
|
||||
|
||||
@@ -35,7 +35,7 @@ return view.extend({
|
||||
*/
|
||||
],
|
||||
|
||||
retrieveLog: async function() {
|
||||
async retrieveLog() {
|
||||
return fs.exec_direct('/bin/dmesg', [ '-r' ]).then(logdata => {
|
||||
let loglines = [];
|
||||
let lastSeverity = null;
|
||||
@@ -113,7 +113,7 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
pollLog: async function() {
|
||||
async pollLog() {
|
||||
const element = document.getElementById('syslog');
|
||||
if (element) {
|
||||
const log = await this.retrieveLog();
|
||||
@@ -122,12 +122,12 @@ return view.extend({
|
||||
}
|
||||
},
|
||||
|
||||
load: async function() {
|
||||
async load() {
|
||||
poll.add(this.pollLog.bind(this));
|
||||
return await this.retrieveLog();
|
||||
},
|
||||
|
||||
render: function(loglines) {
|
||||
render(loglines) {
|
||||
const scrollDownButton = E('button', {
|
||||
'id': 'scrollDownButton',
|
||||
'class': 'cbi-button cbi-button-neutral',
|
||||
@@ -193,7 +193,7 @@ return view.extend({
|
||||
'id': 'logSeveritySelect',
|
||||
'class': 'cbi-input-select',
|
||||
},
|
||||
this.severity.map(([val, tag, label]) =>
|
||||
this.severity.map(([val, , label]) =>
|
||||
E('option', { value: val }, label)
|
||||
));
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
'require network';
|
||||
'require firewall';
|
||||
|
||||
var callGetBuiltinEthernetPorts = rpc.declare({
|
||||
const callGetBuiltinEthernetPorts = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getBuiltinEthernetPorts',
|
||||
expect: { result: [] }
|
||||
@@ -28,7 +28,7 @@ function isString(v)
|
||||
function resolveVLANChain(ifname, bridges, mapping)
|
||||
{
|
||||
while (!mapping[ifname]) {
|
||||
var m = ifname.match(/^(.+)\.([^.]+)$/);
|
||||
const m = ifname.match(/^(.+)\.([^.]+)$/);
|
||||
|
||||
if (!m)
|
||||
break;
|
||||
@@ -52,24 +52,24 @@ function resolveVLANChain(ifname, bridges, mapping)
|
||||
|
||||
function buildVLANMappings(mapping)
|
||||
{
|
||||
var bridge_vlans = uci.sections('network', 'bridge-vlan'),
|
||||
vlan_devices = uci.sections('network', 'device'),
|
||||
interfaces = uci.sections('network', 'interface'),
|
||||
bridges = {};
|
||||
const bridge_vlans = uci.sections('network', 'bridge-vlan');
|
||||
const vlan_devices = uci.sections('network', 'device');
|
||||
const interfaces = uci.sections('network', 'interface');
|
||||
const bridges = {};
|
||||
|
||||
/* find bridge VLANs */
|
||||
for (var i = 0, s; (s = bridge_vlans[i]) != null; i++) {
|
||||
for (let i = 0, s; (s = bridge_vlans[i]) != null; i++) {
|
||||
if (!isString(s.device) || !/^[0-9]{1,4}$/.test(s.vlan) || +s.vlan > 4095)
|
||||
continue;
|
||||
|
||||
var aliases = L.toArray(s.alias),
|
||||
ports = L.toArray(s.ports),
|
||||
br = bridges[s.device] = (bridges[s.device] || { ports: [], vlans: {}, vlan_filtering: true });
|
||||
const aliases = L.toArray(s.alias);
|
||||
const ports = L.toArray(s.ports);
|
||||
const br = bridges[s.device] = (bridges[s.device] || { ports: [], vlans: {}, vlan_filtering: true });
|
||||
|
||||
br.vlans[s.vlan] = [];
|
||||
|
||||
for (var j = 0; j < ports.length; j++) {
|
||||
var port = ports[j].replace(/:[ut*]+$/, '');
|
||||
for (let p of ports) {
|
||||
const port = p.replace(/:[ut*]+$/, '');
|
||||
|
||||
if (br.ports.indexOf(port) === -1)
|
||||
br.ports.push(port);
|
||||
@@ -77,28 +77,28 @@ function buildVLANMappings(mapping)
|
||||
br.vlans[s.vlan].push(port);
|
||||
}
|
||||
|
||||
for (var j = 0; j < aliases.length; j++)
|
||||
if (aliases[j] != s.vlan)
|
||||
br.vlans[aliases[j]] = br.vlans[s.vlan];
|
||||
for (let a of aliases)
|
||||
if (a != s.vlan)
|
||||
br.vlans[a] = br.vlans[s.vlan];
|
||||
}
|
||||
|
||||
/* find bridges, VLAN devices */
|
||||
for (var i = 0, s; (s = vlan_devices[i]) != null; i++) {
|
||||
for (let i = 0, s; (s = vlan_devices[i]) != null; i++) {
|
||||
if (s.type == 'bridge') {
|
||||
if (!isString(s.name))
|
||||
continue;
|
||||
|
||||
var ports = L.toArray(s.ports),
|
||||
br = bridges[s.name] || (bridges[s.name] = { ports: [], vlans: {}, vlan_filtering: false });
|
||||
const ports = L.toArray(s.ports);
|
||||
const br = bridges[s.name] || (bridges[s.name] = { ports: [], vlans: {}, vlan_filtering: false });
|
||||
|
||||
if (s.vlan_filtering == '0')
|
||||
br.vlan_filtering = false;
|
||||
else if (s.vlan_filtering == '1')
|
||||
br.vlan_filtering = true;
|
||||
|
||||
for (var j = 0; j < ports.length; j++)
|
||||
if (br.ports.indexOf(ports[j]) === -1)
|
||||
br.ports.push(ports[j]);
|
||||
for (let p of ports)
|
||||
if (br.ports.indexOf(p) === -1)
|
||||
br.ports.push(p);
|
||||
|
||||
mapping[s.name] = br.ports;
|
||||
}
|
||||
@@ -127,17 +127,17 @@ function buildVLANMappings(mapping)
|
||||
}
|
||||
|
||||
/* resolve VLAN tagged interfaces in bridge ports */
|
||||
for (var brname in bridges) {
|
||||
for (var i = 0; i < bridges[brname].ports.length; i++)
|
||||
resolveVLANChain(bridges[brname].ports[i], bridges, mapping);
|
||||
for (let brname in bridges) {
|
||||
for (let bp of bridges[brname].ports)
|
||||
resolveVLANChain(bp, bridges, mapping);
|
||||
|
||||
for (var vid in bridges[brname].vlans)
|
||||
for (var i = 0; i < bridges[brname].vlans[vid].length; i++)
|
||||
resolveVLANChain(bridges[brname].vlans[vid][i], bridges, mapping);
|
||||
for (let vid in bridges[brname].vlans)
|
||||
for (let v of bridges[brname].vlans[vid])
|
||||
resolveVLANChain(v, bridges, mapping);
|
||||
}
|
||||
|
||||
/* find implicit VLAN devices */
|
||||
for (var i = 0, s; (s = interfaces[i]) != null; i++) {
|
||||
for (let i = 0, s; (s = interfaces[i]) != null; i++) {
|
||||
if (!isString(s.device))
|
||||
continue;
|
||||
|
||||
@@ -147,16 +147,16 @@ function buildVLANMappings(mapping)
|
||||
|
||||
function resolveVLANPorts(ifname, mapping, seen)
|
||||
{
|
||||
var ports = [];
|
||||
const ports = [];
|
||||
|
||||
if (!seen)
|
||||
seen = {};
|
||||
|
||||
if (mapping[ifname]) {
|
||||
for (var i = 0; i < mapping[ifname].length; i++) {
|
||||
if (!seen[mapping[ifname][i]]) {
|
||||
seen[mapping[ifname][i]] = true;
|
||||
ports.push.apply(ports, resolveVLANPorts(mapping[ifname][i], mapping, seen));
|
||||
for (let m of mapping[ifname]) {
|
||||
if (!seen[m]) {
|
||||
seen[m] = true;
|
||||
ports.push.apply(ports, resolveVLANPorts(m, mapping, seen));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,47 +168,47 @@ function resolveVLANPorts(ifname, mapping, seen)
|
||||
}
|
||||
|
||||
function buildInterfaceMapping(zones, networks) {
|
||||
var vlanmap = {},
|
||||
portmap = {},
|
||||
netmap = {};
|
||||
const vlanmap = {};
|
||||
const portmap = {};
|
||||
const netmap = {};
|
||||
|
||||
buildVLANMappings(vlanmap);
|
||||
|
||||
for (var i = 0; i < networks.length; i++) {
|
||||
var l3dev = networks[i].getDevice();
|
||||
for (let net of networks) {
|
||||
const l3dev = net.getDevice();
|
||||
|
||||
if (!l3dev)
|
||||
continue;
|
||||
|
||||
var ports = resolveVLANPorts(l3dev.getName(), vlanmap);
|
||||
const ports = resolveVLANPorts(l3dev.getName(), vlanmap);
|
||||
|
||||
for (var j = 0; j < ports.length; j++) {
|
||||
portmap[ports[j]] = portmap[ports[j]] || { networks: [], zones: [] };
|
||||
portmap[ports[j]].networks.push(networks[i]);
|
||||
for (let p of ports) {
|
||||
portmap[p] = portmap[p] || { networks: [], zones: [] };
|
||||
portmap[p].networks.push(net);
|
||||
}
|
||||
|
||||
netmap[networks[i].getName()] = networks[i];
|
||||
netmap[net.getName()] = net;
|
||||
}
|
||||
|
||||
for (var i = 0; i < zones.length; i++) {
|
||||
var networknames = zones[i].getNetworks();
|
||||
for (let z of zones) {
|
||||
const networknames = z.getNetworks();
|
||||
|
||||
for (var j = 0; j < networknames.length; j++) {
|
||||
if (!netmap[networknames[j]])
|
||||
for (let nn of networknames) {
|
||||
if (!netmap[nn])
|
||||
continue;
|
||||
|
||||
var l3dev = netmap[networknames[j]].getDevice();
|
||||
const l3dev = netmap[nn].getDevice();
|
||||
|
||||
if (!l3dev)
|
||||
continue;
|
||||
|
||||
var ports = resolveVLANPorts(l3dev.getName(), vlanmap);
|
||||
const ports = resolveVLANPorts(l3dev.getName(), vlanmap);
|
||||
|
||||
for (var k = 0; k < ports.length; k++) {
|
||||
portmap[ports[k]] = portmap[ports[k]] || { networks: [], zones: [] };
|
||||
for (let p of ports) {
|
||||
portmap[p] = portmap[p] || { networks: [], zones: [] };
|
||||
|
||||
if (portmap[ports[k]].zones.indexOf(zones[i]) === -1)
|
||||
portmap[ports[k]].zones.push(zones[i]);
|
||||
if (portmap[p].zones.indexOf(z) === -1)
|
||||
portmap[p].zones.push(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,8 +218,8 @@ function buildInterfaceMapping(zones, networks) {
|
||||
|
||||
function formatSpeed(carrier, speed, duplex) {
|
||||
if ((speed > 0) && duplex) {
|
||||
var d = (duplex == 'half') ? '\u202f(H)' : '',
|
||||
e = E('span', { 'title': _('Speed: %d Mbit/s, Duplex: %s').format(speed, duplex) });
|
||||
const d = (duplex == 'half') ? '\u202f(H)' : '';
|
||||
const e = E('span', { 'title': _('Speed: %d Mbit/s, Duplex: %s').format(speed, duplex) });
|
||||
|
||||
switch (true) {
|
||||
case (speed < 1000):
|
||||
@@ -325,8 +325,8 @@ function formatStats(portdev, pse) {
|
||||
}
|
||||
|
||||
function renderNetworkBadge(network, zonename) {
|
||||
var l3dev = network.getDevice();
|
||||
var span = E('span', { 'class': 'ifacebadge', 'style': 'margin:.125em 0' }, [
|
||||
const l3dev = network.getDevice();
|
||||
const span = E('span', { 'class': 'ifacebadge', 'style': 'margin:.125em 0' }, [
|
||||
E('span', {
|
||||
'class': 'zonebadge',
|
||||
'title': zonename ? _('Part of zone %q').format(zonename) : _('No zone assigned'),
|
||||
@@ -347,18 +347,18 @@ function renderNetworkBadge(network, zonename) {
|
||||
}
|
||||
|
||||
function renderNetworksTooltip(pmap) {
|
||||
var res = [ null ],
|
||||
zmap = {};
|
||||
const res = [ null ];
|
||||
const zmap = {};
|
||||
|
||||
for (var i = 0; pmap && i < pmap.zones.length; i++) {
|
||||
var networknames = pmap.zones[i].getNetworks();
|
||||
for (let pmz of pmap.zones) {
|
||||
const networknames = pmz.getNetworks();
|
||||
|
||||
for (var k = 0; k < networknames.length; k++)
|
||||
zmap[networknames[k]] = pmap.zones[i].getName();
|
||||
for (let nn of networknames)
|
||||
zmap[nn] = pmz.getName();
|
||||
}
|
||||
|
||||
for (var i = 0; pmap && i < pmap.networks.length; i++)
|
||||
res.push(E('br'), renderNetworkBadge(pmap.networks[i], zmap[pmap.networks[i].getName()]));
|
||||
for (let pmn of pmap.networks)
|
||||
res.push(E('br'), renderNetworkBadge(pmn, zmap[pmn.getName()]));
|
||||
|
||||
if (res.length > 1)
|
||||
res[0] = N_((res.length - 1) / 2, 'Part of network:', 'Part of networks:');
|
||||
@@ -371,7 +371,7 @@ function renderNetworksTooltip(pmap) {
|
||||
return baseclass.extend({
|
||||
title: _('Port status'),
|
||||
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
L.resolveDefault(callGetBuiltinEthernetPorts(), []),
|
||||
L.resolveDefault(fs.read('/etc/board.json'), '{}'),
|
||||
@@ -421,7 +421,7 @@ return baseclass.extend({
|
||||
});
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
render(data) {
|
||||
if (L.hasSystemFeature('swconfig'))
|
||||
return null;
|
||||
|
||||
@@ -438,7 +438,7 @@ return baseclass.extend({
|
||||
}
|
||||
else {
|
||||
if (L.isObject(board) && L.isObject(board.network)) {
|
||||
for (var k = 'lan'; k != null; k = (k == 'lan') ? 'wan' : null) {
|
||||
for (let k = 'lan'; k != null; k = (k == 'lan') ? 'wan' : null) {
|
||||
if (!L.isObject(board.network[k]))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -224,7 +224,6 @@ return baseclass.extend({
|
||||
},
|
||||
|
||||
render(data) {
|
||||
const seen = {};
|
||||
const radios = data[0];
|
||||
const networks = data[1];
|
||||
const hosthints = data[2];
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
'require fs';
|
||||
'require ui';
|
||||
|
||||
var table_names = [ 'Filter', 'NAT', 'Mangle', 'Raw' ],
|
||||
raw_style = 'font-family:monospace;font-size:smaller;text-align:right';
|
||||
const table_names = [ 'Filter', 'NAT', 'Mangle', 'Raw' ];
|
||||
const raw_style = 'font-family:monospace;font-size:smaller;text-align:right';
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return L.resolveDefault(fs.stat('/usr/sbin/ip6tables'));
|
||||
},
|
||||
|
||||
createTableSection: function(is_ipv6, table) {
|
||||
var idiv = document.querySelector('div[data-tab="%s"]'.format(is_ipv6 ? 'ip6tables' : 'iptables')),
|
||||
tdiv = idiv.querySelector('[data-table="%s-%s"]'.format(is_ipv6 ? 'ipv6' : 'ipv4', table)),
|
||||
title = '%s: %s'.format(_('Table'), table);
|
||||
createTableSection(is_ipv6, table) {
|
||||
const idiv = document.querySelector('div[data-tab="%s"]'.format(is_ipv6 ? 'ip6tables' : 'iptables'));
|
||||
let tdiv = idiv.querySelector('[data-table="%s-%s"]'.format(is_ipv6 ? 'ipv6' : 'ipv4', table));
|
||||
const title = '%s: %s'.format(_('Table'), table);
|
||||
|
||||
if (!tdiv) {
|
||||
tdiv = E('div', { 'data-table': '%s-%s'.format(is_ipv6 ? 'ipv6' : 'ipv4', table) }, [
|
||||
@@ -26,10 +26,10 @@ return view.extend({
|
||||
if (idiv.firstElementChild.nodeName.toLowerCase() === 'p')
|
||||
idiv.removeChild(idiv.firstElementChild);
|
||||
|
||||
var added = false, thisIdx = table_names.indexOf(table);
|
||||
let added = false, thisIdx = table_names.indexOf(table);
|
||||
|
||||
idiv.querySelectorAll('[data-table]').forEach(function(child) {
|
||||
var childIdx = table_names.indexOf(child.getAttribute('data-table').split(/-/)[1]);
|
||||
const childIdx = table_names.indexOf(child.getAttribute('data-table').split(/-/)[1]);
|
||||
|
||||
if (added === false && childIdx > thisIdx) {
|
||||
idiv.insertBefore(tdiv, child);
|
||||
@@ -44,10 +44,10 @@ return view.extend({
|
||||
return tdiv.lastElementChild;
|
||||
},
|
||||
|
||||
createChainSection: function(is_ipv6, table, chain, policy, packets, bytes, references) {
|
||||
var tdiv = this.createTableSection(is_ipv6, table),
|
||||
cdiv = tdiv.querySelector('[data-chain="%s"]'.format(chain)),
|
||||
title;
|
||||
createChainSection(is_ipv6, table, chain, policy, packets, bytes, references) {
|
||||
const tdiv = this.createTableSection(is_ipv6, table);
|
||||
let cdiv = tdiv.querySelector('[data-chain="%s"]'.format(chain));
|
||||
let title;
|
||||
|
||||
if (policy)
|
||||
title = '%s <em>%s</em> <span>(%s: <em>%s</em>, %d %s, %.2mB %s)</span>'
|
||||
@@ -84,14 +84,13 @@ return view.extend({
|
||||
return cdiv.lastElementChild;
|
||||
},
|
||||
|
||||
updateChainSection: function(chaintable, rows) {
|
||||
updateChainSection(chaintable, rows) {
|
||||
if (!chaintable)
|
||||
return;
|
||||
|
||||
cbi_update_table(chaintable, rows, _('No rules in this chain.'));
|
||||
|
||||
if (rows.length === 0 &&
|
||||
document.querySelector('[data-hide-empty="true"]'))
|
||||
if (rows.length === 0 && document.querySelector('[data-hide-empty="true"]'))
|
||||
chaintable.parentNode.style.display = 'none';
|
||||
else
|
||||
chaintable.parentNode.style.display = '';
|
||||
@@ -99,21 +98,21 @@ return view.extend({
|
||||
chaintable.parentNode.setAttribute('data-empty', rows.length === 0);
|
||||
},
|
||||
|
||||
parseIptablesDump: function(is_ipv6, table, s) {
|
||||
var current_chain = null;
|
||||
var current_rules = [];
|
||||
var seen_chains = {};
|
||||
var chain_refs = {};
|
||||
var re = /([^\n]*)\n/g;
|
||||
var m, m2;
|
||||
var raw = document.querySelector('[data-raw-counters="true"]');
|
||||
parseIptablesDump(is_ipv6, table, s) {
|
||||
let current_chain = null;
|
||||
let current_rules = [];
|
||||
const seen_chains = {};
|
||||
const chain_refs = {};
|
||||
const re = /([^\n]*)\n/g;
|
||||
let m, m2;
|
||||
const raw = document.querySelector('[data-raw-counters="true"]');
|
||||
|
||||
while ((m = re.exec(s)) != null) {
|
||||
if (m[1].match(/^Chain (.+) \(policy (\w+) (\d+) packets, (\d+) bytes\)$/)) {
|
||||
var chain = RegExp.$1,
|
||||
policy = RegExp.$2,
|
||||
packets = +RegExp.$3,
|
||||
bytes = +RegExp.$4;
|
||||
const chain = RegExp.$1;
|
||||
const policy = RegExp.$2;
|
||||
const packets = +RegExp.$3;
|
||||
const bytes = +RegExp.$4;
|
||||
|
||||
this.updateChainSection(current_chain, current_rules);
|
||||
|
||||
@@ -122,8 +121,8 @@ return view.extend({
|
||||
current_rules = [];
|
||||
}
|
||||
else if (m[1].match(/^Chain (.+) \((\d+) references\)$/)) {
|
||||
var chain = RegExp.$1,
|
||||
references = +RegExp.$2;
|
||||
const chain = RegExp.$1;
|
||||
const references = +RegExp.$2;
|
||||
|
||||
this.updateChainSection(current_chain, current_rules);
|
||||
|
||||
@@ -135,17 +134,17 @@ return view.extend({
|
||||
continue;
|
||||
}
|
||||
else if ((m2 = m[1].match(/^(\d+) +(\d+) +(\d+) +(.*?) +(\S+) +(\S*) +(\S+) +(\S+) +(!?[a-f0-9:.]+(?:\/[a-f0-9:.]+)?) +(!?[a-f0-9:.]+(?:\/[a-f0-9:.]+)?) +(.+)$/)) !== null) {
|
||||
var num = +m2[1],
|
||||
pkts = +m2[2],
|
||||
bytes = +m2[3],
|
||||
target = m2[4],
|
||||
proto = m2[5],
|
||||
indev = m2[7],
|
||||
outdev = m2[8],
|
||||
srcnet = m2[9],
|
||||
dstnet = m2[10],
|
||||
options = m2[11] || '-',
|
||||
comment = '-';
|
||||
const num = +m2[1];
|
||||
const pkts = +m2[2];
|
||||
const bytes = +m2[3];
|
||||
const target = m2[4];
|
||||
const proto = m2[5];
|
||||
const indev = m2[7];
|
||||
const outdev = m2[8];
|
||||
const srcnet = m2[9];
|
||||
const dstnet = m2[10];
|
||||
let options = m2[11] || '-';
|
||||
let comment = '-';
|
||||
|
||||
options = options.trim().replace(/(?:^| )\/\* (.+) \*\//,
|
||||
function(m1, m2) {
|
||||
@@ -199,14 +198,14 @@ return view.extend({
|
||||
}, this));
|
||||
|
||||
cdiv.querySelectorAll('.references').forEach(L.bind(function(rspan) {
|
||||
var refs = chain_refs[cdiv.getAttribute('data-chain')];
|
||||
const refs = chain_refs[cdiv.getAttribute('data-chain')];
|
||||
if (refs && refs.length) {
|
||||
rspan.classList.add('cbi-tooltip-container');
|
||||
rspan.appendChild(E('small', { 'class': 'cbi-tooltip ifacebadge', 'style': 'top:1em; left:auto' }, [ E('ul') ]));
|
||||
|
||||
refs.forEach(L.bind(function(ref) {
|
||||
var chain = ref[0].parentNode.getAttribute('data-chain'),
|
||||
num = ref[1];
|
||||
const chain = ref[0].parentNode.getAttribute('data-chain');
|
||||
const num = ref[1];
|
||||
|
||||
rspan.lastElementChild.lastElementChild.appendChild(E('li', {}, [
|
||||
_('Chain'), ' ',
|
||||
@@ -223,20 +222,20 @@ return view.extend({
|
||||
}, this));
|
||||
},
|
||||
|
||||
pollFirewallLists: function(has_ip6tables) {
|
||||
var cmds = [ '/usr/sbin/iptables' ];
|
||||
pollFirewallLists(has_ip6tables) {
|
||||
const cmds = [ '/usr/sbin/iptables' ];
|
||||
|
||||
if (has_ip6tables)
|
||||
cmds.push('/usr/sbin/ip6tables');
|
||||
|
||||
poll.add(L.bind(function() {
|
||||
var tasks = [];
|
||||
const tasks = [];
|
||||
|
||||
for (var i = 0; i < cmds.length; i++) {
|
||||
for (var j = 0; j < table_names.length; j++) {
|
||||
for (let i = 0; i < cmds.length; i++) {
|
||||
for (let tn of table_names) {
|
||||
tasks.push(L.resolveDefault(
|
||||
fs.exec_direct(cmds[i], [ '--line-numbers', '-w', '-nvxL', '-t', table_names[j].toLowerCase() ])
|
||||
.then(this.parseIptablesDump.bind(this, i > 0, table_names[j]))));
|
||||
fs.exec_direct(cmds[i], [ '--line-numbers', '-w', '-nvxL', '-t', tn.toLowerCase() ])
|
||||
.then(this.parseIptablesDump.bind(this, i > 0, tn))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,12 +243,12 @@ return view.extend({
|
||||
}, this));
|
||||
},
|
||||
|
||||
handleJumpTarget: function(ev) {
|
||||
var link = ev.target,
|
||||
table = findParent(link, '[data-table]').getAttribute('data-table'),
|
||||
chain = link.textContent,
|
||||
num = +link.getAttribute('data-num'),
|
||||
elem = document.getElementById('rule_%s_%s'.format(table.toLowerCase(), chain));
|
||||
handleJumpTarget(ev) {
|
||||
const link = ev.target;
|
||||
const table = findParent(link, '[data-table]').getAttribute('data-table');
|
||||
const chain = link.textContent;
|
||||
const num = +link.getAttribute('data-num');
|
||||
const elem = document.getElementById('rule_%s_%s'.format(table.toLowerCase(), chain));
|
||||
|
||||
if (elem) {
|
||||
if (elem.scrollIntoView) {
|
||||
@@ -262,7 +261,7 @@ return view.extend({
|
||||
elem.classList.add('flash');
|
||||
|
||||
if (num) {
|
||||
var rule = elem.nextElementSibling.childNodes[num];
|
||||
const rule = elem.nextElementSibling.childNodes[num];
|
||||
if (rule) {
|
||||
rule.classList.remove('flash');
|
||||
void rule.offsetWidth;
|
||||
@@ -272,9 +271,9 @@ return view.extend({
|
||||
}
|
||||
},
|
||||
|
||||
handleRawCounters: function(ev) {
|
||||
var btn = ev.currentTarget,
|
||||
raw = (btn.getAttribute('data-raw-counters') === 'false');
|
||||
handleRawCounters(ev) {
|
||||
const btn = ev.currentTarget;
|
||||
const raw = (btn.getAttribute('data-raw-counters') === 'false');
|
||||
|
||||
btn.setAttribute('data-raw-counters', raw);
|
||||
btn.firstChild.data = raw ? _('Human-readable counters') : _('Show raw counters');
|
||||
@@ -282,16 +281,16 @@ return view.extend({
|
||||
|
||||
document.querySelectorAll('[data-value]')
|
||||
.forEach(function(div) {
|
||||
var fmt = raw ? '%d' : div.getAttribute('data-format');
|
||||
const fmt = raw ? '%d' : div.getAttribute('data-format');
|
||||
|
||||
div.style = raw ? raw_style : '';
|
||||
div.innerText = fmt.format(div.getAttribute('data-value'));
|
||||
});
|
||||
},
|
||||
|
||||
handleHideEmpty: function(ev) {
|
||||
var btn = ev.currentTarget,
|
||||
hide = (btn.getAttribute('data-hide-empty') === 'false');
|
||||
handleHideEmpty(ev) {
|
||||
const btn = ev.currentTarget;
|
||||
const hide = (btn.getAttribute('data-hide-empty') === 'false');
|
||||
|
||||
btn.setAttribute('data-hide-empty', hide);
|
||||
btn.firstChild.data = hide ? _('Show empty chains') : _('Hide empty chains');
|
||||
@@ -303,7 +302,7 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
handleCounterReset: function(has_ip6tables, ev) {
|
||||
handleCounterReset(has_ip6tables, ev) {
|
||||
return Promise.all([
|
||||
fs.exec('/usr/sbin/iptables', [ '-Z' ])
|
||||
.catch(function(err) { ui.addNotification(null, E('p', {}, _('Unable to reset iptables counters: %s').format(err.message))) }),
|
||||
@@ -312,13 +311,13 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
handleRestart: function(ev) {
|
||||
handleRestart(ev) {
|
||||
return fs.exec_direct('/etc/init.d/firewall', [ 'restart' ])
|
||||
.catch(function(err) { ui.addNotification(null, E('p', {}, _('Unable to restart firewall: %s').format(err.message))) });
|
||||
},
|
||||
|
||||
render: function(has_ip6tables) {
|
||||
var view = E([], [
|
||||
render(has_ip6tables) {
|
||||
const view = E([], [
|
||||
E('style', { 'type': 'text/css' }, [
|
||||
'.cbi-tooltip-container, span.jump { border-bottom:1px dotted #00f;cursor:pointer }',
|
||||
'ul { list-style:none }',
|
||||
|
||||
@@ -4,68 +4,67 @@
|
||||
'require request';
|
||||
'require rpc';
|
||||
|
||||
var callLuciRealtimeStats = rpc.declare({
|
||||
const callLuciRealtimeStats = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getRealtimeStats',
|
||||
params: [ 'mode', 'device' ],
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
var graphPolls = [],
|
||||
pollInterval = 3;
|
||||
const graphPolls = [];
|
||||
const pollInterval = 3;
|
||||
|
||||
Math.log2 = Math.log2 || function(x) { return Math.log(x) * Math.LOG2E; };
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
this.loadSVG(L.resource('svg/load.svg'))
|
||||
]);
|
||||
},
|
||||
|
||||
updateGraph: function(svg, lines, cb) {
|
||||
var G = svg.firstElementChild;
|
||||
updateGraph(svg, lines, cb) {
|
||||
const G = svg.firstElementChild;
|
||||
|
||||
var view = document.querySelector('#view');
|
||||
const view = document.querySelector('#view');
|
||||
|
||||
var width = view.offsetWidth - 2;
|
||||
var height = 300 - 2;
|
||||
var step = 5;
|
||||
const width = view.offsetWidth - 2;
|
||||
const height = 300 - 2;
|
||||
const step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
const data_wanted = Math.floor(width / step);
|
||||
|
||||
var data_values = [],
|
||||
line_elements = [];
|
||||
const data_values = [];
|
||||
|
||||
for (var i = 0; i < lines.length; i++)
|
||||
if (lines[i] != null)
|
||||
for (let line of lines)
|
||||
if (line != null)
|
||||
data_values.push([]);
|
||||
|
||||
var info = {
|
||||
const info = {
|
||||
line_current: [],
|
||||
line_average: [],
|
||||
line_peak: []
|
||||
};
|
||||
|
||||
/* prefill datasets */
|
||||
for (var i = 0; i < data_values.length; i++)
|
||||
for (var j = 0; j < data_wanted; j++)
|
||||
data_values[i][j] = 0;
|
||||
for (let dv of data_values)
|
||||
for (let j = 0; j < data_wanted; j++)
|
||||
dv[j] = 0;
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (step * 60); i < width; i += step * 60) {
|
||||
var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', i);
|
||||
line.setAttribute('y1', 0);
|
||||
line.setAttribute('x2', i);
|
||||
line.setAttribute('y2', '100%');
|
||||
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
for (let i = width % (step * 60); i < width; i += step * 60) {
|
||||
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', i);
|
||||
line.setAttribute('y1', 0);
|
||||
line.setAttribute('x2', i);
|
||||
line.setAttribute('y2', '100%');
|
||||
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
|
||||
var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text.setAttribute('x', i + 5);
|
||||
text.setAttribute('y', 15);
|
||||
text.setAttribute('style', 'fill:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
text.appendChild(document.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text.setAttribute('x', i + 5);
|
||||
text.setAttribute('y', 15);
|
||||
text.setAttribute('style', 'fill:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
text.appendChild(document.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
|
||||
G.appendChild(line);
|
||||
G.appendChild(text);
|
||||
@@ -88,35 +87,34 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
pollData: function() {
|
||||
pollData() {
|
||||
poll.add(L.bind(function() {
|
||||
var tasks = [];
|
||||
const tasks = [];
|
||||
|
||||
for (var i = 0; i < graphPolls.length; i++) {
|
||||
var ctx = graphPolls[i];
|
||||
graphPolls.forEach(() => {
|
||||
tasks.push(L.resolveDefault(callLuciRealtimeStats('load'), []));
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all(tasks).then(L.bind(function(datasets) {
|
||||
for (var gi = 0; gi < graphPolls.length; gi++) {
|
||||
var ctx = graphPolls[gi],
|
||||
data = datasets[gi],
|
||||
values = ctx.values,
|
||||
lines = ctx.lines,
|
||||
info = ctx.info;
|
||||
for (let gi = 0; gi < graphPolls.length; gi++) {
|
||||
const ctx = graphPolls[gi];
|
||||
const data = datasets[gi];
|
||||
const values = ctx.values;
|
||||
const lines = ctx.lines;
|
||||
const info = ctx.info;
|
||||
|
||||
var data_scale = 0;
|
||||
var data_wanted = Math.floor(ctx.width / ctx.step);
|
||||
var last_timestamp = NaN;
|
||||
let data_scale = 0;
|
||||
let data_wanted = Math.floor(ctx.width / ctx.step);
|
||||
let last_timestamp = NaN;
|
||||
|
||||
for (var i = 0, di = 0; di < lines.length; di++) {
|
||||
for (let i = 0, di = 0; di < lines.length; di++) {
|
||||
if (lines[di] == null)
|
||||
continue;
|
||||
|
||||
var multiply = (lines[di].multiply != null) ? lines[di].multiply : 1,
|
||||
offset = (lines[di].offset != null) ? lines[di].offset : 0;
|
||||
const multiply = (lines[di].multiply != null) ? lines[di].multiply : 1;
|
||||
const offset = (lines[di].offset != null) ? lines[di].offset : 0;
|
||||
|
||||
for (var j = ctx.timestamp ? 0 : 1; j < data.length; j++) {
|
||||
for (let j = ctx.timestamp ? 0 : 1; j < data.length; j++) {
|
||||
/* skip overlapping entries */
|
||||
if (data[j][0] <= ctx.timestamp)
|
||||
continue;
|
||||
@@ -137,15 +135,15 @@ return view.extend({
|
||||
/* cut off outdated entries */
|
||||
ctx.fill = Math.min(ctx.fill, data_wanted);
|
||||
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var len = values[i].length;
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
const len = values[i].length;
|
||||
values[i] = values[i].slice(len - data_wanted, len);
|
||||
|
||||
/* find peaks, averages */
|
||||
info.line_peak[i] = NaN;
|
||||
info.line_average[i] = 0;
|
||||
|
||||
for (var j = 0; j < values[i].length; j++) {
|
||||
for (let j = 0; j < values[i].length; j++) {
|
||||
info.line_peak[i] = isNaN(info.line_peak[i]) ? values[i][j] : Math.max(info.line_peak[i], values[i][j]);
|
||||
info.line_average[i] += values[i][j];
|
||||
}
|
||||
@@ -159,29 +157,29 @@ return view.extend({
|
||||
if (!isNaN(last_timestamp))
|
||||
ctx.timestamp = last_timestamp;
|
||||
|
||||
var size = Math.floor(Math.log2(info.peak)),
|
||||
div = Math.pow(2, size - (size % 10)),
|
||||
mult = info.peak / div,
|
||||
mult = (mult < 5) ? 2 : ((mult < 50) ? 10 : ((mult < 500) ? 100 : 1000));
|
||||
const size = Math.floor(Math.log2(info.peak));
|
||||
const div = Math.pow(2, size - (size % 10));
|
||||
let mult = info.peak / div;
|
||||
mult = (mult < 5) ? 2 : ((mult < 50) ? 10 : ((mult < 500) ? 100 : 1000));
|
||||
|
||||
info.peak = info.peak + (mult * div) - (info.peak % (mult * div));
|
||||
|
||||
data_scale = ctx.height / info.peak;
|
||||
|
||||
/* plot data */
|
||||
for (var i = 0, di = 0; di < lines.length; di++) {
|
||||
for (let i = 0, di = 0; di < lines.length; di++) {
|
||||
if (lines[di] == null)
|
||||
continue;
|
||||
|
||||
var el = ctx.svg.firstElementChild.getElementById(lines[di].line),
|
||||
pt = '0,' + ctx.height,
|
||||
y = 0;
|
||||
const el = ctx.svg.firstElementChild.getElementById(lines[di].line);
|
||||
let pt = '0,' + ctx.height;
|
||||
let y = 0;
|
||||
|
||||
if (!el)
|
||||
continue;
|
||||
|
||||
for (var j = 0; j < values[i].length; j++) {
|
||||
var x = j * ctx.step;
|
||||
for (let j = 0; j < values[i].length; j++) {
|
||||
let x = j * ctx.step;
|
||||
|
||||
y = ctx.height - Math.floor(values[i][j] * data_scale);
|
||||
//y -= Math.floor(y % (1 / data_scale));
|
||||
@@ -209,7 +207,7 @@ return view.extend({
|
||||
}, this), pollInterval);
|
||||
},
|
||||
|
||||
loadSVG: function(src) {
|
||||
loadSVG(src) {
|
||||
return request.get(src).then(function(response) {
|
||||
if (!response.ok)
|
||||
throw new Error(response.statusText);
|
||||
@@ -220,10 +218,8 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var svg = data[0];
|
||||
|
||||
var v = E('div', { 'class': 'cbi-map', 'id': 'map' }, [
|
||||
render([svg]) {
|
||||
const v = E('div', { 'class': 'cbi-map', 'id': 'map' }, [
|
||||
E('h2', _('System load')),
|
||||
E('div', {'class': 'cbi-map-descr'}, _('Load Average is a metric that is used by Linux to keep track of system resources.')),
|
||||
E('div', { 'class': 'cbi-section' }, [
|
||||
@@ -267,7 +263,7 @@ return view.extend({
|
||||
]);
|
||||
|
||||
this.updateGraph(svg, [ { line: 'load01' }, { line: 'load05' }, { line: 'load15' } ], function(svg, info) {
|
||||
var G = svg.firstElementChild, tab = svg.parentNode;
|
||||
const G = svg.firstElementChild, tab = svg.parentNode;
|
||||
|
||||
G.getElementById('label_25').firstChild.data = '%.2f'.format(info.label_25 / 100);
|
||||
G.getElementById('label_50').firstChild.data = '%.2f'.format(info.label_50 / 100);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
'require ui';
|
||||
'require dom';
|
||||
|
||||
var expr_translations = {
|
||||
const expr_translations = {
|
||||
'meta.iifname': _('Ingress device name', 'nft meta iifname'),
|
||||
'meta.oifname': _('Egress device name', 'nft meta oifname'),
|
||||
'meta.iif': _('Ingress device id', 'nft meta iif'),
|
||||
@@ -85,7 +85,7 @@ var expr_translations = {
|
||||
'payload.th': _('Transport header bits %d-%d', 'nft @th,off,len')
|
||||
};
|
||||
|
||||
var op_translations = {
|
||||
const op_translations = {
|
||||
'==': _('<var>%s</var> is <strong>%s</strong>', 'nft relational "==" operator expression'),
|
||||
'!=': _('<var>%s</var> not <strong>%s</strong>', 'nft relational "!=" operator expression'),
|
||||
'>=': _('<var>%s</var> greater than or equal to <strong>%s</strong>', 'nft relational ">=" operator expression'),
|
||||
@@ -97,7 +97,7 @@ var op_translations = {
|
||||
'not_in_set': _('<var>%s</var> not in set <strong>%s</strong>', 'nft not in set match expression'),
|
||||
};
|
||||
|
||||
var action_translations = {
|
||||
const action_translations = {
|
||||
'accept': _('Accept packet', 'nft accept action'),
|
||||
'notrack': _('Do not track', 'nft notrack action'),
|
||||
'drop': _('Drop packet', 'nft drop action'),
|
||||
@@ -143,24 +143,24 @@ var action_translations = {
|
||||
};
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
L.resolveDefault(fs.exec_direct('/usr/sbin/nft', [ '--terse', '--json', 'list', 'ruleset' ], 'json'), {}),
|
||||
fs.stat('/usr/sbin/iptables-legacy-save').then(function(stat) {
|
||||
fs.stat('/usr/sbin/iptables-legacy-save').then(function() {
|
||||
return L.resolveDefault(fs.exec_direct('/usr/sbin/iptables-legacy-save'), '');
|
||||
}).catch(function(err) {
|
||||
}).catch(function() {
|
||||
return L.resolveDefault(fs.exec_direct('/usr/sbin/iptables-save'), '');
|
||||
}),
|
||||
fs.stat('/usr/sbin/ip6tables-legacy-save').then(function(stat) {
|
||||
fs.stat('/usr/sbin/ip6tables-legacy-save').then(function() {
|
||||
return L.resolveDefault(fs.exec_direct('/usr/sbin/ip6tables-legacy-save'), '');
|
||||
}).catch(function(err) {
|
||||
}).catch(function() {
|
||||
return L.resolveDefault(fs.exec_direct('/usr/sbin/ip6tables-save'), '');
|
||||
})
|
||||
]);
|
||||
},
|
||||
|
||||
isActionExpression: function(expr) {
|
||||
for (var k in expr) {
|
||||
isActionExpression(expr) {
|
||||
for (let k in expr) {
|
||||
if (expr.hasOwnProperty(k)) {
|
||||
switch (k) {
|
||||
case 'accept':
|
||||
@@ -187,11 +187,11 @@ return view.extend({
|
||||
return false;
|
||||
},
|
||||
|
||||
exprToKey: function(expr) {
|
||||
var kind, spec;
|
||||
exprToKey(expr) {
|
||||
let kind, spec;
|
||||
|
||||
if (!Array.isArray(expr) && typeof(expr) == 'object') {
|
||||
for (var k in expr) {
|
||||
for (let k in expr) {
|
||||
if (expr.hasOwnProperty(k)) {
|
||||
kind = k;
|
||||
spec = expr[k];
|
||||
@@ -216,11 +216,11 @@ return view.extend({
|
||||
return null;
|
||||
},
|
||||
|
||||
exprToString: function(expr, hint) {
|
||||
var kind, spec;
|
||||
exprToString(expr, hint) {
|
||||
let kind, spec;
|
||||
|
||||
if (typeof(expr) != 'object') {
|
||||
var s;
|
||||
let s;
|
||||
|
||||
if (hint)
|
||||
s = expr_translations['%s.%h'.format(hint, expr)];
|
||||
@@ -233,7 +233,7 @@ return view.extend({
|
||||
spec = expr;
|
||||
}
|
||||
else {
|
||||
for (var k in expr) {
|
||||
for (let k in expr) {
|
||||
if (expr.hasOwnProperty(k)) {
|
||||
kind = k;
|
||||
spec = expr[k];
|
||||
@@ -244,21 +244,21 @@ return view.extend({
|
||||
if (!kind)
|
||||
return '';
|
||||
|
||||
const items = [];
|
||||
const lis = [];
|
||||
let tpl, k;
|
||||
|
||||
switch (kind) {
|
||||
case 'prefix':
|
||||
return '%h/%d'.format(spec.addr, spec.len);
|
||||
|
||||
case 'set':
|
||||
case 'list':
|
||||
var items = [],
|
||||
lis = [];
|
||||
|
||||
for (var i = 0; i < spec.length; i++) {
|
||||
items.push('<span class="nft-set-item">%s</span>'.format(this.exprToString(spec[i])));
|
||||
lis.push('<span class="ifacebadge">%s</span>'.format(this.exprToString(spec[i])));
|
||||
}
|
||||
|
||||
var tpl;
|
||||
|
||||
if (kind == 'set')
|
||||
tpl = '<div class="nft-set cbi-tooltip-container">{ <span class="nft-set-items">%s</span> }<div class="cbi-tooltip">%s</div></div>';
|
||||
@@ -268,10 +268,9 @@ return view.extend({
|
||||
return tpl.format(items.join(', '), lis.join('<br />'));
|
||||
|
||||
case 'concat':
|
||||
var items = [];
|
||||
|
||||
for (var i = 0; i < spec.length; i++)
|
||||
items.push(this.exprToString(spec[i]));
|
||||
for (let s of spec)
|
||||
items.push(this.exprToString(s));
|
||||
|
||||
return items.join('+');
|
||||
|
||||
@@ -280,11 +279,11 @@ return view.extend({
|
||||
|
||||
case 'payload':
|
||||
if (spec.protocol && spec.field) {
|
||||
var k = '%h.%h'.format(spec.protocol, spec.field);
|
||||
k = '%h.%h'.format(spec.protocol, spec.field);
|
||||
return expr_translations[k] || '<em>%s</em>'.format(k);
|
||||
}
|
||||
else if (spec.base && spec.offset != null && spec.len != null) {
|
||||
var k = 'payload.%h'.format(spec.base);
|
||||
k = 'payload.%h'.format(spec.base);
|
||||
return (expr_translations[k] || '<em>@%s,%%d,%%d</em>'.format(spec.base)).format(spec.offset + 1, spec.offset + spec.len + 1);
|
||||
}
|
||||
|
||||
@@ -299,7 +298,7 @@ return view.extend({
|
||||
Array.isArray(spec[1]) ? '(%h)'.format(spec[1].join('|')) : this.exprToString(spec[1], hint));
|
||||
|
||||
default:
|
||||
var k = this.exprToKey(expr);
|
||||
k = this.exprToKey(expr);
|
||||
|
||||
if (k)
|
||||
return expr_translations[k] || '<em>%s</em>'.format(k);
|
||||
@@ -308,7 +307,7 @@ return view.extend({
|
||||
}
|
||||
},
|
||||
|
||||
renderVMap: function(spec, table) {
|
||||
renderVMap(spec, table) {
|
||||
// spec: { key: {...}, data: { set: [ [mapkey, actionSpec], ... ] } }
|
||||
const matchElem = E('span', { 'class': 'ifacebadge' },
|
||||
_('Verdict map: <var>%h</var> is').format(this.exprToString(spec.key)));
|
||||
@@ -349,7 +348,7 @@ return view.extend({
|
||||
return { match: matchElem, actions: actions };
|
||||
},
|
||||
|
||||
renderMatchExpr: function(spec) {
|
||||
renderMatchExpr(spec) {
|
||||
switch (spec.op) {
|
||||
case '==':
|
||||
case '!=':
|
||||
@@ -374,12 +373,12 @@ return view.extend({
|
||||
);
|
||||
},
|
||||
|
||||
renderNatFlags: function(spec) {
|
||||
var f = [];
|
||||
renderNatFlags(spec) {
|
||||
const f = [];
|
||||
|
||||
if (spec && Array.isArray(spec.flags)) {
|
||||
for (var i = 0; i < spec.flags.length; i++)
|
||||
f.push(expr_translations['natflag.%h'.format(spec.flags[i])] || spec.flags[i]);
|
||||
for (let sf of spec.flags)
|
||||
f.push(expr_translations['natflag.%h'.format(sf)] || sf);
|
||||
}
|
||||
|
||||
return f.length ? E('small', { 'class': 'cbi-tooltip-container' }, [
|
||||
@@ -390,7 +389,7 @@ return view.extend({
|
||||
]) : E([]);
|
||||
},
|
||||
|
||||
renderRateUnit: function(value, unit) {
|
||||
renderRateUnit(value, unit) {
|
||||
if (!unit)
|
||||
unit = 'packets';
|
||||
|
||||
@@ -400,10 +399,10 @@ return view.extend({
|
||||
);
|
||||
},
|
||||
|
||||
renderExpr: function(expr, table) {
|
||||
var kind, spec;
|
||||
renderExpr(expr, table) {
|
||||
let kind, spec;
|
||||
|
||||
for (var k in expr) {
|
||||
for (let k in expr) {
|
||||
if (expr.hasOwnProperty(k)) {
|
||||
kind = k;
|
||||
spec = expr[k];
|
||||
@@ -413,6 +412,9 @@ return view.extend({
|
||||
if (!kind)
|
||||
return E([]);
|
||||
|
||||
let k;
|
||||
let a = [];
|
||||
|
||||
switch (kind) {
|
||||
case 'match':
|
||||
return this.renderMatchExpr(spec);
|
||||
@@ -423,7 +425,7 @@ return view.extend({
|
||||
}, action_translations[kind].format(spec));
|
||||
|
||||
case 'reject':
|
||||
var k = 'reject.%s'.format(spec.type);
|
||||
k = 'reject.%s'.format(spec.type);
|
||||
|
||||
return E('span', {
|
||||
'class': 'ifacebadge'
|
||||
@@ -458,8 +460,7 @@ return view.extend({
|
||||
|
||||
case 'snat':
|
||||
case 'dnat':
|
||||
var k = '%h.%h'.format(kind, spec.family),
|
||||
a = [];
|
||||
k = '%h.%h'.format(kind, spec.family);
|
||||
|
||||
if (spec.addr) {
|
||||
k += '.addr';
|
||||
@@ -477,8 +478,7 @@ return view.extend({
|
||||
]);
|
||||
|
||||
case 'redirect':
|
||||
var k = 'redirect',
|
||||
a = [];
|
||||
k = 'redirect';
|
||||
|
||||
if (spec && spec.port) {
|
||||
k += '.port';
|
||||
@@ -504,8 +504,8 @@ return view.extend({
|
||||
));
|
||||
|
||||
case 'limit':
|
||||
var k = 'limit';
|
||||
var a = [
|
||||
k = 'limit';
|
||||
a = [
|
||||
this.renderRateUnit(spec.rate, spec.rate_unit),
|
||||
expr_translations['unit.%h'.format(spec.per)] || spec.per
|
||||
];
|
||||
@@ -541,7 +541,7 @@ return view.extend({
|
||||
}
|
||||
},
|
||||
|
||||
renderCounter: function(data) {
|
||||
renderCounter(data) {
|
||||
return E('span', { 'class': 'ifacebadge cbi-tooltip-container nft-counter' }, [
|
||||
E('var', [ '%.1024mB'.format(data.bytes) ]),
|
||||
E('div', { 'class': 'cbi-tooltip' }, [
|
||||
@@ -550,7 +550,7 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
renderComment: function(comment) {
|
||||
renderComment(comment) {
|
||||
return E('span', { 'class': 'ifacebadge cbi-tooltip-container nft-comment' }, [
|
||||
E('var', [ '#' ]),
|
||||
E('div', { 'class': 'cbi-tooltip' }, [
|
||||
@@ -559,47 +559,47 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
renderRule: function(data, spec) {
|
||||
var empty = true;
|
||||
renderRule(data, spec) {
|
||||
let empty = true;
|
||||
|
||||
var row = E('tr', { 'class': 'tr' }, [
|
||||
const row = E('tr', { 'class': 'tr' }, [
|
||||
E('td', { 'class': 'td', 'style': 'width:60%' }),
|
||||
E('td', { 'class': 'td', 'style': 'width:40%' })
|
||||
]);
|
||||
|
||||
if (Array.isArray(spec.expr)) {
|
||||
for (var i = 0; i < spec.expr.length; i++) {
|
||||
for (let se of spec.expr) {
|
||||
// nftables JSON format bug, `flow` targets are currently not properly serialized
|
||||
if (typeof(spec.expr[i]) == 'string' && spec.expr[i].match(/^flow add (@\S+)$/))
|
||||
spec.expr[i] = { flow: { op: "add", flowtable: RegExp.$1 } };
|
||||
if (typeof(se) == 'string' && se.match(/^flow add (@\S+)$/))
|
||||
se = { flow: { op: "add", flowtable: RegExp.$1 } };
|
||||
|
||||
// vmap special handling
|
||||
if (spec.expr[i] && spec.expr[i].vmap) {
|
||||
var vm = this.renderVMap(spec.expr[i].vmap, spec.table);
|
||||
if (se && se.vmap) {
|
||||
const vm = this.renderVMap(se.vmap, spec.table);
|
||||
|
||||
// add match summary to left column
|
||||
dom.append(row.childNodes[0], [ vm.match ]);
|
||||
empty = false;
|
||||
|
||||
if (typeof(spec.expr[i]) == 'object' && spec.expr[i].counter) {
|
||||
if (typeof(se) == 'object' && se.counter) {
|
||||
row.childNodes[0].appendChild(
|
||||
this.renderCounter(spec.expr[i].counter));
|
||||
this.renderCounter(se.counter));
|
||||
}
|
||||
|
||||
// append each mapped action to the actions column
|
||||
for (var ai = 0; ai < vm.actions.length; ai++)
|
||||
dom.append(row.childNodes[1], [ vm.actions[ai] ]);
|
||||
for (let vma of vm.actions)
|
||||
dom.append(row.childNodes[1], [ vma ]);
|
||||
continue;
|
||||
}
|
||||
|
||||
var res = this.renderExpr(spec.expr[i], spec.table);
|
||||
const res = this.renderExpr(se, spec.table);
|
||||
|
||||
if (typeof(spec.expr[i]) == 'object' && spec.expr[i].counter) {
|
||||
if (typeof(se) == 'object' && se.counter) {
|
||||
row.childNodes[0].insertBefore(
|
||||
this.renderCounter(spec.expr[i].counter),
|
||||
this.renderCounter(se.counter),
|
||||
row.childNodes[0].firstChild);
|
||||
}
|
||||
else if (this.isActionExpression(spec.expr[i])) {
|
||||
else if (this.isActionExpression(se)) {
|
||||
dom.append(row.childNodes[1], [ res ]);
|
||||
}
|
||||
else {
|
||||
@@ -621,8 +621,8 @@ return view.extend({
|
||||
return row;
|
||||
},
|
||||
|
||||
renderChain: function(data, spec) {
|
||||
var title, policy, hook;
|
||||
renderChain(data, spec) {
|
||||
let title, policy, hook;
|
||||
|
||||
switch (spec.type) {
|
||||
case 'filter':
|
||||
@@ -682,7 +682,7 @@ return view.extend({
|
||||
break;
|
||||
}
|
||||
|
||||
var node = E('div', { 'class': 'nft-chain' }, [
|
||||
const node = E('div', { 'class': 'nft-chain' }, [
|
||||
E('h4', {
|
||||
'id': '%h.%h'.format(spec.table, spec.name)
|
||||
}, [ title ])
|
||||
@@ -704,9 +704,9 @@ return view.extend({
|
||||
])
|
||||
]));
|
||||
|
||||
for (var i = 0; i < data.length; i++)
|
||||
if (typeof(data[i].rule) == 'object' && data[i].rule.table == spec.table && data[i].rule.chain == spec.name && data[i].rule.family == spec.family)
|
||||
node.lastElementChild.appendChild(this.renderRule(data, data[i].rule));
|
||||
for (let d of data)
|
||||
if (typeof(d.rule) == 'object' && d.rule.table == spec.table && d.rule.chain == spec.name && d.rule.family == spec.family)
|
||||
node.lastElementChild.appendChild(this.renderRule(data, d.rule));
|
||||
|
||||
if (node.lastElementChild.childNodes.length == 1)
|
||||
node.lastElementChild.appendChild(E('tr', { 'class': 'tr' }, [
|
||||
@@ -718,8 +718,8 @@ return view.extend({
|
||||
return node;
|
||||
},
|
||||
|
||||
renderTable: function(data, spec) {
|
||||
var title;
|
||||
renderTable(data, spec) {
|
||||
let title;
|
||||
|
||||
switch (spec.family) {
|
||||
case 'ip':
|
||||
@@ -751,7 +751,7 @@ return view.extend({
|
||||
break;
|
||||
}
|
||||
|
||||
var node = E([], [
|
||||
const node = E([], [
|
||||
E('style', { 'type': 'text/css' }, [
|
||||
'.nft-rules .ifacebadge { margin: .125em }',
|
||||
'.nft-rules tr > td { padding: .25em !important }',
|
||||
@@ -766,14 +766,14 @@ return view.extend({
|
||||
])
|
||||
]);
|
||||
|
||||
for (var i = 0; i < data.length; i++)
|
||||
if (typeof(data[i].chain) == 'object' && data[i].chain.table == spec.name && data[i].chain.family == spec.family)
|
||||
node.lastElementChild.lastElementChild.appendChild(this.renderChain(data, data[i].chain));
|
||||
for (let d of data)
|
||||
if (typeof(d.chain) == 'object' && d.chain.table == spec.name && d.chain.family == spec.family)
|
||||
node.lastElementChild.lastElementChild.appendChild(this.renderChain(data, d.chain));
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
checkLegacyRules: function(ipt4save, ipt6save) {
|
||||
checkLegacyRules(ipt4save, ipt6save) {
|
||||
if (ipt4save.match(/\n-A /) || ipt6save.match(/\n-A /)) {
|
||||
ui.addNotification(_('Legacy rules detected'), [
|
||||
E('p', _('There are legacy iptables rules present on the system. Mixing iptables and nftables rules is discouraged and may lead to incomplete traffic filtering.')),
|
||||
@@ -785,20 +785,17 @@ return view.extend({
|
||||
}
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var view = E('div'),
|
||||
nft = data[0],
|
||||
ipt = data[1],
|
||||
ipt6 = data[2];
|
||||
render([nft, ipt, ipt6]) {
|
||||
const view = E('div');
|
||||
|
||||
this.checkLegacyRules(ipt, ipt6);
|
||||
|
||||
if (!Array.isArray(nft.nftables))
|
||||
return E('em', _('No nftables ruleset loaded.'));
|
||||
|
||||
for (var i = 0; i < nft.nftables.length; i++)
|
||||
if (nft.nftables[i].hasOwnProperty('table'))
|
||||
view.appendChild(this.renderTable(nft.nftables, nft.nftables[i].table));
|
||||
for (let t of nft.nftables)
|
||||
if (t.hasOwnProperty('table'))
|
||||
view.appendChild(this.renderTable(nft.nftables, t.table));
|
||||
|
||||
return view;
|
||||
},
|
||||
|
||||
@@ -120,7 +120,7 @@ return view.extend({
|
||||
const res = [];
|
||||
|
||||
for (const line of routes.trim().split(/\n/)) {
|
||||
const [, type = 'unicast', d, f = [] ] = line.match(/^(?:([a-z_]+|\d+) )?(default|[0-9a-f:.\/]+) (.+)$/);
|
||||
const [, type = 'unicast', d, f = [] ] = line.match(/^(?:([a-z_]+|\d+) )?(default|[0-9a-f:./]+) (.+)$/);
|
||||
const dest = d == 'default' ? (v6 ? '::/0' : '0.0.0.0/0') : d;
|
||||
const flags = f?.trim?.().split?.(/\s+/);
|
||||
|
||||
|
||||
@@ -53,8 +53,7 @@ return view.extend({
|
||||
|
||||
const data_wanted = Math.floor(width / step);
|
||||
|
||||
const data_values = [],
|
||||
line_elements = [];
|
||||
const data_values = [];
|
||||
|
||||
for (const line of lines)
|
||||
if (line)
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
'require fs';
|
||||
'require ui';
|
||||
|
||||
var isReadonlyView = !L.hasViewPermission();
|
||||
const isReadonlyView = !L.hasViewPermission();
|
||||
|
||||
var callSystemValidateFirmwareImage = rpc.declare({
|
||||
const callSystemValidateFirmwareImage = rpc.declare({
|
||||
object: 'system',
|
||||
method: 'validate_firmware_image',
|
||||
params: [ 'path' ],
|
||||
@@ -16,11 +16,11 @@ var callSystemValidateFirmwareImage = rpc.declare({
|
||||
});
|
||||
|
||||
function findStorageSize(procmtd, procpart) {
|
||||
var kernsize = 0, rootsize = 0, wholesize = 0;
|
||||
let kernsize = 0, rootsize = 0, wholesize = 0;
|
||||
|
||||
procmtd.split(/\n/).forEach(function(ln) {
|
||||
var match = ln.match(/^mtd\d+: ([0-9a-f]+) [0-9a-f]+ "(.+)"$/),
|
||||
size = match ? parseInt(match[1], 16) : 0;
|
||||
const match = ln.match(/^mtd\d+: ([0-9a-f]+) [0-9a-f]+ "(.+)"$/);
|
||||
const size = match ? parseInt(match[1], 16) : 0;
|
||||
|
||||
switch (match ? match[2] : '') {
|
||||
case 'linux':
|
||||
@@ -49,9 +49,9 @@ function findStorageSize(procmtd, procpart) {
|
||||
return kernsize + rootsize;
|
||||
|
||||
procpart.split(/\n/).forEach(function(ln) {
|
||||
var match = ln.match(/^\s*\d+\s+\d+\s+(\d+)\s+(\S+)$/);
|
||||
const match = ln.match(/^\s*\d+\s+\d+\s+(\d+)\s+(\S+)$/);
|
||||
if (match) {
|
||||
var size = parseInt(match[1], 10);
|
||||
const size = parseInt(match[1], 10);
|
||||
|
||||
if (!match[2].match(/\d/) && size > 2048 && wholesize == 0)
|
||||
wholesize = size * 1024;
|
||||
@@ -62,11 +62,11 @@ function findStorageSize(procmtd, procpart) {
|
||||
}
|
||||
|
||||
|
||||
var mapdata = { actions: {}, config: {} };
|
||||
const mapdata = { actions: {}, config: {} };
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
var tasks = [
|
||||
load() {
|
||||
const tasks = [
|
||||
L.resolveDefault(fs.stat('/lib/upgrade/platform.sh'), {}),
|
||||
fs.trimmed('/proc/sys/kernel/hostname'),
|
||||
fs.trimmed('/proc/mtd'),
|
||||
@@ -77,8 +77,8 @@ return view.extend({
|
||||
return Promise.all(tasks);
|
||||
},
|
||||
|
||||
handleBackup: function(ev) {
|
||||
var form = E('form', {
|
||||
handleBackup(ev) {
|
||||
const form = E('form', {
|
||||
method: 'post',
|
||||
action: L.env.cgi_base + '/cgi-backup',
|
||||
enctype: 'application/x-www-form-urlencoded'
|
||||
@@ -90,7 +90,7 @@ return view.extend({
|
||||
form.parentNode.removeChild(form);
|
||||
},
|
||||
|
||||
handleFirstboot: function(ev) {
|
||||
handleFirstboot(ev) {
|
||||
if (!confirm(_('Do you really want to erase all settings?')))
|
||||
return;
|
||||
|
||||
@@ -104,7 +104,7 @@ return view.extend({
|
||||
ui.awaitReconnect('192.168.1.1', 'openwrt.lan');
|
||||
},
|
||||
|
||||
handleRestore: function(ev) {
|
||||
handleRestore(ev) {
|
||||
return ui.uploadFile('/tmp/backup.tar.gz', ev.target)
|
||||
.then(L.bind(function(btn, res) {
|
||||
btn.firstChild.data = _('Checking archive…');
|
||||
@@ -139,7 +139,7 @@ return view.extend({
|
||||
}, this, ev.target));
|
||||
},
|
||||
|
||||
handleRestoreConfirm: function(btn, ev) {
|
||||
handleRestoreConfirm(btn, ev) {
|
||||
return fs.exec('/sbin/sysupgrade', [ '--restore-backup', '/tmp/backup.tar.gz' ])
|
||||
.then(L.bind(function(btn, res) {
|
||||
if (res.code != 0) {
|
||||
@@ -169,11 +169,11 @@ return view.extend({
|
||||
.finally(function() { btn.firstChild.data = _('Upload archive...') });
|
||||
},
|
||||
|
||||
handleBlock: function(hostname, ev) {
|
||||
var mtdblock = dom.parent(ev.target, '.cbi-section').querySelector('[data-name="mtdselect"] select');
|
||||
var mtdnumber = mtdblock.value;
|
||||
var mtdname = mtdblock.selectedOptions[0].text.replace(/([^a-zA-Z0-9]+)/g, '-');
|
||||
var form = E('form', {
|
||||
handleBlock(hostname, ev) {
|
||||
const mtdblock = dom.parent(ev.target, '.cbi-section').querySelector('[data-name="mtdselect"] select');
|
||||
const mtdnumber = mtdblock.value;
|
||||
const mtdname = mtdblock.selectedOptions[0].text.replace(/([^a-zA-Z0-9]+)/g, '-');
|
||||
const form = E('form', {
|
||||
'method': 'post',
|
||||
'action': L.env.cgi_base + '/cgi-download',
|
||||
'enctype': 'application/x-www-form-urlencoded'
|
||||
@@ -189,7 +189,7 @@ return view.extend({
|
||||
form.parentNode.removeChild(form);
|
||||
},
|
||||
|
||||
handleSysupgrade: function(storage_size, has_rootfs_data, ev) {
|
||||
handleSysupgrade(storage_size, has_rootfs_data, ev) {
|
||||
return ui.uploadFile('/tmp/firmware.bin', ev.target.firstChild)
|
||||
.then(L.bind(function(btn, reply) {
|
||||
btn.firstChild.data = _('Checking image…');
|
||||
@@ -207,7 +207,7 @@ return view.extend({
|
||||
}, this, ev.target))
|
||||
.then(L.bind(function(btn, res) {
|
||||
/* sysupgrade opts table [0]:checkbox element [1]:check condition [2]:args to pass */
|
||||
var opts = {
|
||||
const opts = {
|
||||
keep : [ E('input', { type: 'checkbox' }), false, '-n' ],
|
||||
force : [ E('input', { type: 'checkbox' }), true, '--force' ],
|
||||
skip_orig : [ E('input', { type: 'checkbox' }), true, '-u' ],
|
||||
@@ -265,7 +265,7 @@ return view.extend({
|
||||
])));
|
||||
};
|
||||
|
||||
var cntbtn = E('button', {
|
||||
const cntbtn = E('button', {
|
||||
'class': 'btn cbi-button-action important',
|
||||
'click': ui.createHandlerFn(this, 'handleSysupgradeConfirm', btn, opts),
|
||||
}, [ _('Continue') ]);
|
||||
@@ -315,16 +315,16 @@ return view.extend({
|
||||
}, this, ev.target));
|
||||
},
|
||||
|
||||
handleSysupgradeConfirm: function(btn, opts, ev) {
|
||||
handleSysupgradeConfirm(btn, opts, ev) {
|
||||
btn.firstChild.data = _('Flashing…');
|
||||
|
||||
ui.showModal(_('Flashing…'), [
|
||||
E('p', { 'class': 'spinning' }, _('The system is flashing now.<br /> DO NOT POWER OFF THE DEVICE!<br /> Wait a few minutes before you try to reconnect. It might be necessary to renew the address of your computer to reach the device again, depending on your settings.'))
|
||||
]);
|
||||
|
||||
var args = [];
|
||||
const args = [];
|
||||
|
||||
for (var key in opts)
|
||||
for (let key in opts)
|
||||
/* if checkbox == condition add args to sysupgrade */
|
||||
if (opts[key][0].checked == opts[key][1])
|
||||
args.push(opts[key][2]);
|
||||
@@ -340,7 +340,7 @@ return view.extend({
|
||||
ui.awaitReconnect('192.168.1.1', 'openwrt.lan');
|
||||
},
|
||||
|
||||
handleBackupList: function(ev) {
|
||||
handleBackupList(ev) {
|
||||
return fs.exec('/sbin/sysupgrade', [ '--list-backup' ]).then(function(res) {
|
||||
if (res.code != 0) {
|
||||
ui.addNotification(null, [
|
||||
@@ -363,7 +363,7 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
handleBackupSave: function(m, ev) {
|
||||
handleBackupSave(m, ev) {
|
||||
return m.save(function() {
|
||||
return fs.write('/etc/sysupgrade.conf', mapdata.config.editlist.trim().replace(/\r\n/g, '\n') + '\n');
|
||||
}).then(function() {
|
||||
@@ -373,15 +373,11 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
render: function(rpc_replies) {
|
||||
var has_sysupgrade = (rpc_replies[0].type == 'file'),
|
||||
hostname = rpc_replies[1],
|
||||
procmtd = rpc_replies[2],
|
||||
procpart = rpc_replies[3],
|
||||
procmounts = rpc_replies[4],
|
||||
has_rootfs_data = (procmtd.match(/"rootfs_data"/) != null) || (procmounts.match("overlayfs:\/overlay \/ ") != null),
|
||||
storage_size = findStorageSize(procmtd, procpart),
|
||||
m, s, o, ss;
|
||||
render([p_fstat, hostname, procmtd, procpart, procmounts]) {
|
||||
const has_sysupgrade = (p_fstat.type == 'file');
|
||||
const has_rootfs_data = (procmtd.match(/"rootfs_data"/) != null) || (procmounts.match("overlayfs:/overlay / ") != null);
|
||||
const storage_size = findStorageSize(procmtd, procpart);
|
||||
let m, s, o, ss;
|
||||
|
||||
m = new form.JSONMap(mapdata, _('Flash operations'));
|
||||
m.tabbed = true;
|
||||
@@ -415,9 +411,9 @@ return view.extend({
|
||||
o.onclick = L.bind(this.handleRestore, this);
|
||||
|
||||
|
||||
var mtdblocks = [];
|
||||
const mtdblocks = [];
|
||||
procmtd.split(/\n/).forEach(function(ln) {
|
||||
var match = ln.match(/^mtd(\d+): .+ "(.+?)"$/);
|
||||
const match = ln.match(/^mtd(\d+): .+ "(.+?)"$/);
|
||||
if (match)
|
||||
mtdblocks.push(match[1], match[2]);
|
||||
});
|
||||
|
||||
@@ -5,25 +5,24 @@
|
||||
'require form';
|
||||
'require fs';
|
||||
|
||||
var callLeds = rpc.declare({
|
||||
const callLeds = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getLEDs',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
callLeds(),
|
||||
L.resolveDefault(fs.list('/www' + L.resource('view/system/led-trigger')), [])
|
||||
]).then(function(data) {
|
||||
var plugins = data[1];
|
||||
var tasks = [];
|
||||
]).then(function([leds, plugins]) {
|
||||
const tasks = [];
|
||||
|
||||
for (var i = 0; i < plugins.length; i++) {
|
||||
var m = plugins[i].name.match(/^(.+)\.js$/);
|
||||
for (let p of plugins) {
|
||||
const m = p.name.match(/^(.+)\.js$/);
|
||||
|
||||
if (plugins[i].type != 'file' || m == null)
|
||||
if (p.type != 'file' || m == null)
|
||||
continue;
|
||||
|
||||
tasks.push(L.require('view.system.led-trigger.' + m[1]).then(L.bind(function(name){
|
||||
@@ -37,22 +36,18 @@ return view.extend({
|
||||
}
|
||||
|
||||
return Promise.all(tasks).then(function(plugins) {
|
||||
var value = {};
|
||||
value[0] = data[0];
|
||||
value[1] = plugins;
|
||||
return value;
|
||||
return [leds, plugins];
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var m, s, o, triggers = [];
|
||||
var leds = data[0];
|
||||
var plugins = data[1];
|
||||
render([leds, plugins]) {
|
||||
let m, s, o;
|
||||
const triggers = [];
|
||||
|
||||
for (var k in leds)
|
||||
for (var i = 0; i < leds[k].triggers.length; i++)
|
||||
triggers[i] = leds[k].triggers[i];
|
||||
for (let k in leds)
|
||||
for (let t of leds[k].triggers)
|
||||
triggers.push(t);
|
||||
|
||||
m = new form.Map('system',
|
||||
_('<abbr title="Light Emitting Diode">LED</abbr> Configuration'),
|
||||
@@ -73,9 +68,7 @@ return view.extend({
|
||||
});
|
||||
|
||||
o = s.option(form.ListValue, 'trigger', _('Trigger'));
|
||||
for (var i = 0; i < plugins.length; i++) {
|
||||
var plugin = plugins[i];
|
||||
|
||||
for (let plugin of plugins) {
|
||||
if ( plugin.form.kernel == false ) {
|
||||
o.value(plugin.name, plugin.form.trigger);
|
||||
}
|
||||
@@ -85,17 +78,15 @@ return view.extend({
|
||||
}
|
||||
}
|
||||
o.onchange = function(ev, section, value) {
|
||||
for (var i = 0; i < plugins.length; i++) {
|
||||
var plugin = plugins[i];
|
||||
if ( plugin.name === value )
|
||||
this.map.findElement('id', 'cbid.system.%s.trigger'.format(section))
|
||||
.nextElementSibling.innerHTML = plugin.form.description || '';
|
||||
const nes = this.map.findElement('id', 'cbid.system.%s.trigger'.format(section)).nextElementSibling;
|
||||
for (let plugin of plugins) {
|
||||
if ( plugin.name === value && nes )
|
||||
nes.innerText = plugin.form.description || '';
|
||||
}
|
||||
}
|
||||
o.load = function(section_id) {
|
||||
var trigger = uci.get('system', section_id, 'trigger');
|
||||
for (var i = 0; i < plugins.length; i++) {
|
||||
var plugin = plugins[i];
|
||||
const trigger = uci.get('system', section_id, 'trigger');
|
||||
for (let plugin of plugins) {
|
||||
if ( plugin.name === trigger)
|
||||
this.description = plugin.form.description || ' ';
|
||||
}
|
||||
@@ -103,17 +94,16 @@ return view.extend({
|
||||
};
|
||||
|
||||
s.addModalOptions = function(s) {
|
||||
for (var i = 0; i < plugins.length; i++) {
|
||||
var plugin = plugins[i];
|
||||
for (let plugin of plugins) {
|
||||
plugin.form.addFormOptions(s);
|
||||
}
|
||||
|
||||
var opts = s.getOption();
|
||||
const opts = s.getOption();
|
||||
|
||||
var removeIfNoneActive = function(original_remove_fn, section_id) {
|
||||
var isAnyActive = false;
|
||||
const removeIfNoneActive = function(original_remove_fn, section_id) {
|
||||
let isAnyActive = false;
|
||||
|
||||
for (var optname in opts) {
|
||||
for (let optname in opts) {
|
||||
if (opts[optname].ucioption != this.ucioption)
|
||||
continue;
|
||||
|
||||
@@ -128,7 +118,7 @@ return view.extend({
|
||||
original_remove_fn.call(this, section_id);
|
||||
};
|
||||
|
||||
for (var optname in opts) {
|
||||
for (let optname in opts) {
|
||||
if (!opts[optname].ucioption || optname == opts[optname].ucioption)
|
||||
continue;
|
||||
opts[optname].remove = removeIfNoneActive.bind(opts[optname], opts[optname].remove);
|
||||
|
||||
@@ -6,29 +6,27 @@
|
||||
'require rpc';
|
||||
'require form';
|
||||
|
||||
var callBlockDevices, callMountPoints, callBlockDetect;
|
||||
|
||||
callBlockDevices = rpc.declare({
|
||||
const callBlockDevices = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getBlockDevices',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
callMountPoints = rpc.declare({
|
||||
const callMountPoints = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getMountPoints',
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
callBlockDetect = rpc.declare({
|
||||
const callBlockDetect = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'setBlockDetect',
|
||||
expect: { result: false }
|
||||
});
|
||||
|
||||
function device_textvalue(devices, section_id) {
|
||||
var v = (uci.get('fstab', section_id, 'uuid') || '').toLowerCase(),
|
||||
e = Object.keys(devices).filter(function(dev) { return (devices[dev].uuid || '-').toLowerCase() == v })[0];
|
||||
let v = (uci.get('fstab', section_id, 'uuid') || '').toLowerCase();
|
||||
let e = Object.keys(devices).filter(function(dev) { return (devices[dev].uuid || '-').toLowerCase() == v })[0];
|
||||
|
||||
if (v) {
|
||||
this.section.devices[section_id] = devices[e];
|
||||
@@ -71,13 +69,13 @@ function device_textvalue(devices, section_id) {
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
handleDetect: function(m, ev) {
|
||||
handleDetect(m, ev) {
|
||||
return callBlockDetect()
|
||||
.then(L.bind(uci.unload, uci, 'fstab'))
|
||||
.then(L.bind(m.render, m));
|
||||
},
|
||||
|
||||
handleMountAll: function(m, ev) {
|
||||
handleMountAll(m, ev) {
|
||||
return fs.exec('/sbin/block', ['mount'])
|
||||
.then(function(res) {
|
||||
if (res.code != 0)
|
||||
@@ -87,53 +85,34 @@ return view.extend({
|
||||
.then(L.bind(m.render, m));
|
||||
},
|
||||
|
||||
handleUmount: function(m, path, ev) {
|
||||
handleUmount(m, path, ev) {
|
||||
return fs.exec('/bin/umount', [path])
|
||||
.then(L.bind(uci.unload, uci, 'fstab'))
|
||||
.then(L.bind(m.render, m))
|
||||
.catch(function(e) { ui.addNotification(null, E('p', e.message)) });
|
||||
},
|
||||
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
callBlockDevices(),
|
||||
fs.lines('/proc/filesystems'),
|
||||
fs.lines('/etc/filesystems'),
|
||||
L.resolveDefault(fs.stat('/usr/sbin/e2fsck'), null),
|
||||
L.resolveDefault(fs.stat('/usr/sbin/fsck.f2fs'), null),
|
||||
L.resolveDefault(fs.stat('/usr/sbin/fsck.fat'), null),
|
||||
L.resolveDefault(fs.stat('/usr/bin/btrfsck'), null),
|
||||
L.resolveDefault(fs.stat('/usr/bin/ntfsfix'), null),
|
||||
uci.load('fstab')
|
||||
uci.load('fstab'),
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(results) {
|
||||
var devices = results[0],
|
||||
procfs = results[1],
|
||||
etcfs = results[2],
|
||||
triggers = {},
|
||||
trigger, m, s, o;
|
||||
render([devices, procfs, etcfs]) {
|
||||
let m, s, o;
|
||||
|
||||
var fsck = {
|
||||
ext2: results[3],
|
||||
ext3: results[3],
|
||||
ext4: results[3],
|
||||
f2fs: results[4],
|
||||
vfat: results[5],
|
||||
btrfs: results[6],
|
||||
ntfs: results[7]
|
||||
};
|
||||
let filesystems = {};
|
||||
|
||||
var filesystems = {};
|
||||
for (let p of procfs)
|
||||
if (p.match(/\S/) && !p.match(/^nodev\t/))
|
||||
filesystems[p.trim()] = true;
|
||||
|
||||
for (var i = 0; i < procfs.length; i++)
|
||||
if (procfs[i].match(/\S/) && !procfs[i].match(/^nodev\t/))
|
||||
filesystems[procfs[i].trim()] = true;
|
||||
|
||||
for (var i = 0; i < etcfs.length; i++)
|
||||
if (etcfs[i].match(/\S/))
|
||||
filesystems[etcfs[i].trim()] = true;
|
||||
for (let e of etcfs)
|
||||
if (e.match(/\S/))
|
||||
filesystems[e.trim()] = true;
|
||||
|
||||
filesystems = Object.keys(filesystems).sort();
|
||||
|
||||
@@ -186,7 +165,7 @@ return view.extend({
|
||||
};
|
||||
|
||||
o.render = L.bind(function(view, section_id) {
|
||||
var table = E('table', { 'class': 'table' }, [
|
||||
const table = E('table', { 'class': 'table' }, [
|
||||
E('tr', { 'class': 'tr table-titles' }, [
|
||||
E('th', { 'class': 'th' }, _('Filesystem')),
|
||||
E('th', { 'class': 'th' }, _('Mount Point')),
|
||||
@@ -196,23 +175,23 @@ return view.extend({
|
||||
])
|
||||
]);
|
||||
|
||||
var rows = [];
|
||||
const rows = [];
|
||||
|
||||
for (var i = 0; i < this.mounts.length; i++) {
|
||||
var used = this.mounts[i].size - this.mounts[i].free,
|
||||
for (let tm of this.mounts) {
|
||||
var used = tm.size - tm.free,
|
||||
umount = true;
|
||||
|
||||
if (/^\/(overlay|rom|tmp(?:\/.+)?|dev(?:\/.+)?|)$/.test(this.mounts[i].mount))
|
||||
if (/^\/(overlay|rom|tmp(?:\/.+)?|dev(?:\/.+)?|)$/.test(tm.mount))
|
||||
umount = false;
|
||||
|
||||
rows.push([
|
||||
this.mounts[i].device,
|
||||
this.mounts[i].mount,
|
||||
'%1024.2mB / %1024.2mB'.format(this.mounts[i].avail, this.mounts[i].size),
|
||||
'%.2f%% (%1024.2mB)'.format(100 / this.mounts[i].size * used, used),
|
||||
tm.device,
|
||||
tm.mount,
|
||||
'%1024.2mB / %1024.2mB'.format(tm.avail, tm.size),
|
||||
'%.2f%% (%1024.2mB)'.format(100 / tm.size * used, used),
|
||||
umount ? E('button', {
|
||||
'class': 'btn cbi-button-remove',
|
||||
'click': ui.createHandlerFn(view, 'handleUmount', m, this.mounts[i].mount),
|
||||
'click': ui.createHandlerFn(view, 'handleUmount', m, tm.mount),
|
||||
'disabled': this.map.readonly || null
|
||||
}, [ _('Unmount') ]) : '-'
|
||||
]);
|
||||
@@ -256,9 +235,9 @@ return view.extend({
|
||||
o.modalonly = true;
|
||||
o.value('', _('-- match by uuid --'));
|
||||
|
||||
var devs = Object.keys(devices).sort();
|
||||
for (var i = 0; i < devs.length; i++) {
|
||||
var dev = devices[devs[i]];
|
||||
const devs = Object.keys(devices).sort();
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.uuid && dev.size)
|
||||
o.value(dev.uuid, '%s (%s, %1024.2mB)'.format(dev.uuid, dev.dev, dev.size));
|
||||
else if (dev.uuid)
|
||||
@@ -270,8 +249,8 @@ return view.extend({
|
||||
o.depends('uuid', '');
|
||||
o.value('', _('-- match by label --'));
|
||||
|
||||
for (var i = 0; i < devs.length; i++) {
|
||||
var dev = devices[devs[i]];
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.label && dev.size)
|
||||
o.value(dev.label, '%s (%s, %1024.2mB)'.format(dev.label, dev.dev, dev.size));
|
||||
else if (dev.label)
|
||||
@@ -282,8 +261,8 @@ return view.extend({
|
||||
o.modalonly = true;
|
||||
o.depends({ uuid: '', label: '' });
|
||||
|
||||
for (var i = 0; i < devs.length; i++) {
|
||||
var dev = devices[devs[i]];
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.size)
|
||||
o.value(dev.dev, '%s (%1024.2mB)'.format(dev.dev, dev.size));
|
||||
else
|
||||
@@ -315,8 +294,8 @@ return view.extend({
|
||||
o = s.taboption('advanced', form.ListValue, 'fstype', _('Filesystem'));
|
||||
|
||||
o.textvalue = function(section_id) {
|
||||
var dev = this.section.devices[section_id],
|
||||
text = this.cfgvalue(section_id) || 'auto';
|
||||
const dev = this.section.devices[section_id];
|
||||
let text = this.cfgvalue(section_id) || 'auto';
|
||||
|
||||
if (dev && dev.type && dev.type != text)
|
||||
text += ' (%s)'.format(dev.type);
|
||||
@@ -326,8 +305,8 @@ return view.extend({
|
||||
|
||||
o.value('', 'auto');
|
||||
|
||||
for (var i = 0; i < filesystems.length; i++)
|
||||
o.value(filesystems[i]);
|
||||
for (let fs of filesystems)
|
||||
o.value(fs);
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'options', _('Mount options'), _('See "mount" manpage for details'));
|
||||
o.textvalue = function(section_id) { return this.cfgvalue(section_id) || 'defaults' };
|
||||
@@ -360,9 +339,8 @@ return view.extend({
|
||||
o.modalonly = true;
|
||||
o.value('', _('-- match by uuid --'));
|
||||
|
||||
var devs = Object.keys(devices).sort();
|
||||
for (var i = 0; i < devs.length; i++) {
|
||||
var dev = devices[devs[i]];
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.dev.match(/^\/dev\/(mtdblock|ubi|ubiblock)\d/))
|
||||
continue;
|
||||
|
||||
@@ -377,8 +355,8 @@ return view.extend({
|
||||
o.depends('uuid', '');
|
||||
o.value('', _('-- match by label --'));
|
||||
|
||||
for (var i = 0; i < devs.length; i++) {
|
||||
var dev = devices[devs[i]];
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.dev.match(/^\/dev\/(mtdblock|ubi|ubiblock)\d/))
|
||||
continue;
|
||||
|
||||
@@ -392,8 +370,8 @@ return view.extend({
|
||||
o.modalonly = true;
|
||||
o.depends({ uuid: '', label: '' });
|
||||
|
||||
for (var i = 0; i < devs.length; i++) {
|
||||
var dev = devices[devs[i]];
|
||||
for (let d of devs) {
|
||||
const dev = devices[d];
|
||||
if (dev.dev.match(/^\/dev\/(mtdblock|ubi|ubiblock)\d/))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -7,52 +7,49 @@
|
||||
'require form';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
var callRcList, callRcInit, callTimezone,
|
||||
callGetUnixtime, callSetLocaltime, CBILocalTime;
|
||||
|
||||
callRcList = rpc.declare({
|
||||
const callRcList = rpc.declare({
|
||||
object: 'rc',
|
||||
method: 'list',
|
||||
params: [ 'name' ],
|
||||
expect: { '': {} },
|
||||
filter: function(res) {
|
||||
filter(res) {
|
||||
for (var k in res)
|
||||
return +res[k].enabled;
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
callRcInit = rpc.declare({
|
||||
const callRcInit = rpc.declare({
|
||||
object: 'rc',
|
||||
method: 'init',
|
||||
params: [ 'name', 'action' ],
|
||||
expect: { result: false }
|
||||
});
|
||||
|
||||
callGetUnixtime = rpc.declare({
|
||||
const callGetUnixtime = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getUnixtime',
|
||||
expect: { result: 0 }
|
||||
});
|
||||
|
||||
callSetLocaltime = rpc.declare({
|
||||
const callSetLocaltime = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'setLocaltime',
|
||||
params: [ 'localtime' ],
|
||||
expect: { result: 0 }
|
||||
});
|
||||
|
||||
callTimezone = rpc.declare({
|
||||
const callTimezone = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getTimezones',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
function formatTime(epoch) {
|
||||
var date = new Date(epoch * 1000),
|
||||
zn = uci.get('system', '@system[0]', 'zonename')?.replaceAll(' ', '_') || 'UTC',
|
||||
ts = uci.get('system', '@system[0]', 'clock_timestyle') || 0,
|
||||
hc = uci.get('system', '@system[0]', 'clock_hourcycle') || 0;
|
||||
const date = new Date(epoch * 1000);
|
||||
const zn = uci.get('system', '@system[0]', 'zonename')?.replaceAll(' ', '_') || 'UTC';
|
||||
const ts = uci.get('system', '@system[0]', 'clock_timestyle') || 0;
|
||||
const hc = uci.get('system', '@system[0]', 'clock_hourcycle') || 0;
|
||||
|
||||
return new Intl.DateTimeFormat(undefined, {
|
||||
dateStyle: 'medium',
|
||||
@@ -62,8 +59,8 @@ function formatTime(epoch) {
|
||||
}).format(date);
|
||||
}
|
||||
|
||||
CBILocalTime = form.DummyValue.extend({
|
||||
renderWidget: function(section_id, option_id, cfgvalue) {
|
||||
const CBILocalTime = form.DummyValue.extend({
|
||||
renderWidget(section_id, option_id, cfgvalue) {
|
||||
return E([], [
|
||||
E('input', {
|
||||
'id': 'localtime',
|
||||
@@ -94,7 +91,7 @@ CBILocalTime = form.DummyValue.extend({
|
||||
});
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
callRcList('sysntpd'),
|
||||
callTimezone(),
|
||||
@@ -104,11 +101,8 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(rpc_replies) {
|
||||
var ntpd_enabled = rpc_replies[0],
|
||||
timezones = rpc_replies[1],
|
||||
unixtime = rpc_replies[2],
|
||||
m, s, o;
|
||||
render([ntpd_enabled, timezones, unixtime]) {
|
||||
let m, s, o;
|
||||
|
||||
m = new form.Map('system',
|
||||
_('System'),
|
||||
@@ -146,12 +140,12 @@ return view.extend({
|
||||
o = s.taboption('general', form.ListValue, 'zonename', _('Timezone'));
|
||||
o.value('UTC');
|
||||
|
||||
var zones = Object.keys(timezones || {}).sort();
|
||||
for (var i = 0; i < zones.length; i++)
|
||||
o.value(zones[i]);
|
||||
const zones = Object.keys(timezones || {}).sort();
|
||||
for (let zone of zones)
|
||||
o.value(zone);
|
||||
|
||||
o.write = function(section_id, formvalue) {
|
||||
var tz = timezones[formvalue] ? timezones[formvalue].tzstring : null;
|
||||
const tz = timezones[formvalue] ? timezones[formvalue].tzstring : null;
|
||||
uci.set('system', section_id, 'zonename', formvalue);
|
||||
uci.set('system', section_id, 'timezone', tz);
|
||||
};
|
||||
@@ -236,21 +230,21 @@ return view.extend({
|
||||
o.ucioption = 'lang';
|
||||
o.value('auto', _('auto'));
|
||||
|
||||
var l = Object.assign({ en: 'English' }, uci.get('luci', 'languages')),
|
||||
k = Object.keys(l).sort();
|
||||
for (var i = 0; i < k.length; i++)
|
||||
if (k[i].charAt(0) != '.')
|
||||
o.value(k[i], l[k[i]]);
|
||||
const l = Object.assign({ en: 'English' }, uci.get('luci', 'languages'));
|
||||
const keys = Object.keys(l).sort();
|
||||
for (let k of keys)
|
||||
if (k.charAt(0) != '.')
|
||||
o.value(k, l[k]);
|
||||
|
||||
o = s.taboption('language', form.ListValue, '_mediaurlbase', _('Design'))
|
||||
o.uciconfig = 'luci';
|
||||
o.ucisection = 'main';
|
||||
o.ucioption = 'mediaurlbase';
|
||||
|
||||
var k = Object.keys(uci.get('luci', 'themes') || {}).sort();
|
||||
for (var i = 0; i < k.length; i++)
|
||||
if (k[i].charAt(0) != '.')
|
||||
o.value(uci.get('luci', 'themes', k[i]), k[i]);
|
||||
const th = Object.keys(uci.get('luci', 'themes') || {}).sort();
|
||||
for (let t of th)
|
||||
if (t.charAt(0) != '.')
|
||||
o.value(uci.get('luci', 'themes', t), t);
|
||||
|
||||
o = s.taboption('language', form.Flag, '_tablefilters', _('Table Filters'));
|
||||
o.default = o.disabled;
|
||||
|
||||
Reference in New Issue
Block a user