diff options
author | Stan Grishin <stangri@melmac.net> | 2021-03-10 04:32:00 +0000 |
---|---|---|
committer | Stan Grishin <stangri@melmac.net> | 2021-03-14 02:34:01 +0000 |
commit | d35cdc9dcc0e95e360a94a7b1c87df198768ac64 (patch) | |
tree | f34c44768bd89690bb81f3d9915a6b2d140c7638 /applications/luci-app-vpnbypass/htdocs/luci-static | |
parent | 2516852100eb6b115c0ad90883dfc5cfda16e076 (diff) |
luci-app-vpnbypass: transition to client-side rendering
Signed-off-by: Stan Grishin <stangri@melmac.net>
Diffstat (limited to 'applications/luci-app-vpnbypass/htdocs/luci-static')
-rw-r--r-- | applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js | 62 | ||||
-rw-r--r-- | applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js | 192 |
2 files changed, 254 insertions, 0 deletions
diff --git a/applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js b/applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js new file mode 100644 index 0000000000..b2d5d1f775 --- /dev/null +++ b/applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js @@ -0,0 +1,62 @@ +// Copyright 2021 Stan Grishin (stangri@melmac.net) +// Many thanks to [@vsviridov](https://github.com/vsviridov) for help with transition to JS + +'use strict'; +'require form'; +'require uci'; +'require view'; +'require vpnbypass.widgets as widgets'; + +var pkg = { + get Name() { return 'vpnbypass'; }, + get URL() { return 'https://docs.openwrt.melmac.net/' + pkg.Name + '/'; } +}; + +return view.extend({ + load: function () { + return Promise.all([ + uci.load(pkg.Name), + uci.load('dhcp') + ]); + }, + + render: function (data) { + + var m, d, s, o; + + m = new form.Map(pkg.Name, _('VPN Bypass')); + + s = m.section(form.NamedSection, 'config', pkg.Name); + + o = s.option(widgets.Status, '', _('Service Status')); + + o = s.option(widgets.Buttons, '', _('Service Control')); + + o = s.option(form.DynamicList, 'localport', _('Local Ports to Bypass'), _('Local ports to trigger VPN Bypass.')); + o.datatype = 'portrange'; + o.addremove = false; + o.optional = false; + + o = s.option(form.DynamicList, 'remoteport', _('Remote Ports to Bypass'), _('Remote ports to trigger VPN Bypass.')); + o.datatype = 'portrange'; + o.addremove = false; + o.optional = false; + + o = s.option(form.DynamicList, 'localsubnet', _('Local IP Addresses to Bypass'), _('Local IP addresses or subnets with direct internet access.')); + o.datatype = 'ip4addr'; + o.addremove = false; + o.optional = false; + + o = s.option(form.DynamicList, 'remotesubnet', _('Remote IP Addresses to Bypass'), _('Remote IP addresses or subnets which will be accessed directly.')); + o.datatype = 'ip4addr'; + o.addremove = false; + o.optional = false; + + d = new form.Map('dhcp'); + s = d.section(form.TypedSection, 'dnsmasq'); + s.anonymous = true; + o = s.option(form.DynamicList, 'ipset', _('Domains to Bypass'), _('Domains to be accessed directly, see %sREADME%s for syntax.').format('<a href="' + pkg.URL + '#bypass-domains-formatsyntax" target="_blank" rel="noreferrer noopener">', '</a>')); + + return Promise.all([m.render(), d.render()]); + } +}); diff --git a/applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js b/applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js new file mode 100644 index 0000000000..f14dd21d74 --- /dev/null +++ b/applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js @@ -0,0 +1,192 @@ +// Thsis file wouldn't have been possible without help from [@vsviridov](https://github.com/vsviridov) + +'require ui'; +'require rpc'; +'require form'; + +var pkg = { + get Name() { return 'vpnbypass'; } +}; + +var _getInitList = rpc.declare({ + object: 'luci.' + pkg.Name, + method: 'getInitList', + params: ['name'] +}); + +var _setInitAction = rpc.declare({ + object: 'luci.' + pkg.Name, + method: 'setInitAction', + params: ['name', 'action'], + expect: { result: false } +}); + +var _getInitStatus = rpc.declare({ + object: 'luci.' + pkg.Name, + method: 'getInitStatus', + params: ['name'] +}); + +var RPC = { + listeners: [], + on: function on(event, callback) { + var pair = { event: event, callback: callback } + this.listeners.push(pair); + return function unsubscribe() { + this.listeners = this.listeners.filter(function (listener) { + return listener !== pair; + }); + }.bind(this); + }, + emit: function emit(event, data) { + this.listeners.forEach(function (listener) { + if (listener.event === event) { + listener.callback(data); + } + }); + }, + getInitList: function getInitList(name) { + _getInitList(name).then(function (result) { + this.emit('getInitList', result); + }.bind(this)); + + }, + getInitStatus: function getInitStatus(name) { + _getInitStatus(name).then(function (result) { + this.emit('getInitStatus', result); + }.bind(this)); + }, + setInitAction: function setInitAction(name, action) { + _setInitAction(name, action).then(function (result) { + this.emit('setInitAction', result); + }.bind(this)); + } +} + +var statusCBI = form.DummyValue.extend({ + renderWidget: function (section) { + var status = E('span', {}, _("Quering") + "..."); + RPC.on('getInitStatus', function (reply) { + if (reply[pkg.Name].version) { + if (reply[pkg.Name].running) { + status.innerText = _("Running (version: %s)").format(reply[pkg.Name].version); + } + else { + if (reply[pkg.Name].enabled) { + status.innerText = _("Stopped (version: %s)").format(reply[pkg.Name].version); + } + else { + status.innerText = _("Stopped (Disabled)"); + } + } + } + else { + status.innerText = _("Not installed or not found") + } + }); + return E('div', {}, [status]); + } +}); + +var buttonsCBI = form.DummyValue.extend({ + renderWidget: function (section) { + + var btn_gap = E('span', {}, ' '); + var btn_gap_long = E('span', {}, ' '); + + var btn_start = E('button', { + 'class': 'btn cbi-button cbi-button-apply', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Starting %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'start'); + } + }, _('Start')); + + var btn_action = E('button', { + 'class': 'btn cbi-button cbi-button-apply', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Restarting %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'restart'); + } + }, _('Restart')); + + var btn_stop = E('button', { + 'class': 'btn cbi-button cbi-button-reset', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Stopping %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'stop'); + } + }, _('Stop')); + + var btn_enable = E('button', { + 'class': 'btn cbi-button cbi-button-apply', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Enabling %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'enable'); + } + }, _('Enable')); + + var btn_disable = E('button', { + 'class': 'btn cbi-button cbi-button-reset', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Disabling %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'disable'); + } + }, _('Disable')); + + RPC.on('getInitStatus', function (reply) { + if (reply[pkg.Name].version) { + if (reply[pkg.Name].enabled) { + btn_enable.disabled = true; + btn_disable.disabled = false; + if (reply[pkg.Name].running) { + btn_start.disabled = true; + btn_action.disabled = false; + btn_stop.disabled = false; + } + else { + btn_start.disabled = false; + btn_action.disabled = true; + btn_stop.disabled = true; + } + } + else { + btn_start.disabled = true; + btn_action.disabled = true; + btn_stop.disabled = true; + btn_enable.disabled = false; + btn_disable.disabled = true; + } + } + }); + + RPC.getInitStatus(pkg.Name); + + return E('div', {}, [btn_start, btn_gap, btn_action, btn_gap, btn_stop, btn_gap_long, btn_enable, btn_gap, btn_disable]); + } +}); + +RPC.on('setInitAction', function (reply) { + ui.hideModal(); + RPC.getInitStatus(pkg.Name); +}); + +return L.Class.extend({ + Status: statusCBI, + Buttons: buttonsCBI +}); |