7 var CBIZoneSelect
= form
.ListValue
.extend({
8 __name__
: 'CBI.ZoneSelect',
10 load: function(section_id
) {
11 return Promise
.all([ firewall
.getZones(), network
.getNetworks() ]).then(L
.bind(function(zn
) {
13 this.networks
= zn
[1];
15 return this.super('load', section_id
);
19 filter: function(section_id
, value
) {
23 lookupZone: function(name
) {
24 return this.zones
.filter(function(zone
) { return zone
.getName() == name
})[0];
27 lookupNetwork: function(name
) {
28 return this.networks
.filter(function(network
) { return network
.getName() == name
})[0];
31 renderWidget: function(section_id
, option_index
, cfgvalue
) {
32 var values
= L
.toArray((cfgvalue
!= null) ? cfgvalue
: this.default),
36 if (this.option
== 'dest') {
37 for (var i
= 0; i
< this.section
.children
.length
; i
++) {
38 var opt
= this.section
.children
[i
];
39 if (opt
.option
== 'src') {
40 var val
= opt
.cfgvalue(section_id
) || opt
.default;
41 isOutputOnly
= (val
== null || val
== '');
46 this.title
= isOutputOnly
? _('Output zone') : _('Destination zone');
49 if (this.allowlocal
) {
50 choices
[''] = E('span', {
52 'style': 'background-color:' + firewall
.getColorForName(null)
54 E('strong', _('Device')),
55 (this.allowany
|| this.allowlocal
)
56 ? ' (%s)'.format(this.option
!= 'dest' ? _('output') : _('input')) : ''
59 else if (!this.multiple
&& (this.rmempty
|| this.optional
)) {
60 choices
[''] = E('span', {
62 'style': 'background-color:' + firewall
.getColorForName(null)
63 }, E('em', _('unspecified')));
67 choices
['*'] = E('span', {
69 'style': 'background-color:' + firewall
.getColorForName(null)
71 E('strong', _('Any zone')),
72 (this.allowany
&& this.allowlocal
&& !isOutputOnly
) ? ' (%s)'.format(_('forward')) : ''
76 for (var i
= 0; i
< this.zones
.length
; i
++) {
77 var zone
= this.zones
[i
],
78 name
= zone
.getName(),
79 networks
= zone
.getNetworks(),
82 if (!this.filter(section_id
, name
))
85 for (var j
= 0; j
< networks
.length
; j
++) {
86 var network
= this.lookupNetwork(networks
[j
]);
91 var span
= E('span', {
92 'class': 'ifacebadge' + (network
.getName() == this.network
? ' ifacebadge-active' : '')
93 }, network
.getName() + ': ');
95 var devices
= network
.isBridge() ? network
.getDevices() : L
.toArray(network
.getDevice());
97 for (var k
= 0; k
< devices
.length
; k
++) {
98 span
.appendChild(E('img', {
99 'title': devices
[k
].getI18n(),
100 'src': L
.resource('icons/%s%s.png'.format(devices
[k
].getType(), devices
[k
].isUp() ? '' : '_disabled'))
105 span
.appendChild(E('em', _('(empty)')));
111 ifaces
.push(E('em', _('(empty)')));
113 choices
[name
] = E('span', {
114 'class': 'zonebadge',
115 'style': 'background-color:' + zone
.getColor()
116 }, [ E('strong', name
) ].concat(ifaces
));
119 var widget
= new ui
.Dropdown(values
, choices
, {
120 id
: this.cbid(section_id
),
122 multiple
: this.multiple
,
123 optional
: this.optional
|| this.rmempty
,
124 select_placeholder
: E('em', _('unspecified')),
125 display_items
: this.display_size
|| this.size
|| 3,
126 dropdown_items
: this.dropdown_size
|| this.size
|| 5,
127 validate
: L
.bind(this.validate
, this, section_id
),
128 create
: !this.nocreate
,
130 '<li data-value="{{value}}">' +
131 '<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)">' +
132 '<strong>{{value}}:</strong> <em>('+_('create')+')</em>' +
137 var elem
= widget
.render();
139 if (this.option
== 'src') {
140 elem
.addEventListener('cbi-dropdown-change', L
.bind(function(ev
) {
141 var opt
= this.map
.lookupOption('dest', section_id
),
142 val
= ev
.detail
.instance
.getValue();
147 var cbid
= opt
[0].cbid(section_id
),
148 label
= document
.querySelector('label[for="widget.%s"]'.format(cbid
)),
149 node
= document
.getElementById(cbid
);
151 L
.dom
.content(label
, val
== '' ? _('Output zone') : _('Destination zone'));
154 if (L
.dom
.callClassMethod(node
, 'getValue') == '')
155 L
.dom
.callClassMethod(node
, 'setValue', '*');
157 var emptyval
= node
.querySelector('[data-value=""]'),
158 anyval
= node
.querySelector('[data-value="*"]');
160 L
.dom
.content(anyval
.querySelector('span'), E('strong', _('Any zone')));
162 if (emptyval
!= null)
163 emptyval
.parentNode
.removeChild(emptyval
);
166 var anyval
= node
.querySelector('[data-value="*"]'),
167 emptyval
= node
.querySelector('[data-value=""]');
169 if (emptyval
== null) {
170 emptyval
= anyval
.cloneNode(true);
171 emptyval
.removeAttribute('display');
172 emptyval
.removeAttribute('selected');
173 emptyval
.setAttribute('data-value', '');
176 L
.dom
.content(emptyval
.querySelector('span'), [
177 E('strong', _('Device')), ' (%s)'.format(_('input'))
180 L
.dom
.content(anyval
.querySelector('span'), [
181 E('strong', _('Any zone')), ' (%s)'.format(_('forward'))
184 anyval
.parentNode
.insertBefore(emptyval
, anyval
);
189 else if (isOutputOnly
) {
190 var emptyval
= elem
.querySelector('[data-value=""]');
191 emptyval
.parentNode
.removeChild(emptyval
);
198 var CBIZoneForwards
= form
.DummyValue
.extend({
199 __name__
: 'CBI.ZoneForwards',
201 load: function(section_id
) {
203 firewall
.getDefaults(),
205 network
.getNetworks(),
207 ]).then(L
.bind(function(dznd
) {
208 this.defaults
= dznd
[0];
209 this.zones
= dznd
[1];
210 this.networks
= dznd
[2];
211 this.devices
= dznd
[3];
213 return this.super('load', section_id
);
217 renderZone: function(zone
) {
218 var name
= zone
.getName(),
219 networks
= zone
.getNetworks(),
220 devices
= zone
.getDevices(),
221 subnets
= zone
.getSubnets(),
224 for (var j
= 0; j
< networks
.length
; j
++) {
225 var network
= this.networks
.filter(function(net
) { return net
.getName() == networks
[j
] })[0];
230 var span
= E('span', {
231 'class': 'ifacebadge' + (network
.getName() == this.network
? ' ifacebadge-active' : '')
232 }, network
.getName() + ': ');
234 var subdevs
= network
.isBridge() ? network
.getDevices() : L
.toArray(network
.getDevice());
236 for (var k
= 0; k
< subdevs
.length
&& subdevs
[k
]; k
++) {
237 span
.appendChild(E('img', {
238 'title': subdevs
[k
].getI18n(),
239 'src': L
.resource('icons/%s%s.png'.format(subdevs
[k
].getType(), subdevs
[k
].isUp() ? '' : '_disabled'))
244 span
.appendChild(E('em', _('(empty)')));
249 for (var i
= 0; i
< devices
.length
; i
++) {
250 var device
= this.devices
.filter(function(dev
) { return dev
.getName() == devices
[i
] })[0],
251 title
= device
? device
.getI18n() : _('Absent Interface'),
252 type
= device
? device
.getType() : 'ethernet',
253 up
= device
? device
.isUp() : false;
255 ifaces
.push(E('span', { 'class': 'ifacebadge' }, [
258 'src': L
.resource('icons/%s%s.png'.format(type
, up
? '' : '_disabled'))
260 device
? device
.getName() : devices
[i
]
264 if (subnets
.length
> 0)
265 ifaces
.push(E('span', { 'class': 'ifacebadge' }, [ '{ %s }'.format(subnets
.join('; ')) ]));
268 ifaces
.push(E('span', { 'class': 'ifacebadge' }, E('em', _('(empty)'))));
271 'class': 'zonebadge cbi-tooltip-container',
272 'style': 'background-color:' + zone
.getColor()
275 E('div', { 'class': 'cbi-tooltip' }, ifaces
)
279 renderWidget: function(section_id
, option_index
, cfgvalue
) {
280 var value
= (cfgvalue
!= null) ? cfgvalue
: this.default,
281 zone
= this.zones
.filter(function(z
) { return z
.getName() == value
})[0];
286 var forwards
= zone
.getForwardingsBy('src'),
289 for (var i
= 0; i
< forwards
.length
; i
++) {
290 var dzone
= forwards
[i
].getDestinationZone();
295 dzones
.push(this.renderZone(dzone
));
299 dzones
.push(E('label', { 'class': 'zonebadge zonebadge-empty' },
300 E('strong', this.defaults
.getForward())));
302 return E('div', { 'class': 'zone-forwards' }, [
303 E('div', { 'class': 'zone-src' }, this.renderZone(zone
)),
305 E('div', { 'class': 'zone-dest' }, dzones
)
310 var CBINetworkSelect
= form
.ListValue
.extend({
311 __name__
: 'CBI.NetworkSelect',
313 load: function(section_id
) {
314 return network
.getNetworks().then(L
.bind(function(networks
) {
315 this.networks
= networks
;
317 return this.super('load', section_id
);
321 filter: function(section_id
, value
) {
325 renderIfaceBadge: function(network
) {
326 var span
= E('span', { 'class': 'ifacebadge' }, network
.getName() + ': '),
327 devices
= network
.isBridge() ? network
.getDevices() : L
.toArray(network
.getDevice());
329 for (var j
= 0; j
< devices
.length
&& devices
[j
]; j
++) {
330 span
.appendChild(E('img', {
331 'title': devices
[j
].getI18n(),
332 'src': L
.resource('icons/%s%s.png'.format(devices
[j
].getType(), devices
[j
].isUp() ? '' : '_disabled'))
336 if (!devices
.length
) {
337 span
.appendChild(E('em', { 'class': 'hide-close' }, _('(no interfaces attached)')));
338 span
.appendChild(E('em', { 'class': 'hide-open' }, '-'));
344 renderWidget: function(section_id
, option_index
, cfgvalue
) {
345 var values
= L
.toArray((cfgvalue
!= null) ? cfgvalue
: this.default),
349 for (var i
= 0; i
< values
.length
; i
++)
350 checked
[values
[i
]] = true;
354 if (!this.multiple
&& (this.rmempty
|| this.optional
))
355 choices
[''] = E('em', _('unspecified'));
357 for (var i
= 0; i
< this.networks
.length
; i
++) {
358 var network
= this.networks
[i
],
359 name
= network
.getName();
361 if (name
== 'loopback' || name
== this.exclude
|| !this.filter(section_id
, name
))
364 if (this.novirtual
&& network
.isVirtual())
370 choices
[name
] = this.renderIfaceBadge(network
);
373 var widget
= new ui
.Dropdown(this.multiple
? values
: values
[0], choices
, {
374 id
: this.cbid(section_id
),
376 multiple
: this.multiple
,
377 optional
: this.optional
|| this.rmempty
,
378 select_placeholder
: E('em', _('unspecified')),
379 display_items
: this.display_size
|| this.size
|| 3,
380 dropdown_items
: this.dropdown_size
|| this.size
|| 5,
381 validate
: L
.bind(this.validate
, this, section_id
),
382 create
: !this.nocreate
,
384 '<li data-value="{{value}}">' +
385 '<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)">' +
386 '{{value}}: <em>('+_('create')+')</em>' +
391 return widget
.render();
394 textvalue: function(section_id
) {
395 var cfgvalue
= this.cfgvalue(section_id
),
396 values
= L
.toArray((cfgvalue
!= null) ? cfgvalue
: this.default),
399 for (var i
= 0; i
< (this.networks
|| []).length
; i
++) {
400 var network
= this.networks
[i
],
401 name
= network
.getName();
403 if (values
.indexOf(name
) == -1)
407 L
.dom
.append(rv
, ' ');
409 L
.dom
.append(rv
, this.renderIfaceBadge(network
));
413 rv
.appendChild(E('em', _('unspecified')));
419 var CBIDeviceSelect
= form
.ListValue
.extend({
420 __name__
: 'CBI.DeviceSelect',
422 load: function(section_id
) {
424 network
.getDevices(),
425 this.noaliases
? null : network
.getNetworks()
426 ]).then(L
.bind(function(data
) {
427 this.devices
= data
[0];
428 this.networks
= data
[1];
430 return this.super('load', section_id
);
434 filter: function(section_id
, value
) {
438 renderWidget: function(section_id
, option_index
, cfgvalue
) {
439 var values
= L
.toArray((cfgvalue
!= null) ? cfgvalue
: this.default),
444 for (var i
= 0; i
< values
.length
; i
++)
445 checked
[values
[i
]] = true;
449 if (!this.multiple
&& (this.rmempty
|| this.optional
))
450 choices
[''] = E('em', _('unspecified'));
452 for (var i
= 0; i
< this.devices
.length
; i
++) {
453 var device
= this.devices
[i
],
454 name
= device
.getName(),
455 type
= device
.getType();
457 if (name
== 'lo' || name
== this.exclude
|| !this.filter(section_id
, name
))
460 if (this.noaliases
&& type
== 'alias')
463 if (this.nobridges
&& type
== 'bridge')
466 if (this.noinactive
&& device
.isUp() == false)
471 'title': device
.getI18n(),
472 'src': L
.resource('icons/%s%s.png'.format(type
, device
.isUp() ? '' : '_disabled'))
474 E('span', { 'class': 'hide-open' }, [ name
]),
475 E('span', { 'class': 'hide-close'}, [ device
.getI18n() ])
478 var networks
= device
.getNetworks();
480 if (networks
.length
> 0)
481 L
.dom
.append(item
.lastChild
, [ ' (', networks
.join(', '), ')' ]);
486 choices
[name
] = item
;
490 if (this.networks
!= null) {
491 for (var i
= 0; i
< this.networks
.length
; i
++) {
492 var net
= this.networks
[i
],
493 device
= network
.instantiateDevice('@%s'.format(net
.getName()), net
),
494 name
= device
.getName();
496 if (name
== '@loopback' || name
== this.exclude
|| !this.filter(section_id
, name
))
499 if (this.noinactive
&& net
.isUp() == false)
504 'title': device
.getI18n(),
505 'src': L
.resource('icons/alias%s.png'.format(net
.isUp() ? '' : '_disabled'))
507 E('span', { 'class': 'hide-open' }, [ name
]),
508 E('span', { 'class': 'hide-close'}, [ device
.getI18n() ])
514 choices
[name
] = item
;
519 if (!this.nocreate
) {
520 var keys
= Object
.keys(checked
).sort();
522 for (var i
= 0; i
< keys
.length
; i
++) {
523 if (choices
.hasOwnProperty(keys
[i
]))
526 choices
[keys
[i
]] = E([
528 'title': _('Absent Interface'),
529 'src': L
.resource('icons/ethernet_disabled.png')
531 E('span', { 'class': 'hide-open' }, [ keys
[i
] ]),
532 E('span', { 'class': 'hide-close'}, [ '%s: "%h"'.format(_('Absent Interface'), keys
[i
]) ])
535 values
.push(keys
[i
]);
540 var widget
= new ui
.Dropdown(this.multiple
? values
: values
[0], choices
, {
541 id
: this.cbid(section_id
),
543 multiple
: this.multiple
,
544 optional
: this.optional
|| this.rmempty
,
545 select_placeholder
: E('em', _('unspecified')),
546 display_items
: this.display_size
|| this.size
|| 3,
547 dropdown_items
: this.dropdown_size
|| this.size
|| 5,
548 validate
: L
.bind(this.validate
, this, section_id
),
549 create
: !this.nocreate
,
551 '<li data-value="{{value}}">' +
552 '<img title="'+_('Custom Interface')+': "{{value}}"" src="'+L
.resource('icons/ethernet_disabled.png')+'" />' +
553 '<span class="hide-open">{{value}}</span>' +
554 '<span class="hide-close">'+_('Custom Interface')+': "{{value}}"</span>' +
558 return widget
.render();
563 return L
.Class
.extend({
564 ZoneSelect
: CBIZoneSelect
,
565 ZoneForwards
: CBIZoneForwards
,
566 NetworkSelect
: CBINetworkSelect
,
567 DeviceSelect
: CBIDeviceSelect
,