luci-app-udpxy: fix luci-app-udpxy
authorFeng Cheng <fengcheng@lidig.com>
Tue, 30 Jul 2024 10:33:07 +0000 (18:33 +0800)
committerPaul Donald <newtwen+github@gmail.com>
Sun, 15 Sep 2024 09:36:50 +0000 (11:36 +0200)
modified bind and source option class to automatically generate possible values
Changed ipaddr in datatype to ip4addr, udpxy only supports ipv4
add option source_network

Signed-off-by: Feng Cheng <fengcheng@lidig.com>
applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js
applications/luci-app-udpxy/po/templates/udpxy.pot

index 93aa9c2c88db386dbcf5132c0a8bfa45613f4731..640d77155da2c2daf823300945a2bec2be1ccb7d 100644 (file)
@@ -1,6 +1,153 @@
 'use strict';
 'require form';
 'require view';
+'require network';
+'require ui';
+'require tools.widgets as widgets';
+
+var CBIBindSelect = form.ListValue.extend({
+       __name__: 'CBI.CBIBindSelect',
+
+       load: function(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: function(section_id, value) {
+               return true;
+       },
+
+       renderWidget: function(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 (var i = 0; i < this.devices.length; i++) {
+                       var device = this.devices[i],
+                           name = device.getName(),
+                           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;
+
+                       var item = E([
+                               E('img', {
+                                       'title': device.getI18n(),
+                                       'src': L.resource('icons/%s%s.png'.format(type, device.isUp() ? '' : '_disabled'))
+                               }),
+                               E('span', { 'class': 'hide-open' }, [ name ]),
+                               E('span', { 'class': 'hide-close'}, [ device.getI18n() ])
+                       ]);
+
+                       var 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 (var i = 0; i < this.networks.length; i++) {
+                               var net = this.networks[i],
+                                   device = network.instantiateDevice('@%s'.format(net.getName()), net),
+                                   name = device.getName();
+
+                               if (name == '@loopback' || name == this.exclude || !this.filter(section_id, name))
+                                       continue;
+
+                               if (this.noinactive && net.isUp() == false)
+                                       continue;
+
+                               var item = E([
+                                       E('img', {
+                                               'title': device.getI18n(),
+                                               'src': L.resource('icons/alias%s.png'.format(net.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.nocreate) {
+                       var keys = Object.keys(checked).sort(L.naturalCompare);
+
+                       for (var i = 0; i < keys.length; i++) {
+                               if (choices.hasOwnProperty(keys[i]))
+                                       continue;
+
+                               choices[keys[i]] = E([
+                                       E('img', {
+                                               'title': _('Absent Interface'),
+                                               'src': L.resource('icons/ethernet_disabled.png')
+                                       }),
+                                       E('span', { 'class': 'hide-open' }, [ keys[i] ]),
+                                       E('span', { 'class': 'hide-close'}, [ '%s: "%h"'.format(_('Absent Interface'), keys[i]) ])
+                               ]);
+
+                               values.push(keys[i]);
+                               order.push(keys[i]);
+                       }
+               }
+
+               var 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')),
+                       custom_placeholder: this.placeholder || _('custom'),
+                       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="hide-open">{{value}}</span>' +
+                                       '<span class="hide-close">'+_('Custom Value')+': "{{value}}"</span>' +
+                               '</li>'
+               });
+
+               return widget.render();
+       },
+});
 
 return view.extend({
        render: function () {
@@ -27,18 +174,26 @@ return view.extend({
 
                o = s.option(form.Flag, 'status', _('Client statistics'));
 
-               o = s.option(form.Value, 'bind', _('HTTP Listen interface'));
-               o.datatype = 'or(ipaddr, network)';
-               o.placeholder = '0.0.0.0 || lan1';
+               o = s.option(CBIBindSelect, 'bind', _('HTTP Listen interface'));
+               o.datatype = 'or(ip4addr, device)';
+               o.placeholder = '0.0.0.0 || br-lan';
 
                o = s.option(form.Value, 'port', _('Port'), _('Default') + ' : ' + '%s'.format('4022'));
                o.datatype = 'port';
                o.placeholder = '4022';
 
-               o = s.option(form.Value, 'source', _('Multicast subscribe source interface'), _('Default') + ' : ' + '%s'.format('0.0.0.0'));
-               o.datatype = 'or(ipaddr, network)';
-               o.placeholder = '0.0.0.0 || br-lan';
-
+               o = s.option(widgets.NetworkSelect, 'source_network',
+                       _('Multicast subscribe Source Network'),
+                       _('When the network is reloaded, the udpxy is reloaded'),
+               );
+               o.datatype = 'network';
+
+               o = s.option(CBIBindSelect, 'source',
+                       _('Multicast subscribe source interface'),
+                       _('Default') + ' : ' + '%s'.format('0.0.0.0'),
+               );
+               o.datatype = 'or(ip4addr, device)';
+               o.placeholder = '0.0.0.0 || lan1';
 
                o = s.option(form.Value, 'max_clients', _('Client amount upper limit'));
                o.datatype = 'range(1, 5000)';
index 2cb108fe50e49fbc4df7ac5be8eeb77c5ba1dc85..edb00fc2ed4cce86340c23f84b6d508541dc0614 100644 (file)
@@ -1,37 +1,46 @@
 msgid ""
 msgstr "Content-Type: text/plain; charset=UTF-8"
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:52
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:207
 msgid "-1 is all."
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:56
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:211
 msgid "-1 is unlimited."
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:52
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:117
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:121
+msgid "Absent Interface"
+msgstr ""
+
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:207
 msgid "Buffer message amount"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:56
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:211
 msgid "Buffer time limit"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:43
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:198
 msgid "Client amount upper limit"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:28
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:175
 msgid "Client statistics"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:34
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:38
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:46
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:144
+msgid "Custom Value"
+msgstr ""
+
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:181
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:193
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:201
 msgid "Default"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:16
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:163
 msgid "Enabled"
 msgstr ""
 
@@ -39,57 +48,74 @@ msgstr ""
 msgid "Grant UCI access for luci-app-udpxy"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:30
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:177
 msgid "HTTP Listen interface"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:49
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:204
 msgid "Ingress buffer size"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:46
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:201
 msgid "Log file"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:38
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:186
+msgid "Multicast subscribe Source Network"
+msgstr ""
+
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:192
 msgid "Multicast subscribe source interface"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:60
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:215
 msgid "Nice increment"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:34
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:181
 msgid "Port"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:64
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:219
 msgid "Renew multicast subscription periodicity"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:22
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:169
 msgid "Respawn"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:49
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:204
 msgid "Unit: bytes, Kb, Mb; Max 2097152 bytes"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:64
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:219
 msgid "Unit: seconds; 0 is skip."
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:25
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:172
 msgid "Verbose logging"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:9
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:187
+msgid "When the network is reloaded, the udpxy is reloaded"
+msgstr ""
+
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:136
+msgid "custom"
+msgstr ""
+
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:156
 #: applications/luci-app-udpxy/root/usr/share/luci/menu.d/luci-app-udpxy.json:3
 msgid "udpxy"
 msgstr ""
 
-#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:10
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:157
 msgid ""
 "udpxy is an IPTV stream relay, a UDP-to-HTTP multicast traffic relay daemon "
 "which forwards multicast UDP streams to HTTP clients."
 msgstr ""
+
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:39
+#: applications/luci-app-udpxy/htdocs/luci-static/resources/view/udpxy.js:135
+msgid "unspecified"
+msgstr ""