luci-app-firewall: fix cbi form for rules
authorJo-Philipp Wich <jo@mein.io>
Sun, 21 Jul 2019 09:12:13 +0000 (11:12 +0200)
committerJo-Philipp Wich <jo@mein.io>
Sun, 21 Jul 2019 20:35:24 +0000 (22:35 +0200)
 - Set src/dest defaults only in initial section create state, otherwise it
   is impossible to specify output rules
 - Get rid of dest_remote/dest_local widget switching and implement change
   logic directly in tools.widgets.CBIZoneSelect
 - Remove leftover debug code

Ref: https://github.com/openwrt/luci/issues/2889
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js
modules/luci-base/htdocs/luci-static/resources/tools/widgets.js

index e67397268c1c4c7876e221ae462808453bb87038..4252cf36914109828b9d8cfd21aff4e389e8da80 100644 (file)
@@ -144,6 +144,27 @@ return L.view.extend({
                        return uci.get('firewall', section_id, 'name') || _('Unnamed rule');
                };
 
+               s.handleAdd = function(ev) {
+                       var config_name = this.uciconfig || this.map.config,
+                           section_id = uci.add(config_name, this.sectiontype),
+                           opt1, opt2;
+
+                       for (var i = 0; i < this.children.length; i++)
+                               if (this.children[i].option == 'src')
+                                       opt1 = this.children[i];
+                               else if (this.children[i].option == 'dest')
+                                       opt2 = this.children[i];
+
+                       opt1.default = 'wan';
+                       opt2.default = 'lan';
+
+                       this.addedSection = section_id;
+                       this.renderMoreOptionsModal(section_id);
+
+                       delete opt1.default;
+                       delete opt2.default;
+               };
+
                o = s.taboption('general', form.Value, 'name', _('Name'));
                o.placeholder = _('Unnamed rule');
                o.modalonly = true;
@@ -243,7 +264,6 @@ return L.view.extend({
                o.nocreate = true;
                o.allowany = true;
                o.allowlocal = 'src';
-               o.default = 'wan';
 
                o = s.taboption('advanced', form.Value, 'src_mac', _('Source MAC address'));
                o.modalonly = true;
@@ -276,22 +296,11 @@ return L.view.extend({
                o.depends('proto', 'tcp udp');
                o.depends('proto', 'tcpudp');
 
-               o = s.taboption('general', widgets.ZoneSelect, 'dest_local', _('Output zone'));
-               o.modalonly = true;
-               o.nocreate = true;
-               o.allowany = true;
-               o.alias = 'dest';
-               o.default = 'wan';
-               o.depends('src', '');
-
-               o = s.taboption('general', widgets.ZoneSelect, 'dest_remote', _('Destination zone'));
+               o = s.taboption('general', widgets.ZoneSelect, 'dest', _('Destination zone'));
                o.modalonly = true;
                o.nocreate = true;
                o.allowany = true;
                o.allowlocal = true;
-               o.alias = 'dest';
-               o.default = 'lan';
-               o.depends({'src': '', '!reverse': true});
 
                o = s.taboption('general', form.Value, 'dest_ip', _('Destination address'));
                o.modalonly = true;
@@ -366,9 +375,6 @@ return L.view.extend({
                o.modalonly = true;
                o.default = o.disabled;
 
-               return m.render().catch(function(e) {
-                       console.debug('render fail')
-               });
-
+               return m.render();
        }
 });
index 7f2997f17367c6ef67ca35ee6135699f0cf38d13..90e2512a685151855b25f3d2537fc4288566a75e 100644 (file)
@@ -39,7 +39,7 @@ var CBIZoneSelect = form.ListValue.extend({
                        }, [
                                E('strong', _('Device')),
                                (this.allowany || this.allowlocal)
-                                       ? ' (%s)'.format(this.alias != 'dest' ? _('output') : _('input')) : ''
+                                       ? ' (%s)'.format(this.option != 'dest' ? _('output') : _('input')) : ''
                        ]);
                }
                else if (!this.multiple && (this.rmempty || this.optional)) {
@@ -55,7 +55,7 @@ var CBIZoneSelect = form.ListValue.extend({
                                'style': 'background-color:' + firewall.getColorForName(null)
                        }, [
                                E('strong', _('Any zone')),
-                               (this.allowany && this.allowlocal) ? ' (%s)'.format(_('forward')) : ''
+                               (this.allowany && this.allowlocal && this.option != 'src') ? ' (%s)'.format(_('forward')) : ''
                        ]);
                }
 
@@ -120,7 +120,69 @@ var CBIZoneSelect = form.ListValue.extend({
                                '</li>'
                });
 
-               return widget.render();
+               var elem = widget.render();
+
+               if (this.option == 'src') {
+                       elem.addEventListener('cbi-dropdown-change', L.bind(function(ev) {
+                               var opt = this.map.lookupOption('dest', section_id),
+                                   val = ev.detail.instance.getValue();
+
+                               if (opt == null)
+                                       return;
+
+                               var cbid = opt[0].cbid(section_id),
+                                   label = document.querySelector('label[for="widget.%s"]'.format(cbid)),
+                                   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', '*');
+
+                                       var emptyval = node.querySelector('[data-value=""]'),
+                                           anyval = node.querySelector('[data-value="*"]');
+
+                                       L.dom.content(anyval.querySelector('span'), E('strong', _('Any zone')));
+
+                                       if (emptyval != null)
+                                               emptyval.parentNode.removeChild(emptyval);
+                               }
+                               else {
+                                       var anyval = node.querySelector('[data-value="*"]'),
+                                           emptyval = node.querySelector('[data-value=""]') || anyval.cloneNode(true);
+
+                                       emptyval.removeAttribute('display');
+                                       emptyval.removeAttribute('selected');
+                                       emptyval.setAttribute('data-value', '');
+
+                                       L.dom.content(emptyval.querySelector('span'), [
+                                               E('strong', _('Device')), ' (%s)'.format(_('input'))
+                                       ]);
+
+                                       L.dom.content(anyval.querySelector('span'), [
+                                               E('strong', _('Any zone')), ' (%s)'.format(_('forward'))
+                                       ]);
+
+                                       anyval.parentNode.insertBefore(emptyval, anyval);
+                               }
+
+                       }, this));
+               }
+               else if (this.option == 'dest') {
+                       for (var i = 0; i < this.section.children.length; i++) {
+                               if (this.section.children[i].option == 'src') {
+                                       if (!this.section.children[i].cfgvalue(section_id)) {
+                                               var emptyval = elem.querySelector('[data-value=""]');
+
+                                               if (emptyval != null)
+                                                       emptyval.parentNode.removeChild(emptyval);
+                                       }
+                               }
+                       }
+               }
+
+               return elem;
        },
 });