mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-03 05:23:56 +08:00
⛄ Sync 2026-04-23 20:32:35
This commit is contained in:
1 parent
17738c6f79
commit
fe51d2b304
206 files changed
+725671
No files matched your search
@@ -0,0 +1,855 @@
|
||||
'use strict';
|
||||
'require ui';
|
||||
'require form';
|
||||
'require network';
|
||||
'require firewall';
|
||||
'require fs';
|
||||
'require uci';
|
||||
|
||||
|
||||
/**
|
||||
* Get users found in `/etc/passwd`.
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function getUsers() {
|
||||
return fs.lines('/etc/passwd').then(function(lines) {
|
||||
return lines.map(function(line) { return line.split(/:/)[0] });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get users found in `/etc/group`.
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function getGroups() {
|
||||
return fs.lines('/etc/group').then(function(lines) {
|
||||
return lines.map(function(line) { return line.split(/:/)[0] });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bridge devices or Layer 3 devices of a network object.
|
||||
* @param {object} network
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function getDevices(network) {
|
||||
if (network.isBridge()) {
|
||||
var devices = network.getDevices();
|
||||
return devices ? devices : [];
|
||||
} else {
|
||||
return L.toArray(network.getL3Device());
|
||||
}
|
||||
}
|
||||
|
||||
var CBIZoneSelect = form.ListValue.extend({
|
||||
__name__: 'CBI.ZoneSelect',
|
||||
|
||||
load(section_id) {
|
||||
return Promise.all([ firewall.getZones(), network.getNetworks() ]).then(L.bind(function(zn) {
|
||||
this.zones = zn[0];
|
||||
this.networks = zn[1];
|
||||
|
||||
return this.super('load', section_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
filter(section_id, value) {
|
||||
return true;
|
||||
},
|
||||
|
||||
lookupZone(name) {
|
||||
return this.zones.filter(function(zone) { return zone.getName() == name })[0];
|
||||
},
|
||||
|
||||
lookupNetwork(name) {
|
||||
return this.networks.filter(function(network) { return network.getName() == name })[0];
|
||||
},
|
||||
|
||||
renderWidget(section_id, option_index, cfgvalue) {
|
||||
const values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
|
||||
let isOutputOnly = false;
|
||||
const choices = {};
|
||||
let datatype_str = 'ucifw4zonename';
|
||||
if (!L.hasSystemFeature('firewall4'))
|
||||
datatype_str = `and(${datatype_str},maxlength(11))`;
|
||||
if (this.allowany && this.nocreate)
|
||||
datatype_str = `or(${datatype_str},"*")`;
|
||||
if (this.multiple)
|
||||
datatype_str = `list(${datatype_str})`;
|
||||
|
||||
if (this.option == 'dest') {
|
||||
for (let c of this.section.children) {
|
||||
const opt = c;
|
||||
if (opt.option == 'src') {
|
||||
const val = opt.cfgvalue(section_id) || opt.default;
|
||||
isOutputOnly = (val == null || val == '');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.title = isOutputOnly ? _('Output zone') : _('Destination zone');
|
||||
}
|
||||
|
||||
if (this.allowlocal) {
|
||||
choices[''] = E('span', {
|
||||
'class': 'zonebadge',
|
||||
'style': firewall.getZoneColorStyle(null)
|
||||
}, [
|
||||
E('strong', _('Device')),
|
||||
(this.allowany || this.allowlocal)
|
||||
? E('span', ' (%s)'.format(this.option != 'dest' ? _('output') : _('input'))) : ''
|
||||
]);
|
||||
}
|
||||
else if (!this.multiple && (this.rmempty || this.optional)) {
|
||||
choices[''] = E('span', {
|
||||
'class': 'zonebadge',
|
||||
'style': firewall.getZoneColorStyle(null)
|
||||
}, E('em', _('unspecified')));
|
||||
}
|
||||
|
||||
if (this.allowany) {
|
||||
choices['*'] = E('span', {
|
||||
'class': 'zonebadge',
|
||||
'style': firewall.getZoneColorStyle(null)
|
||||
}, [
|
||||
E('strong', _('Any zone')),
|
||||
(this.allowany && this.allowlocal && !isOutputOnly) ? E('span', ' (%s)'.format(_('forward'))) : ''
|
||||
]);
|
||||
}
|
||||
|
||||
for (let zone of this.zones) {
|
||||
const name = zone.getName();
|
||||
const networks = zone.getNetworks();
|
||||
const ifaces = [];
|
||||
|
||||
if (!this.filter(section_id, name))
|
||||
continue;
|
||||
|
||||
for (let n of networks) {
|
||||
const network = this.lookupNetwork(n);
|
||||
|
||||
if (!network)
|
||||
continue;
|
||||
|
||||
const span = E('span', {
|
||||
'class': 'ifacebadge' + (network.isUp() ? ' ifacebadge-active' : '')
|
||||
}, network.getName() + ': ');
|
||||
|
||||
const devices = getDevices(network);
|
||||
|
||||
for (let d of devices) {
|
||||
span.appendChild(E('img', {
|
||||
'title': d.getI18n(),
|
||||
'src': L.resource('icons/%s%s.svg'.format(d.getType(), d.isUp() ? '' : '_disabled'))
|
||||
}));
|
||||
}
|
||||
|
||||
if (!devices.length)
|
||||
span.appendChild(E('em', _('(empty)')));
|
||||
|
||||
ifaces.push(span);
|
||||
}
|
||||
|
||||
if (!ifaces.length)
|
||||
ifaces.push(E('em', _('(empty)')));
|
||||
|
||||
choices[name] = E('span', {
|
||||
'class': 'zonebadge',
|
||||
'style': firewall.getZoneColorStyle(zone)
|
||||
}, [ E('strong', name) ].concat(ifaces));
|
||||
}
|
||||
|
||||
const widget = new ui.Dropdown(values, choices, {
|
||||
id: this.cbid(section_id),
|
||||
sort: true,
|
||||
multiple: this.multiple,
|
||||
optional: this.optional || this.rmempty,
|
||||
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
|
||||
select_placeholder: E('em', _('unspecified')),
|
||||
display_items: this.display_size || this.size || 3,
|
||||
dropdown_items: this.dropdown_size || this.size || 5,
|
||||
validate: L.bind(this.validate, this, section_id),
|
||||
datatype: datatype_str,
|
||||
create: !this.nocreate,
|
||||
create_markup: '' +
|
||||
'<li data-value="{{value}}">' +
|
||||
'<span class="zonebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">' +
|
||||
'<strong>{{value}}:</strong> <em>('+_('create')+')</em>' +
|
||||
'</span>' +
|
||||
'</li>'
|
||||
});
|
||||
|
||||
const elem = widget.render();
|
||||
|
||||
if (this.option == 'src') {
|
||||
elem.addEventListener('cbi-dropdown-change', L.bind(function(ev) {
|
||||
const opt = this.map.lookupOption('dest', section_id);
|
||||
const val = ev.detail.instance.getValue();
|
||||
|
||||
if (opt == null)
|
||||
return;
|
||||
|
||||
const cbid = opt[0].cbid(section_id);
|
||||
const label = document.querySelector('label[for="widget.%s"]'.format(cbid));
|
||||
const node = document.getElementById(cbid);
|
||||
|
||||
L.dom.content(label, val == '' ? _('Output zone') : _('Destination zone'));
|
||||
|
||||
if (val == '') {
|
||||
if (L.dom.callClassMethod(node, 'getValue') == '')
|
||||
L.dom.callClassMethod(node, 'setValue', '*');
|
||||
|
||||
const emptyval = node.querySelector('[data-value=""]');
|
||||
const anyval = node.querySelector('[data-value="*"]');
|
||||
|
||||
L.dom.content(anyval.querySelector('span'), E('strong', _('Any zone')));
|
||||
|
||||
if (emptyval != null)
|
||||
emptyval.parentNode.removeChild(emptyval);
|
||||
}
|
||||
else {
|
||||
const anyval = node.querySelector('[data-value="*"]') || '';
|
||||
let emptyval = node.querySelector('[data-value=""]') || '';
|
||||
|
||||
if (emptyval == null && anyval) {
|
||||
emptyval = anyval.cloneNode(true);
|
||||
emptyval.removeAttribute('display');
|
||||
emptyval.removeAttribute('selected');
|
||||
emptyval.setAttribute('data-value', '');
|
||||
}
|
||||
|
||||
if (opt[0]?.allowlocal && emptyval)
|
||||
L.dom.content(emptyval.querySelector('span'), [
|
||||
E('strong', _('Device')), E('span', ' (%s)'.format(_('input')))
|
||||
]);
|
||||
if (opt[0]?.allowany && anyval && emptyval) {
|
||||
L.dom.content(anyval.querySelector('span'), [
|
||||
E('strong', _('Any zone')), E('span', ' (%s)'.format(_('forward')))
|
||||
]);
|
||||
|
||||
anyval.parentNode.insertBefore(emptyval, anyval);
|
||||
}
|
||||
}
|
||||
|
||||
}, this));
|
||||
}
|
||||
else if (isOutputOnly) {
|
||||
const emptyval = elem.querySelector('[data-value=""]');
|
||||
emptyval.parentNode.removeChild(emptyval);
|
||||
}
|
||||
|
||||
return elem;
|
||||
},
|
||||
});
|
||||
|
||||
var CBIZoneForwards = form.DummyValue.extend({
|
||||
__name__: 'CBI.ZoneForwards',
|
||||
|
||||
load(section_id) {
|
||||
return Promise.all([
|
||||
firewall.getDefaults(),
|
||||
firewall.getZones(),
|
||||
network.getNetworks(),
|
||||
network.getDevices()
|
||||
]).then(L.bind(function(dznd) {
|
||||
this.defaults = dznd[0];
|
||||
this.zones = dznd[1];
|
||||
this.networks = dznd[2];
|
||||
this.devices = dznd[3];
|
||||
|
||||
return this.super('load', section_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
renderZone(zone) {
|
||||
const name = zone.getName();
|
||||
const networks = zone.getNetworks();
|
||||
const devices = zone.getDevices();
|
||||
const subnets = zone.getSubnets();
|
||||
const ifaces = [];
|
||||
|
||||
for (let n of networks) {
|
||||
const network = this.networks.filter(function(net) { return net.getName() == n })[0];
|
||||
|
||||
if (!network)
|
||||
continue;
|
||||
|
||||
const span = E('span', {
|
||||
'class': 'ifacebadge' + (network.isUp() ? ' ifacebadge-active' : '')
|
||||
}, network.getName() + ': ');
|
||||
|
||||
const subdevs = getDevices(network);
|
||||
|
||||
for (let s of subdevs) {
|
||||
span.appendChild(E('img', {
|
||||
'title': s.getI18n(),
|
||||
'src': L.resource('icons/%s%s.svg'.format(s.getType(), s.isUp() ? '' : '_disabled'))
|
||||
}));
|
||||
}
|
||||
|
||||
if (!subdevs.length)
|
||||
span.appendChild(E('em', _('(empty)')));
|
||||
|
||||
ifaces.push(span);
|
||||
}
|
||||
|
||||
for (let d of devices) {
|
||||
const device = this.devices.filter(function(dev) { return dev.getName() == d })[0];
|
||||
const title = device ? device.getI18n() : _('Absent Interface');
|
||||
const type = device ? device.getType() : 'ethernet';
|
||||
const up = device ? device.isUp() : false;
|
||||
|
||||
ifaces.push(E('span', { 'class': 'ifacebadge' }, [
|
||||
E('img', {
|
||||
'title': title,
|
||||
'src': L.resource('icons/%s%s.svg'.format(type, up ? '' : '_disabled'))
|
||||
}),
|
||||
device ? device.getName() : d
|
||||
]));
|
||||
}
|
||||
|
||||
if (subnets.length > 0)
|
||||
ifaces.push(E('span', { 'class': 'ifacebadge' }, [ '{ %s }'.format(subnets.join('; ')) ]));
|
||||
|
||||
if (!ifaces.length)
|
||||
ifaces.push(E('span', { 'class': 'ifacebadge' }, E('em', _('(empty)'))));
|
||||
|
||||
return E('label', {
|
||||
'class': 'zonebadge cbi-tooltip-container',
|
||||
'style': firewall.getZoneColorStyle(zone)
|
||||
}, [
|
||||
E('strong', name),
|
||||
E('div', { 'class': 'cbi-tooltip' }, ifaces)
|
||||
]);
|
||||
},
|
||||
|
||||
renderWidget(section_id, option_index, cfgvalue) {
|
||||
const value = (cfgvalue != null) ? cfgvalue : this.default;
|
||||
const zone = this.zones.filter(function(z) { return z.getName() == value })[0];
|
||||
|
||||
if (!zone)
|
||||
return E([]);
|
||||
|
||||
const forwards = zone.getForwardingsBy('src');
|
||||
const dzones = [];
|
||||
|
||||
for (var i = 0; i < forwards.length; i++) {
|
||||
const dzone = forwards[i].getDestinationZone();
|
||||
|
||||
if (!dzone)
|
||||
continue;
|
||||
|
||||
dzones.push(this.renderZone(dzone));
|
||||
}
|
||||
|
||||
if (!dzones.length)
|
||||
dzones.push(E('label', { 'class': 'zonebadge zonebadge-empty' },
|
||||
E('strong', this.defaults.getForward())));
|
||||
else
|
||||
dzones.push(E('label', { 'class': 'zonebadge zonebadge-empty' },
|
||||
E('strong', '%s %s'.format(this.defaults.getForward(), ('all others')))));
|
||||
|
||||
return E('div', { 'class': 'zone-forwards' }, [
|
||||
E('div', { 'class': 'zone-src' }, this.renderZone(zone)),
|
||||
E('span', '⇒'),
|
||||
E('div', { 'class': 'zone-dest' }, dzones)
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
const CBIIPSelect = form.ListValue.extend({
|
||||
__name__: 'CBI.IPSelect',
|
||||
|
||||
load(section_id) {
|
||||
return network.getDevices().then(L.bind(function(devices) {
|
||||
this.devices = devices;
|
||||
return this.super('load', section_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
filter(section_id, value) {
|
||||
return true;
|
||||
},
|
||||
|
||||
renderIfaceBadge(device, ip) {
|
||||
return E('div', {}, [
|
||||
ip,
|
||||
' ',
|
||||
E('span', { 'class': 'ifacebadge', }, [ device.getName(),
|
||||
E('img', {
|
||||
'title': device.getI18n(),
|
||||
'src': L.resource('icons/%s%s.svg'.format(device.getType(), device.isUp() ? '' : '_disabled'))
|
||||
})
|
||||
]),
|
||||
]);
|
||||
},
|
||||
|
||||
renderWidget(section_id, option_index, cfgvalue) {
|
||||
let values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
|
||||
const choices = {};
|
||||
const checked = {};
|
||||
|
||||
for (const val of values)
|
||||
checked[val] = true;
|
||||
|
||||
values = [];
|
||||
|
||||
if (!this.multiple && (this.rmempty || this.optional))
|
||||
choices[''] = E('em', _('unspecified'));
|
||||
|
||||
|
||||
for (const device of (this.devices || [])) {
|
||||
const name = device.getName();
|
||||
|
||||
if (name == this.exclude || !this.filter(section_id, name))
|
||||
continue;
|
||||
|
||||
if (name == 'loopback' && !this.loopback)
|
||||
continue;
|
||||
|
||||
if (this.novirtual && device.isVirtual())
|
||||
continue;
|
||||
|
||||
for (const ip of [...device.getIPAddrs(), ...device.getIP6Addrs()]) {
|
||||
const iponly = ip.split('/')?.[0]
|
||||
if (checked[iponly])
|
||||
values.push(iponly);
|
||||
choices[iponly] = this.renderIfaceBadge(device, iponly);
|
||||
}
|
||||
}
|
||||
|
||||
const widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
|
||||
id: this.cbid(section_id),
|
||||
sort: true,
|
||||
multiple: this.multiple,
|
||||
optional: this.optional || this.rmempty,
|
||||
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
|
||||
select_placeholder: E('em', _('unspecified')),
|
||||
display_items: this.display_size || this.size || 2,
|
||||
dropdown_items: this.dropdown_size || this.size || 5,
|
||||
datatype: this.multiple ? 'list(ipaddr)' : 'ipaddr',
|
||||
validate: L.bind(this.validate, this, section_id),
|
||||
create: false,
|
||||
});
|
||||
|
||||
return widget.render();
|
||||
},
|
||||
|
||||
textvalue(section_id) {
|
||||
const cfgvalue = this.cfgvalue(section_id);
|
||||
const values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
|
||||
const rv = E([]);
|
||||
|
||||
for (const device of (this.devices || [])) {
|
||||
for (const ip of [...device.getIPAddrs(), ...device.getIP6Addrs()]) {
|
||||
const iponly = ip.split('/')[0];
|
||||
if (values.indexOf(iponly) === -1)
|
||||
continue;
|
||||
|
||||
if (rv.childNodes.length)
|
||||
rv.appendChild(document.createTextNode(' '));
|
||||
|
||||
rv.appendChild(this.renderIfaceBadge(device, iponly));
|
||||
}
|
||||
}
|
||||
|
||||
if (!rv.firstChild)
|
||||
rv.appendChild(E('em', _('unspecified')));
|
||||
|
||||
return rv;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
var CBINetworkSelect = form.ListValue.extend({
|
||||
__name__: 'CBI.NetworkSelect',
|
||||
|
||||
load(section_id) {
|
||||
return network.getNetworks().then(L.bind(function(networks) {
|
||||
this.networks = networks;
|
||||
|
||||
return this.super('load', section_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
filter(section_id, value) {
|
||||
return true;
|
||||
},
|
||||
|
||||
renderIfaceBadge(network) {
|
||||
const span = E('span', { 'class': 'ifacebadge' }, network.getName() + ': ');
|
||||
const devices = getDevices(network);
|
||||
|
||||
for (let d of devices) {
|
||||
span.appendChild(E('img', {
|
||||
'title': d.getI18n(),
|
||||
'src': L.resource('icons/%s%s.svg'.format(d.getType(), d.isUp() ? '' : '_disabled'))
|
||||
}));
|
||||
}
|
||||
|
||||
if (!devices.length) {
|
||||
span.appendChild(E('em', { 'class': 'hide-close' }, _('(no interfaces attached)')));
|
||||
span.appendChild(E('em', { 'class': 'hide-open' }, '-'));
|
||||
}
|
||||
|
||||
return span;
|
||||
},
|
||||
|
||||
renderWidget(section_id, option_index, cfgvalue) {
|
||||
let values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
|
||||
const choices = {};
|
||||
const checked = {};
|
||||
|
||||
for (var i = 0; i < values.length; i++)
|
||||
checked[values[i]] = true;
|
||||
|
||||
values = [];
|
||||
|
||||
if (!this.multiple && (this.rmempty || this.optional))
|
||||
choices[''] = E('em', _('unspecified'));
|
||||
|
||||
for (let network of this.networks) {
|
||||
const name = network.getName();
|
||||
|
||||
if (name == this.exclude || !this.filter(section_id, name))
|
||||
continue;
|
||||
|
||||
if (name == 'loopback' && !this.loopback)
|
||||
continue;
|
||||
|
||||
if (this.novirtual && network.isVirtual())
|
||||
continue;
|
||||
|
||||
if (checked[name])
|
||||
values.push(name);
|
||||
|
||||
choices[name] = this.renderIfaceBadge(network);
|
||||
}
|
||||
|
||||
const widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
|
||||
id: this.cbid(section_id),
|
||||
sort: true,
|
||||
multiple: this.multiple,
|
||||
optional: this.optional || this.rmempty,
|
||||
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
|
||||
select_placeholder: E('em', _('unspecified')),
|
||||
display_items: this.display_size || this.size || 3,
|
||||
dropdown_items: this.dropdown_size || this.size || 5,
|
||||
datatype: this.multiple ? 'list(uciname)' : 'uciname',
|
||||
validate: L.bind(this.validate, this, section_id),
|
||||
create: !this.nocreate,
|
||||
create_markup: '' +
|
||||
'<li data-value="{{value}}">' +
|
||||
'<span class="ifacebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">' +
|
||||
'{{value}}: <em>('+_('create')+')</em>' +
|
||||
'</span>' +
|
||||
'</li>'
|
||||
});
|
||||
|
||||
return widget.render();
|
||||
},
|
||||
|
||||
textvalue(section_id) {
|
||||
const cfgvalue = this.cfgvalue(section_id);
|
||||
const values = L.toArray((cfgvalue != null) ? cfgvalue : this.default);
|
||||
const rv = E([]);
|
||||
|
||||
for (let network of this.networks) {
|
||||
const name = network.getName();
|
||||
|
||||
if (values.indexOf(name) == -1)
|
||||
continue;
|
||||
|
||||
if (rv.length)
|
||||
L.dom.append(rv, ' ');
|
||||
|
||||
L.dom.append(rv, this.renderIfaceBadge(network));
|
||||
}
|
||||
|
||||
if (!rv.firstChild)
|
||||
rv.appendChild(E('em', _('unspecified')));
|
||||
|
||||
return rv;
|
||||
},
|
||||
});
|
||||
|
||||
var CBIDeviceSelect = form.ListValue.extend({
|
||||
__name__: 'CBI.DeviceSelect',
|
||||
|
||||
load(section_id) {
|
||||
return Promise.all([
|
||||
network.getDevices(),
|
||||
this.noaliases ? null : network.getNetworks()
|
||||
]).then(L.bind(function(data) {
|
||||
this.devices = data[0];
|
||||
this.networks = data[1];
|
||||
|
||||
return this.super('load', section_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
filter(section_id, value) {
|
||||
return true;
|
||||
},
|
||||
|
||||
renderWidget(section_id, option_index, cfgvalue) {
|
||||
var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default),
|
||||
choices = {},
|
||||
checked = {},
|
||||
order = [];
|
||||
|
||||
for (var i = 0; i < values.length; i++)
|
||||
checked[values[i]] = true;
|
||||
|
||||
values = [];
|
||||
|
||||
if (!this.multiple && (this.rmempty || this.optional))
|
||||
choices[''] = E('em', _('unspecified'));
|
||||
|
||||
for (let device of this.devices) {
|
||||
const name = device.getName();
|
||||
const type = device.getType();
|
||||
|
||||
if (name == 'lo' || name == this.exclude || !this.filter(section_id, name))
|
||||
continue;
|
||||
|
||||
if (this.noaliases && type == 'alias')
|
||||
continue;
|
||||
|
||||
if (this.nobridges && type == 'bridge')
|
||||
continue;
|
||||
|
||||
if (this.noinactive && device.isUp() == false)
|
||||
continue;
|
||||
|
||||
const item = E([
|
||||
E('img', {
|
||||
'title': device.getI18n(),
|
||||
'src': L.resource('icons/%s%s.svg'.format(type, device.isUp() ? '' : '_disabled'))
|
||||
}),
|
||||
E('span', { 'class': 'hide-open' }, [ name ]),
|
||||
E('span', { 'class': 'hide-close'}, [ device.getI18n() ])
|
||||
]);
|
||||
|
||||
const networks = device.getNetworks();
|
||||
|
||||
if (networks.length > 0)
|
||||
L.dom.append(item.lastChild, [ ' (', networks.map(function(n) { return n.getName() }).join(', '), ')' ]);
|
||||
|
||||
if (checked[name])
|
||||
values.push(name);
|
||||
|
||||
choices[name] = item;
|
||||
order.push(name);
|
||||
}
|
||||
|
||||
if (this.networks != null) {
|
||||
for (let net of this.networks) {
|
||||
const device = network.instantiateDevice('@%s'.format(net.getName()), net);
|
||||
const name = device.getName();
|
||||
|
||||
if (name == '@loopback' || name == this.exclude || !this.filter(section_id, name))
|
||||
continue;
|
||||
|
||||
if (this.noinactive && net.isUp() == false)
|
||||
continue;
|
||||
|
||||
const item = E([
|
||||
E('img', {
|
||||
'title': device.getI18n(),
|
||||
'src': L.resource('icons/alias%s.svg'.format(device.isUp() ? '' : '_disabled'))
|
||||
}),
|
||||
E('span', { 'class': 'hide-open' }, [ name ]),
|
||||
E('span', { 'class': 'hide-close'}, [ device.getI18n() ])
|
||||
]);
|
||||
|
||||
if (checked[name])
|
||||
values.push(name);
|
||||
|
||||
choices[name] = item;
|
||||
order.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.includeips) {
|
||||
this.devices.forEach(net_dev => {
|
||||
['getIPAddrs', 'getIP6Addrs'].forEach(fn => {
|
||||
net_dev[fn]().forEach(addr => {
|
||||
const name = addr.split('/')[0];
|
||||
if (checked[name]) values.push(name);
|
||||
|
||||
choices[name] = E([], [name, ' (', E('strong', net_dev.getName()), ')']);
|
||||
order.push(name);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.nocreate) {
|
||||
const keys = Object.keys(checked).sort(L.naturalCompare);
|
||||
|
||||
for (let k of keys) {
|
||||
if (choices.hasOwnProperty(k))
|
||||
continue;
|
||||
|
||||
choices[k] = E([
|
||||
E('img', {
|
||||
'title': _('Absent Interface'),
|
||||
'src': L.resource('icons/ethernet_disabled.svg')
|
||||
}),
|
||||
E('span', { 'class': 'hide-open' }, [ k ]),
|
||||
E('span', { 'class': 'hide-close'}, [ '%s: "%h"'.format(_('Absent Interface'), k) ])
|
||||
]);
|
||||
|
||||
values.push(k);
|
||||
order.push(k);
|
||||
}
|
||||
}
|
||||
|
||||
const widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
|
||||
id: this.cbid(section_id),
|
||||
sort: order,
|
||||
multiple: this.multiple,
|
||||
optional: this.optional || this.rmempty,
|
||||
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
|
||||
select_placeholder: E('em', _('unspecified')),
|
||||
display_items: this.display_size || this.size || 3,
|
||||
dropdown_items: this.dropdown_size || this.size || 5,
|
||||
validate: L.bind(this.validate, this, section_id),
|
||||
create: !this.nocreate,
|
||||
create_markup: '' +
|
||||
'<li data-value="{{value}}">' +
|
||||
'<img title="'+_('Custom Interface')+': "{{value}}"" src="'+L.resource('icons/ethernet_disabled.svg')+'" />' +
|
||||
'<span class="hide-open">{{value}}</span>' +
|
||||
'<span class="hide-close">'+_('Custom Interface')+': "{{value}}"</span>' +
|
||||
'</li>'
|
||||
});
|
||||
|
||||
return widget.render();
|
||||
},
|
||||
});
|
||||
|
||||
var CBIUserSelect = form.ListValue.extend({
|
||||
__name__: 'CBI.UserSelect',
|
||||
|
||||
load(section_id) {
|
||||
return getUsers().then(L.bind(function(users) {
|
||||
delete this.keylist;
|
||||
delete this.vallist;
|
||||
for (var i = 0; i < users.length; i++) {
|
||||
this.value(users[i]);
|
||||
}
|
||||
|
||||
return this.super('load', section_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
filter(section_id, value) {
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
var CBIGroupSelect = form.ListValue.extend({
|
||||
__name__: 'CBI.GroupSelect',
|
||||
|
||||
load(section_id) {
|
||||
return getGroups().then(L.bind(function(groups) {
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
this.value(groups[i]);
|
||||
}
|
||||
|
||||
return this.super('load', section_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
filter(section_id, value) {
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
var CBIWifidogxGroupSelect = form.ListValue.extend({
|
||||
__name__: 'CBI.WifidogxGroupSelect',
|
||||
|
||||
// group_type: 1: Domain Group, 2: MAC Group
|
||||
// add a new property to store the group type
|
||||
group_type: '1',
|
||||
|
||||
load: function(section_id) {
|
||||
this.sappList = [];
|
||||
var sections = uci.sections('wifidogx', 'group');
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i]['g_type'] == this.group_type)
|
||||
this.sappList.push(sections[i]['.name']);
|
||||
}
|
||||
|
||||
return this.super('load', section_id);
|
||||
},
|
||||
|
||||
setGroupType: function(group_type) {
|
||||
if (group_type == 'mac') {
|
||||
this.group_type = '2';
|
||||
} else if (group_type == 'wildcard') {
|
||||
this.group_type = '3';
|
||||
}
|
||||
},
|
||||
|
||||
filter: function(section_id, value) {
|
||||
return true;
|
||||
},
|
||||
|
||||
renderWidget: function(section_id, option_index, cfgvalue) {
|
||||
var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default),
|
||||
choices = {},
|
||||
checked = {};
|
||||
|
||||
for (var i = 0; i < values.length; i++)
|
||||
checked[values[i]] = true;
|
||||
|
||||
values = [];
|
||||
|
||||
if (!this.multiple && (this.rmempty || this.optional))
|
||||
choices[''] = E('em', _('unspecified'));
|
||||
|
||||
for (var i = 0; i < this.sappList.length; i++) {
|
||||
var name = this.sappList[i];
|
||||
|
||||
if (checked[name])
|
||||
values.push(name);
|
||||
|
||||
choices[name] = E('span', { 'class': 'ifacebadge' }, name);
|
||||
}
|
||||
|
||||
var widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
|
||||
id: this.cbid(section_id),
|
||||
sort: true,
|
||||
multiple: this.multiple,
|
||||
optional: this.optional || this.rmempty,
|
||||
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
|
||||
select_placeholder: E('em', _('unspecified')),
|
||||
display_items: this.display_size || this.size || 3,
|
||||
dropdown_items: this.dropdown_size || this.size || 5,
|
||||
validate: L.bind(this.validate, this, section_id),
|
||||
create: !this.nocreate,
|
||||
create_markup: '' +
|
||||
'<li data-value="{{value}}">' +
|
||||
'<span class="ifacebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">' +
|
||||
'{{value}}: <em>('+_('create')+')</em>' +
|
||||
'</span>' +
|
||||
'</li>'
|
||||
});
|
||||
|
||||
return widget.render();
|
||||
}
|
||||
});
|
||||
|
||||
return L.Class.extend({
|
||||
ZoneSelect: CBIZoneSelect,
|
||||
ZoneForwards: CBIZoneForwards,
|
||||
IPSelect: CBIIPSelect,
|
||||
NetworkSelect: CBINetworkSelect,
|
||||
DeviceSelect: CBIDeviceSelect,
|
||||
UserSelect: CBIUserSelect,
|
||||
GroupSelect: CBIGroupSelect,
|
||||
WifidogxGroupSelect: CBIWifidogxGroupSelect,
|
||||
});
|
||||
Reference in new issue
Block a user