Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • autinerd/experimental-openwrt-24.10
  • experimental
  • feature/addMikrotikwAP
  • master
  • nrb/airmax-test
  • nrb/ar9344-reset-sequence
  • nrb/ex400-remove-wps
  • nrb/gluon-master-cpe510
  • nrb/test-radv-filter
  • nrbffs/fastd-remove-delay
  • nrbffs/netgear-ex6120
  • v2018.2.2-ffs
  • v2018.2.3-ffs
  • v2019.1-ffs
  • v2019.1.1-ffs
  • v2019.1.2-ffs
  • v2020.1-ffs
  • v2020.1.1-ffs
  • v2020.1.3-ffs
  • v2020.2-ffs
  • v2020.2.1-ffs
  • v2020.2.2-ffs
  • v2020.2.3-ffs
  • v2021.1-ffs
  • v2021.1.1-ffs
  • v2021.1.2-ffs
  • v2022.1.1-ffs
  • v2022.1.3-ffs
  • v2022.1.4-ffs
  • v2023.1-ffs
  • v2023.2-ffs
  • v2023.2.2-ffs
  • v2023.2.3-ffs
  • v2023.2.4-ffs
  • experimental-2022-09-24
  • experimental-2022-09-24-base
  • experimental-2023-03-11
  • experimental-2023-03-11-base
  • experimental-2023-03-12
  • experimental-2023-03-12-base
  • experimental-2023-03-16
  • experimental-2023-03-16-base
  • experimental-2023-03-20
  • experimental-2023-03-20-base
  • experimental-2023-03-23
  • experimental-2023-03-23-base
  • experimental-2023-03-25
  • experimental-2023-03-25-base
  • experimental-2023-03-26
  • experimental-2023-03-26-base
  • experimental-2023-03-30
  • experimental-2023-03-30-base
  • experimental-2023-03-31
  • experimental-2023-03-31-base
  • experimental-2023-04-01
  • experimental-2023-04-01-base
  • experimental-2023-04-08
  • experimental-2023-04-08-base
  • experimental-2023-04-10
  • experimental-2023-04-10-base
  • experimental-2023-04-13
  • experimental-2023-04-13-base
  • experimental-2023-04-15
  • experimental-2023-04-15-base
  • experimental-2023-04-16
  • experimental-2023-04-16-base
  • experimental-2023-04-18
  • experimental-2023-04-18-base
  • experimental-2023-04-20
  • experimental-2023-04-20-base
  • experimental-2023-04-26
  • experimental-2023-04-26-base
  • experimental-2023-04-28
  • experimental-2023-04-28-base
  • experimental-2023-04-30
  • experimental-2023-04-30-base
  • experimental-2023-05-02
  • experimental-2023-05-02-base
  • experimental-2023-05-03
  • experimental-2023-05-03-base
  • experimental-2023-05-12
  • experimental-2023-05-12-base
  • experimental-2023-05-21
  • experimental-2023-05-21-base
  • experimental-2023-05-25
  • experimental-2023-05-25-base
  • experimental-2023-07-02
  • experimental-2023-07-02-base
  • experimental-2023-07-04
  • experimental-2023-07-04-base
  • experimental-2023-07-12
  • experimental-2023-07-12-base
  • experimental-2023-07-16
  • experimental-2023-07-16-base
  • experimental-2023-08-04
  • experimental-2023-08-04-base
  • experimental-2023-08-10
  • experimental-2023-08-10-base
  • experimental-2023-09-08
  • experimental-2023-09-08-base
  • experimental-2023-09-09
  • experimental-2023-09-09-base
  • experimental-2023-09-10
  • experimental-2023-09-10-base
  • experimental-2023-09-11
  • experimental-2023-09-11-base
  • experimental-2023-09-12
  • experimental-2023-09-12-base
  • experimental-2023-09-13
  • experimental-2023-09-13-base
  • experimental-2023-09-15
  • experimental-2023-09-15-base
  • experimental-2023-09-16
  • experimental-2023-09-16-base
  • experimental-2023-09-18
  • experimental-2023-09-18-base
  • experimental-2023-09-20
  • experimental-2023-09-20-base
  • experimental-2023-09-27
  • experimental-2023-09-27-base
  • experimental-2023-09-28
  • experimental-2023-09-28-base
  • experimental-2023-09-29
  • experimental-2023-09-29-base
  • experimental-2023-10-02
  • experimental-2023-10-02-base
  • experimental-2023-10-13
  • experimental-2023-10-13-base
  • experimental-2023-10-14
  • experimental-2023-10-14-base
  • experimental-2023-10-16
  • experimental-2023-10-16-base
  • experimental-2023-10-23
  • experimental-2023-10-23-base
136 results

Target

Select target project
  • firmware/gluon
  • 0x4A6F/gluon
  • patrick/gluon
3 results
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • 2014.3.x
  • 2014.4.x
  • babel
  • hoodselector
  • master
  • radv-filterd
  • v2015.1.x
  • v2016.1.x
  • v2016.2.4-batmanbug
  • v2016.2.x
  • v2018.2.2-ffs
  • v2018.2.x
  • v2014.1
  • v2014.2
  • v2014.3
  • v2014.3.1
  • v2014.4
  • v2015.1
  • v2015.1.1
  • v2015.1.2
  • v2016.1
  • v2016.1.1
  • v2016.1.2
  • v2016.1.3
  • v2016.1.4
  • v2016.1.5
  • v2016.1.6
  • v2016.2
  • v2016.2.1
  • v2016.2.2
  • v2016.2.3
  • v2016.2.4
  • v2016.2.5
  • v2016.2.6
  • v2016.2.7
  • v2017.1
  • v2017.1.1
  • v2017.1.2
  • v2017.1.3
  • v2017.1.4
  • v2017.1.5
  • v2017.1.6
  • v2017.1.7
  • v2017.1.8
  • v2018.1
  • v2018.1.1
  • v2018.1.2
  • v2018.1.3
  • v2018.1.4
  • v2018.2
  • v2018.2-ffs0.1
  • v2018.2.1
  • v2018.2.1-ffs0.1
  • v2018.2.2-ffs0.1
