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),
35 if (this.allowlocal) {
36 choices[''] = E('span', {
38 'style': 'background-color:' + firewall.getColorForName(null)
40 E('strong', _('Device')),
41 (this.allowany || this.allowlocal)
42 ? ' (%s)'.format(this.option != 'dest' ? _('output') : _('input')) : ''
45 else if (!this.multiple && (this.rmempty || this.optional)) {
46 choices[''] = E('span', {
48 'style': 'background-color:' + firewall.getColorForName(null)
49 }, E('em', _('unspecified')));
53 choices['*'] = E('span', {
55 'style': 'background-color:' + firewall.getColorForName(null)
57 E('strong', _('Any zone')),
58 (this.allowany && this.allowlocal && this.option != 'src') ? ' (%s)'.format(_('forward')) : ''
62 for (var i = 0; i < this.zones.length; i++) {
63 var zone = this.zones[i],
64 name = zone.getName(),
65 networks = zone.getNetworks(),
68 if (!this.filter(section_id, name))
71 for (var j = 0; j < networks.length; j++) {
72 var network = this.lookupNetwork(networks[j]);
77 var span = E('span', {
78 'class': 'ifacebadge' + (network.getName() == this.network ? ' ifacebadge-active' : '')
79 }, network.getName() + ': ');
81 var devices = network.isBridge() ? network.getDevices() : L.toArray(network.getDevice());
83 for (var k = 0; k < devices.length; k++) {
84 span.appendChild(E('img', {
85 'title': devices[k].getI18n(),
86 'src': L.resource('icons/%s%s.png'.format(devices[k].getType(), devices[k].isUp() ? '' : '_disabled'))
91 span.appendChild(E('em', _('(empty)')));
97 ifaces.push(E('em', _('(empty)')));
99 choices[name] = E('span', {
100 'class': 'zonebadge',
101 'style': 'background-color:' + zone.getColor()
102 }, [ E('strong', name) ].concat(ifaces));
105 var widget = new ui.Dropdown(values, choices, {
106 id: this.cbid(section_id),
108 multiple: this.multiple,
109 optional: this.optional || this.rmempty,
110 select_placeholder: E('em', _('unspecified')),
111 display_items: this.display_size || this.size || 3,
112 dropdown_items: this.dropdown_size || this.size || 5,
113 validate: L.bind(this.validate, this, section_id),
114 create: !this.nocreate,
116 '<li data-value="{{value}}">' +
117 '<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)">' +
118 '<strong>{{value}}:</strong> <em>('+_('create')+')</em>' +
123 var elem = widget.render();
125 if (this.option == 'src') {
126 elem.addEventListener('cbi-dropdown-change', L.bind(function(ev) {
127 var opt = this.map.lookupOption('dest', section_id),
128 val = ev.detail.instance.getValue();
133 var cbid = opt[0].cbid(section_id),
134 label = document.querySelector('label[for="widget.%s"]'.format(cbid)),
135 node = document.getElementById(cbid);
137 L.dom.content(label, val == '' ? _('Output zone') : _('Destination zone'));
140 if (L.dom.callClassMethod(node, 'getValue') == '')
141 L.dom.callClassMethod(node, 'setValue', '*');
143 var emptyval = node.querySelector('[data-value=""]'),
144 anyval = node.querySelector('[data-value="*"]');
146 L.dom.content(anyval.querySelector('span'), E('strong', _('Any zone')));
148 if (emptyval != null)
149 emptyval.parentNode.removeChild(emptyval);
152 var anyval = node.querySelector('[data-value="*"]'),
153 emptyval = node.querySelector('[data-value=""]') || anyval.cloneNode(true);
155 emptyval.removeAttribute('display');
156 emptyval.removeAttribute('selected');
157 emptyval.setAttribute('data-value', '');
159 L.dom.content(emptyval.querySelector('span'), [
160 E('strong', _('Device')), ' (%s)'.format(_('input'))
163 L.dom.content(anyval.querySelector('span'), [
164 E('strong', _('Any zone')), ' (%s)'.format(_('forward'))
167 anyval.parentNode.insertBefore(emptyval, anyval);
172 else if (this.option == 'dest') {
173 for (var i = 0; i < this.section.children.length; i++) {
174 if (this.section.children[i].option == 'src') {
175 if (!this.section.children[i].cfgvalue(section_id)) {
176 var emptyval = elem.querySelector('[data-value=""]');
178 if (emptyval != null)
179 emptyval.parentNode.removeChild(emptyval);
189 var CBIZoneForwards = form.DummyValue.extend({
190 __name__: 'CBI.ZoneForwards',
192 load: function(section_id) {
193 return Promise.all([ firewall.getDefaults(), firewall.getZones(), network.getNetworks() ]).then(L.bind(function(dzn) {
194 this.defaults = dzn[0];
196 this.networks = dzn[2];
198 return this.super('load', section_id);
202 renderZone: function(zone) {
203 var name = zone.getName(),
204 networks = zone.getNetworks(),
207 for (var j = 0; j < networks.length; j++) {
208 var network = this.networks.filter(function(net) { return net.getName() == networks[j] })[0];
213 var span = E('span', {
214 'class': 'ifacebadge' + (network.getName() == this.network ? ' ifacebadge-active' : '')
215 }, network.getName() + ': ');
217 var devices = network.isBridge() ? network.getDevices() : L.toArray(network.getDevice());
219 for (var k = 0; k < devices.length && devices[k]; k++) {
220 span.appendChild(E('img', {
221 'title': devices[k].getI18n(),
222 'src': L.resource('icons/%s%s.png'.format(devices[k].getType(), devices[k].isUp() ? '' : '_disabled'))
227 span.appendChild(E('em', _('(empty)')));
233 ifaces.push(E('span', { 'class': 'ifacebadge' }, E('em', _('(empty)'))));
236 'class': 'zonebadge cbi-tooltip-container',
237 'style': 'background-color:' + zone.getColor()
240 E('div', { 'class': 'cbi-tooltip' }, ifaces)
244 renderWidget: function(section_id, option_index, cfgvalue) {
245 var value = (cfgvalue != null) ? cfgvalue : this.default,
246 zone = this.zones.filter(function(z) { return z.getName() == value })[0];
251 var forwards = zone.getForwardingsBy('src'),
254 for (var i = 0; i < forwards.length; i++) {
255 var dzone = forwards[i].getDestinationZone();
260 dzones.push(this.renderZone(dzone));
264 dzones.push(E('label', { 'class': 'zonebadge zonebadge-empty' },
265 E('strong', this.defaults.getForward())));
267 return E('div', { 'class': 'zone-forwards' }, [
268 E('div', { 'class': 'zone-src' }, this.renderZone(zone)),
270 E('div', { 'class': 'zone-dest' }, dzones)
275 var CBINetworkSelect = form.ListValue.extend({
276 __name__: 'CBI.NetworkSelect',
278 load: function(section_id) {
279 return network.getNetworks().then(L.bind(function(networks) {
280 this.networks = networks;
282 return this.super('load', section_id);
286 filter: function(section_id, value) {
290 renderIfaceBadge: function(network) {
291 var span = E('span', { 'class': 'ifacebadge' }, network.getName() + ': '),
292 devices = network.isBridge() ? network.getDevices() : L.toArray(network.getDevice());
294 for (var j = 0; j < devices.length && devices[j]; j++) {
295 span.appendChild(E('img', {
296 'title': devices[j].getI18n(),
297 'src': L.resource('icons/%s%s.png'.format(devices[j].getType(), devices[j].isUp() ? '' : '_disabled'))
301 if (!devices.length) {
302 span.appendChild(E('em', { 'class': 'hide-close' }, _('(no interfaces attached)')));
303 span.appendChild(E('em', { 'class': 'hide-open' }, '-'));
309 renderWidget: function(section_id, option_index, cfgvalue) {
310 var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default),
314 for (var i = 0; i < values.length; i++)
315 checked[values[i]] = true;
319 if (!this.multiple && (this.rmempty || this.optional))
320 choices[''] = E('em', _('unspecified'));
322 for (var i = 0; i < this.networks.length; i++) {
323 var network = this.networks[i],
324 name = network.getName();
326 if (name == 'loopback' || !this.filter(section_id, name))
329 if (this.novirtual && network.isVirtual())
335 choices[name] = this.renderIfaceBadge(network);
338 var widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
339 id: this.cbid(section_id),
341 multiple: this.multiple,
342 optional: this.optional || this.rmempty,
343 select_placeholder: E('em', _('unspecified')),
344 display_items: this.display_size || this.size || 3,
345 dropdown_items: this.dropdown_size || this.size || 5,
346 validate: L.bind(this.validate, this, section_id),
347 create: !this.nocreate,
349 '<li data-value="{{value}}">' +
350 '<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)">' +
351 '{{value}}: <em>('+_('create')+')</em>' +
356 return widget.render();
359 textvalue: function(section_id) {
360 var cfgvalue = this.cfgvalue(section_id),
361 values = L.toArray((cfgvalue != null) ? cfgvalue : this.default),
364 for (var i = 0; i < (this.networks || []).length; i++) {
365 var network = this.networks[i],
366 name = network.getName();
368 if (values.indexOf(name) == -1)
372 L.dom.append(rv, ' ');
374 L.dom.append(rv, this.renderIfaceBadge(network));
378 rv.appendChild(E('em', _('unspecified')));
385 return L.Class.extend({
386 ZoneSelect: CBIZoneSelect,
387 ZoneForwards: CBIZoneForwards,
388 NetworkSelect: CBINetworkSelect