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
  • v2023.2.5-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
137 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
  • experimental
  • hoodselector
  • master
  • nrb/gluon-master-cpe510
  • nrb/test-radv-filter
  • nrbffs/fastd-remove-delay
  • nrbffs/netgear-ex6120
  • radv-filterd
  • v2015.1.x
  • v2016.1.x
  • v2016.2.4-batmanbug
  • v2016.2.x
  • v2018.2.2-ffs
  • v2018.2.3-ffs
  • v2018.2.x
  • 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
  • v2020.2.x
  • v2021.1-ffs
  • v2021.1.1-ffs
  • v2021.1.2-ffs
  • 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
  • v2018.2.3-ffs0.1
  • v2019.1-ffs0.1
  • v2019.1.1-ffs0.1
  • v2019.1.2-ffs0.1
  • v2020.1-ffs0.1
  • v2020.1.1-ffs0.1
  • v2020.1.3-ffs0.1
  • v2020.2
  • v2020.2-ffs0.1
  • v2020.2.1-ffs0.1
  • v2020.2.2-ffs0.1
  • v2020.2.3-ffs0.1
  • v2020.2.3-ffs0.2
  • v2020.2.3-ffs0.3
  • v2020.2.x-ffs0.1
  • v2021.1-ffs0.1
  • v2021.1.1-ffs0.1
  • v2021.1.1-ffs0.2
  • v2021.1.1-ffs0.3
  • v2021.1.1-ffs0.4
  • v2021.1.2-ffs0.1
  • v2021.1.2-ffs0.2