56 results
Show changes
Showing
with 488 additions and 324 deletions
<%
local br = self.orientation == "horizontal" and '&#160;&#160;&#160;' or '<br>'
local entries = self:entries()
local util = require 'gluon.util'
%>
<div>
<% for i, entry in pairs(entries) do %>
<label<%=
attr("data-index", i) ..
attr("data-depends", self:deplist(entry.deps))
%>>
<input data-update="click change" type="checkbox"<%=
attr("id", id.."."..entry.key) ..
attr("name", id) ..
attr("value", entry.key) ..
attr("checked", (util.contains(self:cfgvalue(), entry.key)) and "checked") ..
attr("data-exclusive-with", self.exclusions[entry.key]) ..
attr("data-update", "change")
%>>
<label<%= attr("for", id.."."..entry.key)%>></label>
<span class="gluon-multi-list-option-descr"><%|entry.value%></span>
</label>
<% if i ~= #entries then write(br) end %>
<% end %>
</div>
<fieldset class="gluon-section">
<fieldset class="gluon-section" id="<%=id%>" data-index="<%=self.index%>"<%= attr("data-depends", self:deplist()) %>>
<% if self.title and #self.title > 0 then -%>
<legend><%|self.title%></legend>
<%- end %>
<% if self.description and #self.description > 0 then -%>
<div class="gluon-section-descr"><%=self.description%></div>
<%- end %>
<div class="gluon-section-node">
<div id="section-<%=id%>">
<div class="gluon-section-node" id="section-<%=id%>">
<% self:render_children(renderer, scope) %>
</div>
<% if self.error and self.error[1] then -%>
<div class="gluon-section-error">
<ul><% for _, e in ipairs(self.error[1]) do -%>
<li>
<%- if e == "invalid" then -%>
<%:One or more fields contain invalid values!%>
<%- elseif e == "missing" then -%>
<%:One or more required fields have no value!%>
<%- else -%>
<%|e%>
<%- end -%>
</li>
<%- end %></ul>
</div>
<%- end %>
</div>
</fieldset>
<textarea class="gluon-input-textarea" <% if not self.size then %> style="width: 100%"<% else %> cols="<%=self.size%>"<% end %> data-update="change"<%= attr("name", id) .. attr("id", id) .. attr("rows", self.rows) .. attr("wrap", self.wrap) %>>
<textarea <% if not self.size then %> style="width: 100%"<% else %> cols="<%=self.size%>"<% end %> data-update="change"<%= attr("name", id) .. attr("id", id) .. attr("rows", self.rows) .. attr("wrap", self.wrap) %>>
<%-|self:cfgvalue()-%>
</textarea>
......@@ -2,11 +2,10 @@
attr("id", id) ..
attr("name", id) ..
attr("type", self.password and "password" or "text") ..
attr("class", self.password and "gluon-input-password" or "gluon-input-text") ..
attr("value", self:cfgvalue()) ..
attr("size", self.size) ..
attr("placeholder", self.placeholder) ..
attr("maxlength", self.maxlength) ..
attr("data-type", self.datatype) ..
attr("data-optional", self.datatype and self.optional)
%> />
%>>
......@@ -7,7 +7,7 @@
<%- end -%>
<% if self.subtemplate then include(self.subtemplate) end %>
<% if self.description and #self.description > 0 then -%>
<br />
<br>
<div class="gluon-value-description">
<%=self.description%>
</div>
......
<%- if not self.hide then -%>
<div class="gluon-warning"<%=
attr("id", id) ..
attr("data-index", self.index) ..
attr("data-depends", self:deplist(self.deps))
%>>
<%- if self.content then -%>
<%= self.content %>
<%- else -%>
<b><%= self.title %></b><br>
<%= self.description %>
<%- end -%>
</div>
<%- end -%>
!function(){var e={};function t(e){return/^-?\d+$/.test(e)?+e:NaN}function n(e){return/^-?\d*\.?\d+?$/.test(e)?+e:NaN}var a={integer:function(){return!isNaN(t(this))},uinteger:function(){return t(this)>=0},float:function(){return!isNaN(n(this))},ufloat:function(){return n(this)>=0},ipaddr:function(){return a.ip4addr.apply(this)||a.ip6addr.apply(this)},ip4addr:function(){var e;return!!(e=this.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/))&&(e[1]>=0&&e[1]<=255&&e[2]>=0&&e[2]<=255&&e[3]>=0&&e[3]<=255&&e[4]>=0&&e[4]<=255)},ip6addr:function(){return this.indexOf("::")<0?null!=this.match(/^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i):!(this.indexOf(":::")>=0||this.match(/::.+::/)||this.match(/^:[^:]/)||this.match(/[^:]:$/))&&(!!this.match(/^(?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}$/i)||(!!this.match(/^(?:[a-f0-9]{1,4}:){7}:$/i)||!!this.match(/^:(?::[a-f0-9]{1,4}){7}$/i)))},wpakey:function(){var e=this;return 64==e.length?null!=e.match(/^[a-f0-9]{64}$/i):e.length>=8&&e.length<=63},range:function(e,t){var a=n(this);return a>=+e&&a<=+t},min:function(e){return n(this)>=+e},max:function(e){return n(this)<=+e},irange:function(e,n){var a=t(this);return a>=+e&&a<=+n},imin:function(e){return t(this)>=+e},imax:function(e){return t(this)<=+e},minlength:function(e){return(""+this).length>=+e},maxlength:function(e){return(""+this).length<=+e}};function r(e){for(var t=0;t<e.length;t++){var n=!0;for(var a in e[t])n=n&&(r=a,i=e[t][a],o=void 0,(o=document.getElementById(r))?("checkbox"==o.type?o.checked:o.value?o.value:"")==i:!!(o=document.getElementById(r+"."+i))&&"radio"==o.type&&o.checked);if(n)return!0}var r,i,o;return!1}function i(){var t=!1;for(var n in e){var a=e[n],o=document.getElementById(n),d=document.getElementById(a.parent);if(o&&o.parentNode&&!r(a.deps))o.parentNode.removeChild(o),t=!0;else if(d&&(!o||!o.parentNode)&&r(a.deps)){var u=void 0;for(u=d.firstChild;u&&!(u.getAttribute&&parseInt(u.getAttribute("data-index"),10)>a.index);u=u.nextSibling);u?d.insertBefore(a.node,u):d.appendChild(a.node),t=!0}d&&d.parentNode&&d.getAttribute("data-optionals")&&(d.parentNode.style.display=d.options.length<=1?"none":"")}t&&i()}function o(e,t,n,a){return e.addEventListener?e.addEventListener(t,n,!!a):e.attachEvent("on"+t,function(){var e=window.event;return!e.target&&e.srcElement&&(e.target=e.srcElement),!!n(e)}),e}function d(e,t){var n=t.prefix;function a(a,l,s){for(var c=[];e.firstChild;){var p=e.firstChild;(f=+p.index)!=s&&("input"==p.nodeName.toLowerCase()?c.push(p.value||""):"select"==p.nodeName.toLowerCase()&&(c[c.length-1]=p.options[p.selectedIndex].value)),e.removeChild(p)}l>=0?(a=l+1,c.splice(l,0,"")):t.optional||0!=c.length||c.push("");for(var f=1;f<=c.length;f++){var v=document.createElement("input");if(v.id=n+"."+f,v.name=n,v.value=c[f-1],v.type="text",v.index=f,v.className="gluon-input-text",t.size&&(v.size=t.size),t.placeholder&&(v.placeholder=t.placeholder),e.appendChild(v),t.type&&u(v,!1,t.type),o(v,"keydown",i),o(v,"keypress",r),f==a)v.focus();else if(-f==a){v.focus();var h=v.value;v.value=" ",v.value=h}if(t.optional||c.length>1)(m=document.createElement("span")).className="gluon-remove",e.appendChild(m),o(m,"click",d(!1)),e.appendChild(document.createElement("br"))}var m;(m=document.createElement("span")).className="gluon-add",e.appendChild(m),o(m,"click",d(!0))}function r(e){var t=(e=e||window.event).target?e.target:e.srcElement;switch(3==t.nodeType&&(t=t.parentNode),e.keyCode){case 8:case 46:return 0!=t.value.length||(e.preventDefault&&e.preventDefault(),!1);case 13:case 38:case 40:return e.preventDefault&&e.preventDefault(),!1}return!0}function i(e){var t,r,i=(e=e||window.event).target?e.target:e.srcElement,o=0;if(i){for(3==i.nodeType&&(i=i.parentNode),o=i.index,t=i.previousSibling;t&&t.name!=n;)t=t.previousSibling;for(r=i.nextSibling;r&&r.name!=n;)r=r.nextSibling}switch(e.keyCode){case 8:case 46:if("select"==i.nodeName.toLowerCase()||0==i.value.length){e.preventDefault&&e.preventDefault();var d=i.index;return 8==e.keyCode&&(d=1-d),a(d,-1,o),!1}break;case 13:a(-1,o,-1);break;case 38:t&&t.focus();break;case 40:r&&r.focus()}return!0}function d(e){return function(t){for(var a=((t=t||window.event).target?t.target:t.srcElement).previousSibling;a&&a.name!=n;)a=a.previousSibling;return e?i({target:a,keyCode:13}):(a.value="",i({target:a,keyCode:8})),!1}}a(NaN,-1,-1)}function u(e,t,n){var r,i,d,u=(d=(r=n).match(/^([^\(]+)\(([^,]+),([^\)]+)\)$/))&&void 0!==(i=a[d[1]])?function(){return i.apply(this,[d[2],d[3]])}:(d=r.match(/^([^\(]+)\(([^,\)]+)\)$/))&&void 0!==(i=a[d[1]])?function(){return i.apply(this,[d[2]])}:a[r];if(u){var l=function(){if(e.form){e.className=e.className.replace(/ gluon-input-invalid/g,"");var n=e.options&&e.options.selectedIndex>-1?e.options[e.options.selectedIndex].value:e.value;0==n.length&&t||u.apply(n)||(e.className+=" gluon-input-invalid")}};o(e,"blur",l),o(e,"keyup",l),"select"==e.nodeName.toLowerCase()&&(o(e,"change",l),o(e,"click",l)),l()}}!function(){var t,n,a,r,l;t=document.querySelectorAll("[data-depends]");for(var s=0;void 0!==(g=t[s]);s++){var c=parseInt(g.getAttribute("data-index"),10),p=JSON.parse(g.getAttribute("data-depends"));if(!isNaN(c)&&p.length>0)for(var f=0;f<p.length;f++)n=g,a=p[f],r=c,l=void 0,(l=e[n.id])||(l={node:n,parent:n.parentNode.id,deps:[],index:r},e[n.id]=l),l.deps.push(a)}t=document.querySelectorAll("[data-update]");for(s=0;void 0!==(g=t[s]);s++)for(var v,h=g.getAttribute("data-update").split(" "),m=0;void 0!==(v=h[m]);m++)o(g,v,i);t=document.querySelectorAll("[data-type]");for(s=0;void 0!==(g=t[s]);s++)u(g,"true"===g.getAttribute("data-optional"),g.getAttribute("data-type"));t=document.querySelectorAll("[data-dynlist]");var g;for(s=0;void 0!==(g=t[s]);s++){d(g,JSON.parse(g.getAttribute("data-dynlist")))}i()}()}();
\ No newline at end of file
......@@ -10,12 +10,6 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "One or more fields contain invalid values!"
msgstr "Ein oder mehrere Felder enthalten ungültige Werte!"
msgid "One or more required fields have no value!"
msgstr "Ein oder mehr benötigte Felder sind nicht ausgefüllt!"
msgid "Reset"
msgstr "Zurücksetzen"
......
......@@ -10,12 +10,6 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
msgid "One or more fields contain invalid values!"
msgstr "Un ou plusieurs champs contiennent des valeurs incorrectes !"
msgid "One or more required fields have no value!"
msgstr "Un ou plusieurs champs n'ont pas de valeur !"
msgid "Reset"
msgstr "Remise à zéro"
......
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "One or more fields contain invalid values!"
msgstr ""
msgid "One or more required fields have no value!"
msgstr ""
msgid "Reset"
msgstr ""
......
/*
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2012 Jo-Philipp Wich <jow@openwrt.org>
Copyright 2017 Matthias Schiffer <mschiffer@universe-factory.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
SPDX-License-Identifier: Apache-2.0
SPDX-FileCopyrightText: 2008, Steven Barth <steven@midlink.org>
SPDX-FileCopyrightText: 2008-2012, Jo-Philipp Wich <jow@openwrt.org>
SPDX-FileCopyrightText: 2017, Matthias Schiffer <mschiffer@universe-factory.net>
SPDX-FileCopyrightText: 2023, Leonardo Mörlein <me@irrelefant.net>
*/
/*
Build using:
uglifyjs javascript/gluon-web-model.js -o files/lib/gluon/web/www/static/gluon-web-model.js -c -m --support-ie8
uglifyjs javascript/gluon-web-model.js -o javascript/gluon-web-model.min.js -c -m --ie
*/
......@@ -183,6 +179,8 @@
}
function update() {
window.dispatchEvent(new Event('gluon-update'));
var state = false;
for (var id in dep_entries) {
var entry = dep_entries[id];
......@@ -191,6 +189,7 @@
if (node && node.parentNode && !check(entry.deps)) {
node.parentNode.removeChild(node);
node.dispatchEvent(new Event('gluon-hide'));
state = true;
} else if (parent && (!node || !node.parentNode) && check(entry.deps)) {
var next = undefined;
......@@ -207,6 +206,7 @@
parent.insertBefore(entry.node, next);
}
entry.node.dispatchEvent(new Event('gluon-show'));
state = true;
}
......@@ -215,6 +215,20 @@
parent.parentNode.style.display = (parent.options.length <= 1) ? 'none' : '';
}
var nodes = document.querySelectorAll('[data-exclusive-with]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
var exclusive_with = JSON.parse(node.getAttribute('data-exclusive-with'));
node.disabled = false;
for (var list_item of exclusive_with) {
var el = document.getElementById(node.name + '.' + list_item);
node.disabled ||= el.checked;
}
if (node.disabled)
node.checked = false;
}
if (state) {
update();
}
......@@ -272,7 +286,6 @@
t.value = values[i-1];
t.type = 'text';
t.index = i;
t.className = 'gluon-input-text';
if (attr.size)
t.size = attr.size;
......@@ -471,6 +484,7 @@
bind(field, "blur", validator);
bind(field, "keyup", validator);
bind(field, "gluon-revalidate", validator);
if (field.nodeName.toLowerCase() == 'select') {
bind(field, "change", validator);
......@@ -512,7 +526,7 @@
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
var events = node.getAttribute('data-update').split(' ');
for (var j = 0, event; (event = events[j]) !== undefined; j++) {
bind(node, event, update);
bind(node, event, function () {setTimeout(update, 0);});
}
}
......
!function(){var s={};function a(e){return/^-?\d+$/.test(e)?+e:NaN}function i(e){return/^-?\d*\.?\d+?$/.test(e)?+e:NaN}var d={integer:function(){return!isNaN(a(this))},uinteger:function(){return 0<=a(this)},"float":function(){return!isNaN(i(this))},ufloat:function(){return 0<=i(this)},ipaddr:function(){return d.ip4addr.apply(this)||d.ip6addr.apply(this)},ip4addr:function(){var e;return!!(e=this.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/))&&0<=e[1]&&e[1]<=255&&0<=e[2]&&e[2]<=255&&0<=e[3]&&e[3]<=255&&0<=e[4]&&e[4]<=255},ip6addr:function(){return this.indexOf("::")<0?null!=this.match(/^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i):!(0<=this.indexOf(":::")||this.match(/::.+::/)||this.match(/^:[^:]/)||this.match(/[^:]:$/)||!this.match(/^(?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}$/i)&&!this.match(/^(?:[a-f0-9]{1,4}:){7}:$/i)&&!this.match(/^:(?::[a-f0-9]{1,4}){7}$/i))},wpakey:function(){var e=this;return 64==e.length?null!=e.match(/^[a-f0-9]{64}$/i):8<=e.length&&e.length<=63},range:function(e,t){var n=i(this);return+e<=n&&n<=+t},min:function(e){return i(this)>=+e},max:function(e){return i(this)<=+e},irange:function(e,t){var n=a(this);return+e<=n&&n<=+t},imin:function(e){return a(this)>=+e},imax:function(e){return a(this)<=+e},minlength:function(e){return+e<=(""+this).length},maxlength:function(e){return(""+this).length<=+e}};function p(e){for(var t,n,a,i=0;i<e.length;i++){var r,d=!0;for(r in e[i])d=d&&(t=r,n=e[i][r],a=void 0,(a=document.getElementById(t))?("checkbox"==a.type?a.checked:a.value||"")==n:!!(a=document.getElementById(t+"."+n))&&"radio"==a.type&&a.checked);if(d)return 1}}function f(){window.dispatchEvent(new Event("gluon-update"));var e,t=!1;for(e in s){var n=s[e],a=document.getElementById(e),i=document.getElementById(n.parent);if(a&&a.parentNode&&!p(n.deps))a.parentNode.removeChild(a),a.dispatchEvent(new Event("gluon-hide")),t=!0;else if(i&&(!a||!a.parentNode)&&p(n.deps)){for(var r=undefined,r=i.firstChild;r&&!(r.getAttribute&&parseInt(r.getAttribute("data-index"),10)>n.index);r=r.nextSibling);r?i.insertBefore(n.node,r):i.appendChild(n.node),n.node.dispatchEvent(new Event("gluon-show")),t=!0}i&&i.parentNode&&i.getAttribute("data-optionals")&&(i.parentNode.style.display=i.options.length<=1?"none":"")}for(var d=document.querySelectorAll("[data-exclusive-with]"),o=0;(a=d[o])!==undefined;o++){var u,l=JSON.parse(a.getAttribute("data-exclusive-with"));a.disabled=!1;for(u of l){var c=document.getElementById(a.name+"."+u);a.disabled||=c.checked}a.disabled&&(a.checked=!1)}t&&f()}function v(e,t,n,a){e.addEventListener?e.addEventListener(t,n,!!a):e.attachEvent("on"+t,function(){var e=window.event;return!e.target&&e.srcElement&&(e.target=e.srcElement),!!n(e)})}function m(t,n,e){var a,i,r=(i=(e=e).match(/^([^\(]+)\(([^,]+),([^\)]+)\)$/))&&(a=d[i[1]])!==undefined?function(){return a.apply(this,[i[2],i[3]])}:(i=e.match(/^([^\(]+)\(([^,\)]+)\)$/))&&(a=d[i[1]])!==undefined?function(){return a.apply(this,[i[2]])}:d[e];r&&(v(t,"blur",e=function(){var e;t.form&&(t.className=t.className.replace(/ gluon-input-invalid/g,""),0==(e=(t.options&&-1<t.options.selectedIndex?t.options[t.options.selectedIndex]:t).value).length&&n||r.apply(e)||(t.className+=" gluon-input-invalid"))}),v(t,"keyup",e),v(t,"gluon-revalidate",e),"select"==t.nodeName.toLowerCase()&&(v(t,"change",e),v(t,"click",e)),e())}for(var e,t,n,r,o=document.querySelectorAll("[data-depends]"),u=0;(b=o[u])!==undefined;u++){var l=parseInt(b.getAttribute("data-index"),10),c=JSON.parse(b.getAttribute("data-depends"));if(!isNaN(l)&&0<c.length)for(var h=0;h<c.length;h++)e=b,t=c[h],n=l,r=void 0,(r=s[e.id])||(r={node:e,parent:e.parentNode.id,deps:[],index:n},s[e.id]=r),r.deps.push(t)}for(o=document.querySelectorAll("[data-update]"),u=0;(b=o[u])!==undefined;u++)for(var g,y=b.getAttribute("data-update").split(" "),N=0;(g=y[N])!==undefined;N++)v(b,g,function(){setTimeout(f,0)});for(o=document.querySelectorAll("[data-type]"),u=0;(b=o[u])!==undefined;u++)m(b,"true"===b.getAttribute("data-optional"),b.getAttribute("data-type"));o=document.querySelectorAll("[data-dynlist]");for(var b,u=0;(b=o[u])!==undefined;u++){var w=JSON.parse(b.getAttribute("data-dynlist"));!function(l,c){var s=c.prefix;function d(e,t,n){for(var a=[];l.firstChild;){var i=l.firstChild;(r=+i.index)!=n&&("input"==i.nodeName.toLowerCase()?a.push(i.value||""):"select"==i.nodeName.toLowerCase()&&(a[a.length-1]=i.options[i.selectedIndex].value)),l.removeChild(i)}0<=t?(e=t+1,a.splice(t,0,"")):c.optional||0!=a.length||a.push("");for(var r=1;r<=a.length;r++){var d,o,u=document.createElement("input");u.id=s+"."+r,u.name=s,u.value=a[r-1],u.type="text",u.index=r,c.size&&(u.size=c.size),c.placeholder&&(u.placeholder=c.placeholder),l.appendChild(u),c.type&&m(u,!1,c.type),v(u,"keydown",f),v(u,"keypress",p),r==e?u.focus():-r==e&&(u.focus(),d=u.value,u.value=" ",u.value=d),(c.optional||1<a.length)&&((o=document.createElement("span")).className="gluon-remove",l.appendChild(o),v(o,"click",h(!1)),l.appendChild(document.createElement("br")))}(o=document.createElement("span")).className="gluon-add",l.appendChild(o),v(o,"click",h(!0))}function p(e){var t=(e=e||window.event).target||e.srcElement;switch(3==t.nodeType&&(t=t.parentNode),e.keyCode){case 8:case 46:return 0==t.value.length?(e.preventDefault&&e.preventDefault(),!1):!0;case 13:case 38:case 40:return e.preventDefault&&e.preventDefault(),!1}return!0}function f(e){var t,n,a,i=(e=e||window.event).target||e.srcElement,r=0;if(i){for(r=(i=3==i.nodeType?i.parentNode:i).index,t=i.previousSibling;t&&t.name!=s;)t=t.previousSibling;for(n=i.nextSibling;n&&n.name!=s;)n=n.nextSibling}switch(e.keyCode){case 8:case 46:if("select"==i.nodeName.toLowerCase()||0==i.value.length)return e.preventDefault&&e.preventDefault(),a=i.index,d(a=8==e.keyCode?1-a:a,-1,r),!1;break;case 13:d(-1,r,-1);break;case 38:t&&t.focus();break;case 40:n&&n.focus()}return!0}function h(n){return function(e){for(var t=((e=e||window.event).target||e.srcElement).previousSibling;t&&t.name!=s;)t=t.previousSibling;return n?f({target:t,keyCode:13}):(t.value="",f({target:t,keyCode:8})),!1}}d(NaN,-1,-1)}(b,w)}f()}();
\ No newline at end of file
......@@ -2,8 +2,6 @@
-- Copyright 2017-2018 Matthias Schiffer <mschiffer@universe-factory.net>
-- Licensed to the public under the Apache License 2.0.
module('gluon.web.model', package.seeall)
local unistd = require 'posix.unistd'
local classes = require 'gluon.web.model.classes'
......@@ -15,7 +13,7 @@ local function load(filename, i18n)
local func = assert(loadfile(filename))
setfenv(func, setmetatable({}, {__index =
function(tbl, key)
function(_, key)
return classes[key] or i18n[key] or _G[key]
end
}))
......
-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Copyright 2017-2018 Matthias Schiffer <mschiffer@universe-factory.net>
-- Licensed to the public under the Apache License 2.0.
module("gluon.web.model.classes", package.seeall)
-- SPDX-License-Identifier: Apache-2.0
-- SPDX-FileCopyrightText: 2008, Steven Barth <steven@midlink.org>
-- SPDX-FileCopyrightText: 2017-2018, Matthias Schiffer <mschiffer@universe-factory.net>
-- SPDX-FileCopyrightText: 2023, Leonardo Mörlein <me@irrelefant.net>
local util = require "gluon.web.util"
local gluon_util = require "gluon.util"
local datatypes = require "gluon.web.model.datatypes"
local class = util.class
local instanceof = util.instanceof
FORM_NODATA = 0
FORM_VALID = 1
FORM_INVALID = -1
local M = {}
M.FORM_NODATA = 0
M.FORM_VALID = 1
M.FORM_INVALID = -1
local function parse_datatype(code)
......@@ -41,15 +44,18 @@ local function verify_datatype(dt, value)
end
Node = class()
local Node = class()
M.Node = Node
function Node:__init__(title, description, name)
function Node:__init__(name, title, description)
self.children = {}
self.deps = {}
self.title = title or ""
self.description = description or ""
self.name = name
self.index = nil
self.parent = nil
self.state = M.FORM_NODATA
self.package = 'gluon-web-model'
end
......@@ -69,12 +75,33 @@ function Node:id()
return prefix.."."..self:id_suffix()
end
function Node:reset_node()
self.state = M.FORM_NODATA
for _, child in ipairs(self.children) do
child:reset_node()
end
end
function Node:parse(http)
self.state = M.FORM_VALID
for _, child in ipairs(self.children) do
child:parse(http)
end
end
function Node:propagate_state()
if self.state == M.FORM_NODATA then
return
end
for _, child in ipairs(self.children) do
child:propagate_state()
if child.state == M.FORM_INVALID then
self.state = M.FORM_INVALID
end
end
end
function Node:render(renderer, scope)
if self.template then
local env = setmetatable({
......@@ -92,104 +119,90 @@ function Node:render_children(renderer, scope)
end
end
function Node:resolve_depends()
local updated = false
for _, node in ipairs(self.children) do
update = updated or node:resolve_depends()
end
return updated
function Node:depends(field, value)
local deps
if instanceof(field, Node) then
deps = { [field] = value }
else
deps = field
end
function Node:handle()
for _, node in ipairs(self.children) do
node:handle()
end
table.insert(self.deps, deps)
end
function Node:deplist(deplist)
local deps = {}
Template = class(Node)
function Template:__init__(template)
Node.__init__(self)
self.template = template
for _, d in ipairs(deplist or self.deps) do
local a = {}
for k, v in pairs(d) do
a[k:id()] = v
end
table.insert(deps, a)
end
if next(deps) then
return deps
end
end
Form = class(Node)
function Node:resolve_depends()
local updated = self:resolve_node_depends()
function Form:__init__(...)
Node.__init__(self, ...)
self.template = "model/form"
for _, node in ipairs(self.children) do
updated = updated or node:resolve_depends()
end
function Form:submitstate(http)
return http:getenv("REQUEST_METHOD") == "POST" and http:formvalue(self:id()) ~= nil
return updated
end
function Form:parse(http)
if not self:submitstate(http) then
self.state = FORM_NODATA
return
function Node:resolve_node_depends()
if #self.deps == 0 then
return false
end
Node.parse(self, http)
while self:resolve_depends() do end
for _, s in ipairs(self.children) do
for _, v in ipairs(s.children) do
if v.state == FORM_INVALID then
self.state = FORM_INVALID
return
for _, d in ipairs(self.deps) do
local valid = true
for k, v in pairs(d) do
if k.state ~= M.FORM_VALID or k.data ~= v then
valid = false
break
end
end
if valid then return false end
end
self.state = FORM_VALID
self:reset_node()
return true
end
function Form:handle()
if self.state == FORM_VALID then
Node.handle(self)
self:write()
end
-- will be overridden: write(value)
function Node:write()
end
function Form:write()
function Node:handle()
if self.state == M.FORM_VALID then
for _, node in ipairs(self.children) do
node:handle()
end
function Form:section(t, ...)
assert(instanceof(t, Section), "class must be a descendent of Section")
local obj = t(...)
self:append(obj)
return obj
self:write(self.data)
end
Section = class(Node)
function Section:__init__(...)
Node.__init__(self, ...)
self.fields = {}
self.template = "model/section"
end
function Section:option(t, option, title, description, ...)
assert(instanceof(t, AbstractValue), "class must be a descendant of AbstractValue")
local obj = t(title, description, option, ...)
self:append(obj)
self.fields[option] = obj
return obj
end
local Template = class(Node)
M.Template = Template
function Template:__init__(template)
Node.__init__(self)
self.template = template
end
AbstractValue = class(Node)
local AbstractValue = class(Node)
M.AbstractValue = AbstractValue
function AbstractValue:__init__(option, ...)
Node.__init__(self, option, ...)
self.deps = {}
function AbstractValue:__init__(...)
Node.__init__(self, ...)
self.default = nil
self.size = nil
......@@ -197,34 +210,7 @@ function AbstractValue:__init__(option, ...)
self.template = "model/valuewrapper"
self.state = FORM_NODATA
end
function AbstractValue:depends(field, value)
local deps
if instanceof(field, Node) then
deps = { [field] = value }
else
deps = field
end
table.insert(self.deps, deps)
end
function AbstractValue:deplist(section, deplist)
local deps = {}
for _, d in ipairs(deplist or self.deps) do
local a = {}
for k, v in pairs(d) do
a[k:id()] = v
end
table.insert(deps, a)
end
if next(deps) then
return deps
end
self.error = false
end
function AbstractValue:defaultvalue()
......@@ -236,68 +222,38 @@ function AbstractValue:formvalue(http)
end
function AbstractValue:cfgvalue()
if self.state == FORM_NODATA then
if self.state == M.FORM_NODATA then
return self:defaultvalue()
else
return self.data
end
end
function AbstractValue:add_error(type, msg)
self.error = msg or type
if type == "invalid" then
self.tag_invalid = true
elseif type == "missing" then
self.tag_missing = true
end
self.state = FORM_INVALID
end
function AbstractValue:reset()
self.error = nil
self.tag_invalid = nil
self.tag_missing = nil
function AbstractValue:reset_node()
self.data = nil
self.state = FORM_NODATA
self.error = false
self.state = M.FORM_NODATA
end
function AbstractValue:parse(http)
self.data = self:formvalue(http)
local ok, err = self:validate()
if not ok then
if type(self.data) ~= "string" or #self.data > 0 then
self:add_error("invalid", err)
else
self:add_error("missing", err)
end
if not self:validate() then
self.error = true
self.state = M.FORM_INVALID
return
end
self.state = FORM_VALID
self.state = M.FORM_VALID
end
function AbstractValue:resolve_depends()
if self.state == FORM_NODATA or #self.deps == 0 then
function AbstractValue:resolve_node_depends()
if self.state == M.FORM_NODATA then
return false
end
for _, d in ipairs(self.deps) do
local valid = true
for k, v in pairs(d) do
if k.state ~= FORM_VALID or k.data ~= v then
valid = false
break
end
end
if valid then return false end
end
self:reset()
return true
return Node.resolve_node_depends(self)
end
function AbstractValue:validate()
......@@ -317,17 +273,9 @@ function AbstractValue:validate()
end
function AbstractValue:handle()
if self.state == FORM_VALID then
self:write(self.data)
end
end
function AbstractValue:write(value)
end
Value = class(AbstractValue)
local Value = class(AbstractValue)
M.Value = Value
function Value:__init__(...)
AbstractValue.__init__(self, ...)
......@@ -335,7 +283,8 @@ function Value:__init__(...)
end
Flag = class(AbstractValue)
local Flag = class(AbstractValue)
M.Flag = Flag
function Flag:__init__(...)
AbstractValue.__init__(self, ...)
......@@ -353,7 +302,8 @@ function Flag:validate()
end
ListValue = class(AbstractValue)
local ListValue = class(AbstractValue)
M.ListValue = ListValue
function ListValue:__init__(...)
AbstractValue.__init__(self, ...)
......@@ -413,7 +363,85 @@ function ListValue:validate()
end
DynamicList = class(AbstractValue)
local MultiListValue = class(AbstractValue)
M.MultiListValue = MultiListValue
function MultiListValue:__init__(...)
AbstractValue.__init__(self, ...)
self.subtemplate = "model/mlvalue"
self.size = 1
self.keys = {}
self.entry_list = {}
end
function MultiListValue:value(key, val, ...)
key = tostring(key)
if self.keys[key] then
return
end
self.keys[key] = true
self.exclusions = {}
val = val or key
table.insert(self.entry_list, {
key = key,
value = tostring(val),
deps = {...},
})
end
function MultiListValue:entries()
local ret = {unpack(self.entry_list)}
return ret
end
function MultiListValue:validate()
for _, val in ipairs(self.data) do
if not self.keys[val] then
return false
end
end
for key, exclusive_with in pairs(self.exclusions) do
if gluon_util.contains(self.data, key) then
for _, exclusion in ipairs(exclusive_with) do
if gluon_util.contains(self.data, exclusion) then
return false
end
end
end
end
return true
end
function MultiListValue:exclusive(a, b)
if not self.exclusions[a] then
self.exclusions[a] = {}
end
if not self.exclusions[b] then
self.exclusions[b] = {}
end
gluon_util.add_to_set(self.exclusions[a], b)
gluon_util.add_to_set(self.exclusions[b], a)
end
function MultiListValue:defaultvalue()
return self.default or {}
end
function MultiListValue:formvalue(http)
return http:formvaluetable(self:id())
end
local DynamicList = class(AbstractValue)
M.DynamicList = DynamicList
function DynamicList:__init__(...)
AbstractValue.__init__(self, ...)
......@@ -452,9 +480,105 @@ function DynamicList:validate()
end
TextValue = class(AbstractValue)
local TextValue = class(AbstractValue)
M.TextValue = TextValue
function TextValue:__init__(...)
AbstractValue.__init__(self, ...)
self.subtemplate = "model/tvalue"
end
local Element = class(AbstractValue)
M.Element = Element
function Element:__init__(template, kv, ...)
AbstractValue.__init__(self, ...)
self.default = nil
self.size = nil
self.optional = false
self.template = template
for key, value in pairs(kv) do
self[key] = value
end
self.error = false
end
function Element:parse(http)
if not self.datatype then
self.state = M.FORM_VALID
return
end
return AbstractValue:parse(http)
end
function Element:validate()
if not self.datatype then
return true
end
AbstractValue:validate()
end
local Section = class(Node)
M.Section = Section
function Section:__init__(title, description, name)
Node.__init__(self, name, title, description)
self.template = "model/section"
end
function Section:option(t, ...)
assert(instanceof(t, AbstractValue), "class must be a descendant of AbstractValue")
local obj = t(...)
self:append(obj)
return obj
end
function Section:element(...)
local obj = Element(...)
self:append(obj)
return obj
end
local Form = class(Node)
M.Form = Form
function Form:__init__(title, description, name)
Node.__init__(self, name, title, description)
self.template = "model/form"
end
function Form:submitstate(http)
return http:getenv("REQUEST_METHOD") == "POST" and http:formvalue(self:id()) ~= nil
end
function Form:parse(http)
if not self:submitstate(http) then
self.state = M.FORM_NODATA
return
end
Node.parse(self, http)
while self:resolve_depends() do end
self:propagate_state()
end
function Form:section(t, ...)
assert(instanceof(t, Section), "class must be a descendent of Section")
local obj = t(...)
self:append(obj)
return obj
end
return M
-- Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
-- Copyright 2017 Matthias Schiffer <mschiffer@universe-factory.net>
-- Licensed to the public under the Apache License 2.0.
-- SPDX-License-Identifier: Apache-2.0
-- SPDX-FileCopyrightText: 2010, Jo-Philipp Wich <jow@openwrt.org>
-- SPDX-FileCopyrightText: 2017, Matthias Schiffer <mschiffer@universe-factory.net>
local tonumber = tonumber
local M = {}
module "gluon.web.model.datatypes"
function bool(val)
function M.bool(val)
if val == "1" or val == "yes" or val == "on" or val == "true" then
return true
elseif val == "0" or val == "no" or val == "off" or val == "false" then
......@@ -32,29 +28,29 @@ local function int(val)
end
end
function uinteger(val)
function M.uinteger(val)
local n = int(val)
return (n ~= nil and n >= 0)
end
function integer(val)
function M.integer(val)
return (int(val) ~= nil)
end
function ufloat(val)
function M.ufloat(val)
local n = dec(val)
return (n ~= nil and n >= 0)
end
function float(val)
function M.float(val)
return (dec(val) ~= nil)
end
function ipaddr(val)
return ip4addr(val) or ip6addr(val)
function M.ipaddr(val)
return M.ip4addr(val) or M.ip6addr(val)
end
function ip4addr(val)
function M.ip4addr(val)
local g = '(%d%d?%d?)'
local v1, v2, v3, v4 = val:match('^'..((g..'%.'):rep(3))..g..'$')
local n1, n2, n3, n4 = tonumber(v1), tonumber(v2), tonumber(v3), tonumber(v4)
......@@ -69,7 +65,7 @@ function ip4addr(val)
)
end
function ip6addr(val)
function M.ip6addr(val)
local g1 = '%x%x?%x?%x?'
if not val:match('::') then
......@@ -100,7 +96,7 @@ function ip6addr(val)
return false
end
function wpakey(val)
function M.wpakey(val)
if #val == 64 then
return (val:match("^%x+$") ~= nil)
else
......@@ -108,11 +104,11 @@ function wpakey(val)
end
end
function range(val, vmin, vmax)
return min(val, vmin) and max(val, vmax)
function M.range(val, vmin, vmax)
return M.min(val, vmin) and M.max(val, vmax)
end
function min(val, min)
function M.min(val, min)
val = dec(val)
min = tonumber(min)
......@@ -123,7 +119,7 @@ function min(val, min)
return false
end
function max(val, max)
function M.max(val, max)
val = dec(val)
max = tonumber(max)
......@@ -134,19 +130,19 @@ function max(val, max)
return false
end
function irange(val, vmin, vmax)
return integer(val) and range(val, vmin, vmax)
function M.irange(val, vmin, vmax)
return M.integer(val) and M.range(val, vmin, vmax)
end
function imin(val, vmin)
return integer(val) and min(val, vmin)
function M.imin(val, vmin)
return M.integer(val) and M.min(val, vmin)
end
function imax(val, vmax)
return integer(val) and max(val, vmax)
function M.imax(val, vmax)
return M.integer(val) and M.max(val, vmax)
end
function minlength(val, min)
function M.minlength(val, min)
min = tonumber(min)
if min ~= nil then
......@@ -156,7 +152,7 @@ function minlength(val, min)
return false
end
function maxlength(val, max)
function M.maxlength(val, max)
max = tonumber(max)
if max ~= nil then
......@@ -165,3 +161,5 @@ function maxlength(val, max)
return false
end
return M
......@@ -4,8 +4,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-web-network
PKG_VERSION:=1
PKG_RELEASE:=1
include ../gluon.mk
......
......@@ -19,18 +19,15 @@ msgstr "Automatisch (RA/DHCPv6)"
msgid "Disabled"
msgstr "Deaktiviert"
msgid "Enable \"%s\""
msgstr "\"%s\" aktivieren"
msgid "Enable PoE Passthrough"
msgstr "PoE-Passthrough aktivieren"
msgid "Enable PoE Power Port %s"
msgstr "PoE-Ausgabe auf Port %s aktivieren"
msgid "Enable meshing on the LAN interface"
msgstr "Mesh auf dem LAN-Port aktivieren"
msgid "Enable meshing on the WAN interface"
msgstr "Mesh auf dem WAN-Port aktivieren"
msgid "Gateway"
msgstr "Gateway"
......@@ -43,6 +40,12 @@ msgstr "IPv4"
msgid "IPv6"
msgstr "IPv6"
msgid "Interface"
msgstr "Interface"
msgid "LAN Interfaces"
msgstr "LAN-Interfaces"
msgid "Netmask"
msgstr "Netzmaske"
......@@ -55,5 +58,8 @@ msgstr "Statisch"
msgid "Static DNS servers"
msgstr "Statische DNS-Server"
msgid "WAN Interfaces"
msgstr "WAN-Interfaces"
msgid "WAN connection"
msgstr "WAN-Verbindung"
......@@ -19,18 +19,15 @@ msgstr "Automatique (RA/DHCPv6)"
msgid "Disabled"
msgstr "Désactivé"
msgid "Enable \"%s\""
msgstr ""
msgid "Enable PoE Passthrough"
msgstr ""
msgid "Enable PoE Power Port %s"
msgstr ""
msgid "Enable meshing on the LAN interface"
msgstr "Activer le réseau MESH sur le port LAN"
msgid "Enable meshing on the WAN interface"
msgstr "Activer le réseau MESH sur les ports WAN"
msgid "Gateway"
msgstr "Passerelle"
......
......@@ -10,16 +10,13 @@ msgstr ""
msgid "Disabled"
msgstr ""
msgid "Enable PoE Passthrough"
msgstr ""
msgid "Enable PoE Power Port %s"
msgid "Enable \"%s\""
msgstr ""
msgid "Enable meshing on the LAN interface"
msgid "Enable PoE Passthrough"
msgstr ""
msgid "Enable meshing on the WAN interface"
msgid "Enable PoE Power Port %s"
msgstr ""
msgid "Gateway"
......@@ -34,6 +31,12 @@ msgstr ""
msgid "IPv6"
msgstr ""
msgid "Interface"
msgstr ""
msgid "LAN Interfaces"
msgstr ""
msgid "Netmask"
msgstr ""
......@@ -46,5 +49,8 @@ msgstr ""
msgid "Static DNS servers"
msgstr ""
msgid "WAN Interfaces"
msgstr ""
msgid "WAN connection"
msgstr ""
--[[
Copyright 2014 Nils Schneider <nils@nilsschneider.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
]]--
-- SPDX-License-Identifier: Apache-2.0
-- SPDX-FileCopyrightText: 2014, Nils Schneider <nils@nilsschneider.net>
-- SPDX-FileCopyrightText: 2023, Leonardo Mörlein <me@irrelefant.net>
local uci = require("simple-uci").cursor()
local sysconfig = require 'gluon.sysconfig'
local util = require 'gluon.util'
local wan = uci:get_all("network", "wan")
local wan6 = uci:get_all("network", "wan6")
local dns_static = uci:get_first("gluon-wan-dnsmasq", "static")
local f = Form(translate("WAN connection"))
local s = f:section(Section)
......@@ -42,7 +35,7 @@ ipv4_gateway.default = wan.gateway
ipv4_gateway.datatype = "ip4addr"
local s = f:section(Section)
s = f:section(Section)
local ipv6 = s:option(ListValue, "ipv6", translate("IPv6"))
ipv6:value("dhcpv6", translate("Automatic (RA/DHCPv6)"))
......@@ -61,7 +54,7 @@ ipv6_gateway.default = wan6.ip6gw
ipv6_gateway.datatype = "ip6addr"
if dns_static then
local s = f:section(Section)
s = f:section(Section)
local dns = s:option(DynamicList, "dns", translate("Static DNS servers"))
dns.default = uci:get_list("gluon-wan-dnsmasq", dns_static, "server")
......@@ -74,57 +67,83 @@ if dns_static then
end
end
local s = f:section(Section)
s = f:section(Section)
local mesh_wan = s:option(Flag, "mesh_wan", translate("Enable meshing on the WAN interface"))
mesh_wan.default = not uci:get_bool("network", "mesh_wan", "disabled")
local pretty_ifnames = {
["/wan"] = translate("WAN Interfaces"),
["/single"] = translate("Interface"),
["/lan"] = translate("LAN Interfaces")
}
function mesh_wan:write(data)
uci:set("network", "mesh_wan", "disabled", not data)
end
uci:foreach('gluon', 'interface', function(config)
local section_name = config['.name']
local ifaces = s:option(MultiListValue, section_name, pretty_ifnames[config.name] or config.name)
if sysconfig.lan_ifname then
local s = f:section(Section)
local mesh_lan = s:option(Flag, "mesh_lan", translate("Enable meshing on the LAN interface"))
mesh_lan.default = not uci:get_bool("network", "mesh_lan", "disabled")
function mesh_lan:write(data)
uci:set("network", "mesh_lan", "disabled", not data)
ifaces.orientation = 'horizontal'
ifaces:value('uplink', 'Uplink')
ifaces:value('mesh', 'Mesh')
ifaces:value('client', 'Client')
ifaces:exclusive('uplink', 'client')
ifaces:exclusive('mesh', 'client')
local interfaces = uci:get_list("network", "client", "ifname")
ifaces.default = config.role
for lanif in sysconfig.lan_ifname:gmatch('%S+') do
if data then
util.remove_from_set(interfaces, lanif)
else
util.add_to_set(interfaces, lanif)
end
function ifaces:write(data)
uci:set_list("gluon", section_name, "role", data)
end
end)
uci:set_list("network", "client", "ifname", interfaces)
end
end
local section
uci:foreach("system", "gpio_switch", function(s)
if s[".name"]:match("poe") then
uci:foreach("system", "gpio_switch", function(si)
if si[".name"]:match("poe") then
if not section then
section = f:section(Section)
end
local port = s.name:match("^PoE Power Port(%d*)$")
local texts = {
["^PoE Power Port(%d*)$"] = {
get_title = function(m) return translatef("Enable PoE Power Port %s", m[1]) end,
active_low = false,
},
["^PoE Passthrough$"] = {
get_title = function() return translate("Enable PoE Passthrough") end,
active_low = false,
},
-- Typo in AP-303H (ipq40xx-generic)
["^POE passtrough disable$"] = {
get_title = function() return translate("Enable PoE Passthrough") end,
active_low = true,
},
}
local name
if port then
name = translatef("Enable PoE Power Port %s", port)
else
name = translate("Enable " .. s.name)
local active_low = false
for pattern, text_obj in pairs(texts) do
local match = {si.name:match(pattern)}
if match[1] then
name = text_obj.get_title(match)
active_low = text_obj.active_low
break
end
end
if not name then
name = translatef('Enable "%s"', si.name)
end
local poe = section:option(Flag, si[".name"], name)
poe.default = uci:get_bool("system", si[".name"], "value")
if active_low then
poe.default = not poe.default
end
local poe = section:option(Flag, s[".name"], name)
poe.default = uci:get_bool("system", s[".name"], "value")
function poe:write(data)
uci:set("system", s[".name"], "value", data)
local write_value = data
if active_low then
write_value = not write_value
end
uci:set("system", si[".name"], "value", write_value)
end
end
end)
......@@ -150,9 +169,10 @@ function f:write()
uci:delete("network", "wan6", "ip6gw")
end
uci:commit('gluon')
uci:commit("network")
uci:commit('system')
end
return f