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=""]');
155 if (emptyval == null) {
156 emptyval = anyval.cloneNode(true);
157 emptyval.removeAttribute('display');
158 emptyval.removeAttribute('selected');
159 emptyval.setAttribute('data-value', '');
162 L.dom.content(emptyval.querySelector('span'), [
163 E('strong', _('Device')), ' (%s)'.format(_('input'))
166 L.dom.content(anyval.querySelector('span'), [
167 E('strong', _('Any zone')), ' (%s)'.format(_('forward'))
170 anyval.parentNode.insertBefore(emptyval, anyval);
175 else if (this.option == 'dest') {
176 for (var i = 0; i < this.section.children.length; i++) {
177 var opt = this.section.children[i];
178 if (opt.option == 'src') {
179 if (!opt.cfgvalue(section_id) && !opt.default) {
180 var emptyval = elem.querySelector('[data-value=""]');
182 if (emptyval != null)
183 emptyval.parentNode.removeChild(emptyval);
193 var CBIZoneForwards = form.DummyValue.extend({
194 __name__: 'CBI.ZoneForwards',
196 load: function(section_id) {
197 return Promise.all([ firewall.getDefaults(), firewall.getZones(), network.getNetworks() ]).then(L.bind(function(dzn) {
198 this.defaults = dzn[0];
200 this.networks = dzn[2];
202 return this.super('load', section_id);
206 renderZone: function(zone) {
207 var name = zone.getName(),
208 networks = zone.getNetworks(),
211 for (var j = 0; j < networks.length; j++) {
212 var network = this.networks.filter(function(net) { return net.getName() == networks[j] })[0];
217 var span = E('span', {
218 'class': 'ifacebadge' + (network.getName() == this.network ? ' ifacebadge-active' : '')
219 }, network.getName() + ': ');
221 var devices = network.isBridge() ? network.getDevices() : L.toArray(network.getDevice());
223 for (var k = 0; k < devices.length && devices[k]; k++) {
224 span.appendChild(E('img', {
225 'title': devices[k].getI18n(),
226 'src': L.resource('icons/%s%s.png'.format(devices[k].getType(), devices[k].isUp() ? '' : '_disabled'))
231 span.appendChild(E('em', _('(empty)')));
237 ifaces.push(E('span', { 'class': 'ifacebadge' }, E('em', _('(empty)'))));
240 'class': 'zonebadge cbi-tooltip-container',
241 'style': 'background-color:' + zone.getColor()
244 E('div', { 'class': 'cbi-tooltip' }, ifaces)
248 renderWidget: function(section_id, option_index, cfgvalue) {
249 var value = (cfgvalue != null) ? cfgvalue : this.default,
250 zone = this.zones.filter(function(z) { return z.getName() == value })[0];
255 var forwards = zone.getForwardingsBy('src'),
258 for (var i = 0; i < forwards.length; i++) {
259 var dzone = forwards[i].getDestinationZone();
264 dzones.push(this.renderZone(dzone));
268 dzones.push(E('label', { 'class': 'zonebadge zonebadge-empty' },
269 E('strong', this.defaults.getForward())));
271 return E('div', { 'class': 'zone-forwards' }, [
272 E('div', { 'class': 'zone-src' }, this.renderZone(zone)),
274 E('div', { 'class': 'zone-dest' }, dzones)
279 var CBINetworkSelect = form.ListValue.extend({
280 __name__: 'CBI.NetworkSelect',
282 load: function(section_id) {
283 return network.getNetworks().then(L.bind(function(networks) {
284 this.networks = networks;
286 return this.super('load', section_id);
290 filter: function(section_id, value) {
294 renderIfaceBadge: function(network) {
295 var span = E('span', { 'class': 'ifacebadge' }, network.getName() + ': '),
296 devices = network.isBridge() ? network.getDevices() : L.toArray(network.getDevice());
298 for (var j = 0; j < devices.length && devices[j]; j++) {
299 span.appendChild(E('img', {
300 'title': devices[j].getI18n(),
301 'src': L.resource('icons/%s%s.png'.format(devices[j].getType(), devices[j].isUp() ? '' : '_disabled'))
305 if (!devices.length) {
306 span.appendChild(E('em', { 'class': 'hide-close' }, _('(no interfaces attached)')));
307 span.appendChild(E('em', { 'class': 'hide-open' }, '-'));
313 renderWidget: function(section_id, option_index, cfgvalue) {
314 var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default),
318 for (var i = 0; i < values.length; i++)
319 checked[values[i]] = true;
323 if (!this.multiple && (this.rmempty || this.optional))
324 choices[''] = E('em', _('unspecified'));
326 for (var i = 0; i < this.networks.length; i++) {
327 var network = this.networks[i],
328 name = network.getName();
330 if (name == 'loopback' || !this.filter(section_id, name))
333 if (this.novirtual && network.isVirtual())
339 choices[name] = this.renderIfaceBadge(network);
342 var widget = new ui.Dropdown(this.multiple ? values : values[0], choices, {
343 id: this.cbid(section_id),
345 multiple: this.multiple,
346 optional: this.optional || this.rmempty,
347 select_placeholder: E('em', _('unspecified')),
348 display_items: this.display_size || this.size || 3,
349 dropdown_items: this.dropdown_size || this.size || 5,
350 validate: L.bind(this.validate, this, section_id),
351 create: !this.nocreate,
353 '<li data-value="{{value}}">' +
354 '<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)">' +
355 '{{value}}: <em>('+_('create')+')</em>' +
360 return widget.render();
363 textvalue: function(section_id) {
364 var cfgvalue = this.cfgvalue(section_id),
365 values = L.toArray((cfgvalue != null) ? cfgvalue : this.default),
368 for (var i = 0; i < (this.networks || []).length; i++) {
369 var network = this.networks[i],
370 name = network.getName();
372 if (values.indexOf(name) == -1)
376 L.dom.append(rv, ' ');
378 L.dom.append(rv, this.renderIfaceBadge(network));
382 rv.appendChild(E('em', _('unspecified')));
389 return L.Class.extend({
390 ZoneSelect: CBIZoneSelect,
391 ZoneForwards: CBIZoneForwards,
392 NetworkSelect: CBINetworkSelect