98 results
Show changes
Showing
with 1814 additions and 5 deletions
<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>
<input data-update="change"<%=
attr("id", id) ..
attr("name", id) ..
attr("type", self.password and "password" or "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)
%>>
<div class="gluon-value<% if self.error then %> gluon-value-error<% end %>" id="value-<%=id%>" data-index="<%=self.index%>"<%= attr("data-depends", self:deplist()) %>>
<%- if self.title and #self.title > 0 then -%>
<label class="gluon-value-title"<%= attr("for", id) %>>
<%-|self.title-%>
</label>
<div class="gluon-value-field">
<%- end -%>
<% if self.subtemplate then include(self.subtemplate) end %>
<% if self.description and #self.description > 0 then -%>
<br>
<div class="gluon-value-description">
<%=self.description%>
</div>
<%- end %>
<%- if self.title and #self.title > 0 then -%>
</div>
<%- end -%>
</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 -%>
<%
for _, map in ipairs(maps) do
map:render(renderer)
end
%>
<script type="text/javascript" src="/static/gluon-web-model.js"></script>
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2013-03-29 12:13+0200\n"
"Last-Translator: Matthias Schiffer <mschiffer@universe-factory.net>\n"
"Language-Team: German\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Reset"
msgstr "Zurücksetzen"
msgid "Save"
msgstr "Speichern"
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2013-12-22 17:11+0200\n"
"Last-Translator: goofy <pierre.gaufillet@gmail.com>\n"
"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
msgid "Reset"
msgstr "Remise à zéro"
msgid "Save"
msgstr "Soumettre"
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Reset"
msgstr ""
msgid "Save"
msgstr ""
/*
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 javascript/gluon-web-model.min.js -c -m --ie
*/
(function() {
var dep_entries = {};
function Int(x) {
return (/^-?\d+$/.test(x) ? +x : NaN);
}
function Dec(x) {
return (/^-?\d*\.?\d+?$/.test(x) ? +x : NaN);
}
var validators = {
'integer': function() {
return !isNaN(Int(this));
},
'uinteger': function() {
return (Int(this) >= 0);
},
'float': function() {
return !isNaN(Dec(this));
},
'ufloat': function() {
return (Dec(this) >= 0);
},
'ipaddr': function() {
return validators.ip4addr.apply(this) ||
validators.ip6addr.apply(this);
},
'ip4addr': function() {
var match;
if ((match = this.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/))) {
return (match[1] >= 0) && (match[1] <= 255) &&
(match[2] >= 0) && (match[2] <= 255) &&
(match[3] >= 0) && (match[3] <= 255) &&
(match[4] >= 0) && (match[4] <= 255);
}
return false;
},
'ip6addr': function() {
if (this.indexOf('::') < 0)
return (this.match(/^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i) != null);
if (
(this.indexOf(':::') >= 0) || this.match(/::.+::/) ||
this.match(/^:[^:]/) || this.match(/[^:]:$/)
)
return false;
if (this.match(/^(?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}$/i))
return true;
if (this.match(/^(?:[a-f0-9]{1,4}:){7}:$/i))
return true;
if (this.match(/^:(?::[a-f0-9]{1,4}){7}$/i))
return true;
return false;
},
'wpakey': function() {
var v = this;
if (v.length == 64)
return (v.match(/^[a-f0-9]{64}$/i) != null);
else
return (v.length >= 8) && (v.length <= 63);
},
'range': function(min, max) {
var val = Dec(this);
return (val >= +min && val <= +max);
},
'min': function(min) {
return (Dec(this) >= +min);
},
'max': function(max) {
return (Dec(this) <= +max);
},
'irange': function(min, max) {
var val = Int(this);
return (val >= +min && val <= +max);
},
'imin': function(min) {
return (Int(this) >= +min);
},
'imax': function(max) {
return (Int(this) <= +max);
},
'minlength': function(min) {
return ((''+this).length >= +min);
},
'maxlength': function(max) {
return ((''+this).length <= +max);
},
};
function compile(type) {
var v, match;
if ((match = type.match(/^([^\(]+)\(([^,]+),([^\)]+)\)$/)) && (v = validators[match[1]]) !== undefined) {
return function() {
return v.apply(this, [match[2], match[3]]);
}
} else if ((match = type.match(/^([^\(]+)\(([^,\)]+)\)$/)) && (v = validators[match[1]]) !== undefined) {
return function() {
return v.apply(this, [match[2]]);
}
} else {
return validators[type];
}
}
function checkvalue(target, ref) {
var t = document.getElementById(target);
var value;
if (t) {
if (t.type == "checkbox") {
value = t.checked;
} else if (t.value) {
value = t.value;
} else {
value = "";
}
return (value == ref);
} else {
t = document.getElementById(target + '.' + ref);
if (t)
return (t.type == "radio" && t.checked);
}
return false;
}
function check(deps) {
for (var i=0; i < deps.length; i++) {
var stat = true;
for (var j in deps[i]) {
stat = (stat && checkvalue(j, deps[i][j]));
}
if (stat)
return true;
}
return false;
}
function update() {
window.dispatchEvent(new Event('gluon-update'));
var state = false;
for (var id in dep_entries) {
var entry = dep_entries[id];
var node = document.getElementById(id);
var parent = document.getElementById(entry.parent);
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;
for (next = parent.firstChild; next; next = next.nextSibling) {
if (next.getAttribute && parseInt(next.getAttribute('data-index'), 10) > entry.index) {
break;
}
}
if (!next) {
parent.appendChild(entry.node);
} else {
parent.insertBefore(entry.node, next);
}
entry.node.dispatchEvent(new Event('gluon-show'));
state = true;
}
// hide optionals widget if no choices remaining
if (parent && parent.parentNode && parent.getAttribute('data-optionals'))
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();
}
}
function bind(obj, type, callback, mode) {
if (!obj.addEventListener) {
obj.attachEvent('on' + type,
function() {
var e = window.event;
if (!e.target && e.srcElement)
e.target = e.srcElement;
return !!callback(e);
}
);
} else {
obj.addEventListener(type, callback, !!mode);
}
return obj;
}
function init_dynlist(parent, attr) {
var prefix = attr.prefix;
function dynlist_redraw(focus, add, del) {
var values = [];
while (parent.firstChild) {
var n = parent.firstChild;
var i = +n.index;
if (i != del) {
if (n.nodeName.toLowerCase() == 'input')
values.push(n.value || '');
else if (n.nodeName.toLowerCase() == 'select')
values[values.length-1] = n.options[n.selectedIndex].value;
}
parent.removeChild(n);
}
if (add >= 0) {
focus = add + 1;
values.splice(add, 0, '');
} else if (!attr.optional && values.length == 0) {
values.push('');
}
for (var i = 1; i <= values.length; i++) {
var t = document.createElement('input');
t.id = prefix + '.' + i;
t.name = prefix;
t.value = values[i-1];
t.type = 'text';
t.index = i;
if (attr.size)
t.size = attr.size;
if (attr.placeholder)
t.placeholder = attr.placeholder;
parent.appendChild(t);
if (attr.type)
validate_field(t, false, attr.type);
bind(t, 'keydown', dynlist_keydown);
bind(t, 'keypress', dynlist_keypress);
if (i == focus) {
t.focus();
} else if (-i == focus) {
t.focus();
/* force cursor to end */
var v = t.value;
t.value = ' '
t.value = v;
}
if (attr.optional || values.length > 1) {
var b = document.createElement('span');
b.className = 'gluon-remove';
parent.appendChild(b);
bind(b, 'click', dynlist_btnclick(false));
parent.appendChild(document.createElement('br'));
}
}
var b = document.createElement('span');
b.className = 'gluon-add';
parent.appendChild(b);
bind(b, 'click', dynlist_btnclick(true));
}
function dynlist_keypress(ev) {
ev = ev ? ev : window.event;
var se = ev.target ? ev.target : ev.srcElement;
if (se.nodeType == 3)
se = se.parentNode;
switch (ev.keyCode) {
/* backspace, delete */
case 8:
case 46:
if (se.value.length == 0) {
if (ev.preventDefault)
ev.preventDefault();
return false;
}
return true;
/* enter, arrow up, arrow down */
case 13:
case 38:
case 40:
if (ev.preventDefault)
ev.preventDefault();
return false;
}
return true;
}
function dynlist_keydown(ev) {
ev = ev ? ev : window.event;
var se = ev.target ? ev.target : ev.srcElement;
var index = 0;
var prev, next;
if (se) {
if (se.nodeType == 3)
se = se.parentNode;
index = se.index;
prev = se.previousSibling;
while (prev && prev.name != prefix)
prev = prev.previousSibling;
next = se.nextSibling;
while (next && next.name != prefix)
next = next.nextSibling;
}
switch (ev.keyCode) {
/* backspace, delete */
case 8:
case 46:
var del = (se.nodeName.toLowerCase() == 'select')
? true : (se.value.length == 0);
if (del) {
if (ev.preventDefault)
ev.preventDefault();
var focus = se.index;
if (ev.keyCode == 8)
focus = -focus+1;
dynlist_redraw(focus, -1, index);
return false;
}
break;
/* enter */
case 13:
dynlist_redraw(-1, index, -1);
break;
/* arrow up */
case 38:
if (prev)
prev.focus();
break;
/* arrow down */
case 40:
if (next)
next.focus();
break;
}
return true;
}
function dynlist_btnclick(add) {
return function(ev) {
ev = ev ? ev : window.event;
var se = ev.target ? ev.target : ev.srcElement;
var input = se.previousSibling;
while (input && input.name != prefix) {
input = input.previousSibling;
}
if (add) {
dynlist_keydown({
target: input,
keyCode: 13
});
} else {
input.value = '';
dynlist_keydown({
target: input,
keyCode: 8
});
}
return false;
}
}
dynlist_redraw(NaN, -1, -1);
}
function validate_field(field, optional, type) {
var check = compile(type);
if (!check)
return;
var validator = function() {
if (!field.form)
return;
field.className = field.className.replace(/ gluon-input-invalid/g, '');
var value = (field.options && field.options.selectedIndex > -1)
? field.options[field.options.selectedIndex].value : field.value;
if (!(((value.length == 0) && optional) || check.apply(value)))
field.className += ' gluon-input-invalid';
};
bind(field, "blur", validator);
bind(field, "keyup", validator);
bind(field, "gluon-revalidate", validator);
if (field.nodeName.toLowerCase() == 'select') {
bind(field, "change", validator);
bind(field, "click", validator);
}
validator();
}
function add(obj, dep, index) {
var entry = dep_entries[obj.id];
if (!entry) {
entry = {
"node": obj,
"parent": obj.parentNode.id,
"deps": [],
"index": index
};
dep_entries[obj.id] = entry;
}
entry.deps.push(dep)
}
(function() {
var nodes;
nodes = document.querySelectorAll('[data-depends]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
var index = parseInt(node.getAttribute('data-index'), 10);
var depends = JSON.parse(node.getAttribute('data-depends'));
if (!isNaN(index) && depends.length > 0) {
for (var alt = 0; alt < depends.length; alt++) {
add(node, depends[alt], index);
}
}
}
nodes = document.querySelectorAll('[data-update]');
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, function () {setTimeout(update, 0);});
}
}
nodes = document.querySelectorAll('[data-type]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
validate_field(node, node.getAttribute('data-optional') === 'true',
node.getAttribute('data-type'));
}
nodes = document.querySelectorAll('[data-dynlist]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
var attr = JSON.parse(node.getAttribute('data-dynlist'));
init_dynlist(node, attr);
}
update();
})();
})();
!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
-- 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.
local unistd = require 'posix.unistd'
local classes = require 'gluon.web.model.classes'
local util = require 'gluon.web.util'
local instanceof = util.instanceof
-- Loads a model from given file, creating an environment and returns it
local function load(filename, i18n)
local func = assert(loadfile(filename))
setfenv(func, setmetatable({}, {__index =
function(_, key)
return classes[key] or i18n[key] or _G[key]
end
}))
local models = { func() }
for k, model in ipairs(models) do
if not instanceof(model, classes.Node) then
error("model definition returned an invalid model object")
end
model.index = k
end
return models
end
return function(config, http, renderer, name, pkg)
local hidenav = false
local modeldir = config.base_path .. '/model/'
local filename = modeldir..name..'.lua'
if not unistd.access(filename) then
error("Model '" .. name .. "' not found!")
end
local i18n = setmetatable({
i18n = renderer.i18n
}, {
__index = renderer.i18n(pkg)
})
local maps = load(filename, i18n)
for _, map in ipairs(maps) do
map:parse(http)
end
for _, map in ipairs(maps) do
map:handle()
hidenav = hidenav or map.hidenav
end
renderer.render_layout('model/wrapper', {
maps = maps,
}, nil, {
hidenav = hidenav,
})
end
-- 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
local M = {}
M.FORM_NODATA = 0
M.FORM_VALID = 1
M.FORM_INVALID = -1
local function parse_datatype(code)
local match, arg, arg2
match, arg, arg2 = code:match('^([^%(]+)%(([^,]+),([^%)]+)%)$')
if match then
return datatypes[match], {arg, arg2}
end
match, arg = code:match('^([^%(]+)%(([^%)]+)%)$')
if match then
return datatypes[match], {arg}
end
return datatypes[code], {}
end
local function verify_datatype(dt, value)
if dt then
local c, args = parse_datatype(dt)
assert(c, "Invalid datatype")
return c(value, unpack(args))
end
return true
end
local Node = class()
M.Node = Node
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
function Node:append(obj)
table.insert(self.children, obj)
obj.index = #self.children
obj.parent = self
end
function Node:id_suffix()
return self.name or (self.index and tostring(self.index)) or '_'
end
function Node:id()
local prefix = self.parent and self.parent:id() or "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({
self = self,
id = self:id(),
scope = scope,
}, {__index = scope})
renderer.render(self.template, env, self.package)
end
end
function Node:render_children(renderer, scope)
for _, node in ipairs(self.children) do
node:render(renderer, scope)
end
end
function Node:depends(field, value)
local deps
if instanceof(field, Node) then
deps = { [field] = value }
else
deps = field
end
table.insert(self.deps, deps)
end
function Node:deplist(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
end
function Node:resolve_depends()
local updated = self:resolve_node_depends()
for _, node in ipairs(self.children) do
updated = updated or node:resolve_depends()
end
return updated
end
function Node:resolve_node_depends()
if #self.deps == 0 then
return false
end
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:reset_node()
return true
end
-- will be overridden: write(value)
function Node:write()
end
function Node:handle()
if self.state == M.FORM_VALID then
for _, node in ipairs(self.children) do
node:handle()
end
self:write(self.data)
end
end
local Template = class(Node)
M.Template = Template
function Template:__init__(template)
Node.__init__(self)
self.template = template
end
local AbstractValue = class(Node)
M.AbstractValue = AbstractValue
function AbstractValue:__init__(...)
Node.__init__(self, ...)
self.default = nil
self.size = nil
self.optional = false
self.template = "model/valuewrapper"
self.error = false
end
function AbstractValue:defaultvalue()
return self.default
end
function AbstractValue:formvalue(http)
return http:formvalue(self:id())
end
function AbstractValue:cfgvalue()
if self.state == M.FORM_NODATA then
return self:defaultvalue()
else
return self.data
end
end
function AbstractValue:reset_node()
self.data = nil
self.error = false
self.state = M.FORM_NODATA
end
function AbstractValue:parse(http)
self.data = self:formvalue(http)
if not self:validate() then
self.error = true
self.state = M.FORM_INVALID
return
end
self.state = M.FORM_VALID
end
function AbstractValue:resolve_node_depends()
if self.state == M.FORM_NODATA then
return false
end
return Node.resolve_node_depends(self)
end
function AbstractValue:validate()
if self.data and verify_datatype(self.datatype, self.data) then
return true
end
if type(self.data) == "string" and #self.data == 0 then
self.data = nil
end
if self.data == nil then
return self.optional
end
return false
end
local Value = class(AbstractValue)
M.Value = Value
function Value:__init__(...)
AbstractValue.__init__(self, ...)
self.subtemplate = "model/value"
end
local Flag = class(AbstractValue)
M.Flag = Flag
function Flag:__init__(...)
AbstractValue.__init__(self, ...)
self.subtemplate = "model/fvalue"
self.default = false
end
function Flag:formvalue(http)
return http:formvalue(self:id()) ~= nil
end
function Flag:validate()
return true
end
local ListValue = class(AbstractValue)
M.ListValue = ListValue
function ListValue:__init__(...)
AbstractValue.__init__(self, ...)
self.subtemplate = "model/lvalue"
self.size = 1
self.widget = "select"
self.keys = {}
self.entry_list = {}
end
function ListValue:value(key, val, ...)
key = tostring(key)
if self.keys[key] then
return
end
self.keys[key] = true
val = val or key
table.insert(self.entry_list, {
key = key,
value = tostring(val),
deps = {...},
})
end
function ListValue:entries()
local ret = {unpack(self.entry_list)}
if self:cfgvalue() == nil or self.optional then
table.insert(ret, 1, {
key = '',
value = '',
deps = {},
})
end
return ret
end
function ListValue:validate()
if self.keys[self.data] then
return true
end
if type(self.data) == "string" and #self.data == 0 then
self.data = nil
end
if self.data == nil then
return self.optional
end
return false
end
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, ...)
self.subtemplate = "model/dynlist"
end
function DynamicList:defaultvalue()
local value = self.default
if type(value) == "table" then
return value
else
return { value }
end
end
function DynamicList:formvalue(http)
return http:formvaluetable(self:id())
end
function DynamicList:validate()
if self.data == nil then
self.data = {}
end
if #self.data == 0 then
return self.optional
end
for _, v in ipairs(self.data) do
if not verify_datatype(self.datatype, v) then
return false
end
end
return true
end
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
-- 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 M = {}
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
return true
elseif val == "" or val == nil then
return true
end
return false
end
local function dec(val)
if val:match('^%-?%d*%.?%d+$') then
return tonumber(val)
end
end
local function int(val)
if val:match('^%-?%d+$') then
return tonumber(val)
end
end
function M.uinteger(val)
local n = int(val)
return (n ~= nil and n >= 0)
end
function M.integer(val)
return (int(val) ~= nil)
end
function M.ufloat(val)
local n = dec(val)
return (n ~= nil and n >= 0)
end
function M.float(val)
return (dec(val) ~= nil)
end
function M.ipaddr(val)
return M.ip4addr(val) or M.ip6addr(val)
end
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)
if not (n1 and n2 and n3 and n4) then return false end
return (
(n1 >= 0) and (n1 <= 255) and
(n2 >= 0) and (n2 <= 255) and
(n3 >= 0) and (n3 <= 255) and
(n4 >= 0) and (n4 <= 255)
)
end
function M.ip6addr(val)
local g1 = '%x%x?%x?%x?'
if not val:match('::') then
return val:match('^'..((g1..':'):rep(7))..g1..'$') ~= nil
end
if
val:match(':::') or val:match('::.+::') or
val:match('^:[^:]') or val:match('[^:]:$')
then
return false
end
local g0 = '%x?%x?%x?%x?'
for i = 2, 7 do
if val:match('^'..((g0..':'):rep(i))..g0..'$') then
return true
end
end
if val:match('^'..((g1..':'):rep(7))..':$') then
return true
end
if val:match('^:'..((':'..g1):rep(7))..'$') then
return true
end
return false
end
function M.wpakey(val)
if #val == 64 then
return (val:match("^%x+$") ~= nil)
else
return (#val >= 8) and (#val <= 63)
end
end
function M.range(val, vmin, vmax)
return M.min(val, vmin) and M.max(val, vmax)
end
function M.min(val, min)
val = dec(val)
min = tonumber(min)
if val ~= nil and min ~= nil then
return (val >= min)
end
return false
end
function M.max(val, max)
val = dec(val)
max = tonumber(max)
if val ~= nil and max ~= nil then
return (val <= max)
end
return false
end
function M.irange(val, vmin, vmax)
return M.integer(val) and M.range(val, vmin, vmax)
end
function M.imin(val, vmin)
return M.integer(val) and M.min(val, vmin)
end
function M.imax(val, vmax)
return M.integer(val) and M.max(val, vmax)
end
function M.minlength(val, min)
min = tonumber(min)
if min ~= nil then
return (#val >= min)
end
return false
end
function M.maxlength(val, max)
max = tonumber(max)
if max ~= nil then
return (#val <= max)
end
return false
end
return M
# Copyright (C) 2013 Nils Schneider <nils at nilsschneider.net>
# This is free software, licensed under the Apache 2.0 license.
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-web-network
include ../gluon.mk
define Package/gluon-web-network
TITLE:=gluon-web module for network port configuration
DEPENDS:=+gluon-web-admin +gluon-client-bridge
endef
$(eval $(call BuildPackageGluon,gluon-web-network))
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2015-05-04 02:08+0200\n"
"Last-Translator: <mschiffer@universe-factory.net>\n"
"Language-Team: German\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
......@@ -16,11 +16,41 @@ msgstr "Automatisch (DHCP)"
msgid "Automatic (RA/DHCPv6)"
msgstr "Automatisch (RA/DHCPv6)"
msgid "Enable meshing on the WAN interface"
msgstr "Mesh auf dem WAN-Port aktivieren"
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 "Gateway"
msgstr "Gateway"
msgid "IP address"
msgstr "IP-Adresse"
msgid "Enable meshing on the LAN interface"
msgstr "Mesh auf dem LAN-Port aktivieren"
msgid "IPv4"
msgstr "IPv4"
msgid "IPv6"
msgstr "IPv6"
msgid "Interface"
msgstr "Interface"
msgid "LAN Interfaces"
msgstr "LAN-Interfaces"
msgid "Netmask"
msgstr "Netzmaske"
msgid "Network"
msgstr "Netzwerk"
msgid "Static"
msgstr "Statisch"
......@@ -28,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"
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2015-08-19 23:30+0100\n"
"Last-Translator:Tobias Bernot <tqbs@airmail.cc>\n"
"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Automatic (DHCP)"
msgstr "Automatique (DHCP)"
msgid "Automatic (RA/DHCPv6)"
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 "Gateway"
msgstr "Passerelle"
msgid "IP address"
msgstr "Adresse IP"
msgid "IPv4"
msgstr "IPv4"
msgid "IPv6"
msgstr "IPv6"
msgid "Netmask"
msgstr "Masque de réseau"
msgid "Network"
msgstr "Réseau"
msgid "Static"
msgstr "Statique"
msgid "Static DNS servers"
msgstr "Adresse DNS statique"
msgid "WAN connection"
msgstr "Connexion WAN"
......@@ -7,10 +7,40 @@ msgstr ""
msgid "Automatic (RA/DHCPv6)"
msgstr ""
msgid "Enable meshing on the WAN interface"
msgid "Disabled"
msgstr ""
msgid "Enable meshing on the LAN interface"
msgid "Enable \"%s\""
msgstr ""
msgid "Enable PoE Passthrough"
msgstr ""
msgid "Enable PoE Power Port %s"
msgstr ""
msgid "Gateway"
msgstr ""
msgid "IP address"
msgstr ""
msgid "IPv4"
msgstr ""
msgid "IPv6"
msgstr ""
msgid "Interface"
msgstr ""
msgid "LAN Interfaces"
msgstr ""
msgid "Netmask"
msgstr ""
msgid "Network"
msgstr ""
msgid "Static"
......@@ -19,5 +49,8 @@ msgstr ""
msgid "Static DNS servers"
msgstr ""
msgid "WAN Interfaces"
msgstr ""
msgid "WAN connection"
msgstr ""
package 'gluon-web-network'
entry({"admin", "network"}, model("admin/network"), _("Network"), 40)
-- 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 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)
local ipv4 = s:option(ListValue, "ipv4", translate("IPv4"))
ipv4:value("dhcp", translate("Automatic (DHCP)"))
ipv4:value("static", translate("Static"))
ipv4:value("none", translate("Disabled"))
ipv4.default = wan.proto
local ipv4_addr = s:option(Value, "ipv4_addr", translate("IP address"))
ipv4_addr:depends(ipv4, "static")
ipv4_addr.default = wan.ipaddr
ipv4_addr.datatype = "ip4addr"
local ipv4_netmask = s:option(Value, "ipv4_netmask", translate("Netmask"))
ipv4_netmask:depends(ipv4, "static")
ipv4_netmask.default = wan.netmask or "255.255.255.0"
ipv4_netmask.datatype = "ip4addr"
local ipv4_gateway = s:option(Value, "ipv4_gateway", translate("Gateway"))
ipv4_gateway:depends(ipv4, "static")
ipv4_gateway.default = wan.gateway
ipv4_gateway.datatype = "ip4addr"
s = f:section(Section)
local ipv6 = s:option(ListValue, "ipv6", translate("IPv6"))
ipv6:value("dhcpv6", translate("Automatic (RA/DHCPv6)"))
ipv6:value("static", translate("Static"))
ipv6:value("none", translate("Disabled"))
ipv6.default = wan6.proto
local ipv6_addr = s:option(Value, "ipv6_addr", translate("IP address"))
ipv6_addr:depends(ipv6, "static")
ipv6_addr.default = wan6.ip6addr
ipv6_addr.datatype = "ip6addr"
local ipv6_gateway = s:option(Value, "ipv6_gateway", translate("Gateway"))
ipv6_gateway:depends(ipv6, "static")
ipv6_gateway.default = wan6.ip6gw
ipv6_gateway.datatype = "ip6addr"
if dns_static then
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")
dns.datatype = "ipaddr"
dns.optional = true
function dns:write(data)
uci:set_list("gluon-wan-dnsmasq", dns_static, "server", data)
uci:commit("gluon-wan-dnsmasq")
end
end
s = f:section(Section)
local pretty_ifnames = {
["/wan"] = translate("WAN Interfaces"),
["/single"] = translate("Interface"),
["/lan"] = translate("LAN Interfaces")
}
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)
ifaces.orientation = 'horizontal'
ifaces:value('uplink', 'Uplink')
ifaces:value('mesh', 'Mesh')
ifaces:value('client', 'Client')
ifaces:exclusive('uplink', 'client')
ifaces:exclusive('mesh', 'client')
ifaces.default = config.role
function ifaces:write(data)
uci:set_list("gluon", section_name, "role", data)
end
end)
local section
uci:foreach("system", "gpio_switch", function(si)
if si[".name"]:match("poe") then
if not section then
section = f:section(Section)
end
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
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
function poe:write(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)
function f:write()
uci:set("network", "wan", "proto", ipv4.data)
if ipv4.data == "static" then
uci:set("network", "wan", "ipaddr", ipv4_addr.data)
uci:set("network", "wan", "netmask", ipv4_netmask.data)
uci:set("network", "wan", "gateway", ipv4_gateway.data)
else
uci:delete("network", "wan", "ipaddr")
uci:delete("network", "wan", "netmask")
uci:delete("network", "wan", "gateway")
end
uci:set("network", "wan6", "proto", ipv6.data)
if ipv6.data == "static" then
uci:set("network", "wan6", "ip6addr", ipv6_addr.data)
uci:set("network", "wan6", "ip6gw", ipv6_gateway.data)
else
uci:delete("network", "wan6", "ip6addr")
uci:delete("network", "wan6", "ip6gw")
end
uci:commit('gluon')
uci:commit("network")
uci:commit('system')
end
return f
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-web-node-role
include ../gluon.mk
define Package/gluon-web-node-role
DEPENDS:=+gluon-web-admin +gluon-node-info
TITLE:=UI for specifying node role
endef
$(eval $(call BuildPackageGluon,gluon-web-node-role))