1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-03-09 15:40:03 +00:00

Update luci and theme

This commit is contained in:
Ycarus 2019-05-28 21:51:29 +02:00
parent fe03553aae
commit 4d7962337f
165 changed files with 74180 additions and 13802 deletions

View file

@ -0,0 +1,66 @@
<%#
Copyright 2010 Jo-Philipp Wich <jo@mein.io>
Licensed to the public under the Apache License 2.0.
-%>
<% export("uci_changelog", function(changes) -%>
<div class="cbi-section">
<strong><%:Legend:%></strong>
<div class="uci-change-legend">
<div class="uci-change-legend-label"><ins>&#160;</ins> <%:Section added%></div>
<div class="uci-change-legend-label"><del>&#160;</del> <%:Section removed%></div>
<div class="uci-change-legend-label"><var><ins>&#160;</ins></var> <%:Option changed%></div>
<div class="uci-change-legend-label"><var><del>&#160;</del></var> <%:Option removed%></div>
<br style="clear:both" />
</div>
<br />
<div class="uci-change-list"><%
local util = luci.util
local tpl = {
["add-3"] = "<ins>uci add %0 <strong>%3</strong> # =%2</ins>",
["set-3"] = "<ins>uci set %0.<strong>%2</strong>=%3</ins>",
["set-4"] = "<var><ins>uci set %0.%2.%3=<strong>%4</strong></ins></var>",
["remove-2"] = "<del>uci del %0.<strong>%2</strong></del>",
["remove-3"] = "<var><del>uci del %0.%2.<strong>%3</strong></del></var>",
["order-3"] = "<var>uci reorder %0.%2=<strong>%3</strong></var>",
["list-add-4"] = "<var><ins>uci add_list %0.%2.%3=<strong>%4</strong></ins></var>",
["list-del-4"] = "<var><del>uci del_list %0.%2.%3=<strong>%4</strong></del></var>",
["rename-3"] = "<var>uci rename %0.%2=<strong>%3</strong></var>",
["rename-4"] = "<var>uci rename %0.%2.%3=<strong>%4</strong></var>"
}
local conf, deltas
for conf, deltas in util.kspairs(changes) do
write("<h3># /etc/config/%s</h3>" % conf)
local _, delta, added
for _, delta in pairs(deltas) do
local t = tpl["%s-%d" %{ delta[1], #delta }]
write(t:gsub("%%(%d)", function(n)
if n == "0" then
return conf
elseif n == "2" then
if added and delta[2] == added[1] then
return "@%s[-1]" % added[2]
else
return delta[2]
end
elseif n == "4" then
return util.shellquote(delta[4])
else
return delta[tonumber(n)]
end
end))
if delta[1] == "add" then
added = { delta[2], delta[3] }
end
end
write("<br />")
end
%></div>
</div>
<%- end) %>

View file

@ -0,0 +1,45 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<%-
local node, redir_url = luci.dispatcher.lookup(luci.http.formvalue("redir"))
export("redirect", redir_url or url("admin/uci/changes"))
include("admin_uci/changelog")
-%>
<h2 name="content"><%:Configuration%> / <%:Changes%></h2>
<% if changes then %>
<%- uci_changelog(changes) -%>
<% else %>
<p><strong><%:There are no pending changes!%></strong></p>
<% end %>
<div class="alert-message" id="cbi_apply_status" style="display:none"></div>
<div class="cbi-page-actions">
<% if redir_url then %>
<form method="get" action="<%=luci.util.pcdata(redir_url)%>">
<input class="cbi-button cbi-button-link" type="submit" value="<%:Back%>" />
</form>
<% end %>
<form method="post" action="<%=url("admin/uci/changes")%>">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="redir" value="<%=pcdata(luci.http.formvalue("redir"))%>" />
<input class="cbi-button cbi-button-save" type="submit" name="trigger_apply" value="<%:Save & Apply%>" />
</form>
<form method="post" action="<%=url("admin/uci/revert")%>">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="redir" value="<%=pcdata(luci.http.formvalue("redir"))%>" />
<input class="cbi-button cbi-button-reset" type="submit" value="<%:Revert%>" />
</form>
</div>
<%+footer%>

View file

@ -0,0 +1,33 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<%-
local node, redir_url = luci.dispatcher.lookup(luci.http.formvalue("redir"))
export("redirect", redir_url or url("admin/uci/changes"))
include("admin_uci/changelog")
-%>
<h2 name="content"><%:Configuration%> / <%:Revert%></h2>
<% if changes then %>
<p><strong><%:The following changes have been reverted%>:</strong></p>
<%- uci_changelog(changes) -%>
<% else %>
<p><strong><%:There are no pending changes to revert!%></strong></p>
<% end %>
<% if redir_url then %>
<div class="cbi-page-actions">
<form class="inline" method="get" action="<%=luci.util.pcdata(redir_url)%>">
<input class="cbi-button cbi-button-link" style="margin:0" type="submit" value="<%:Back%>" />
</form>
</div>
<% end %>
<%+footer%>

View file

@ -1,49 +1,4 @@
<% export("cbi_apply_widget", function(redirect_ok, rollback_token) -%>
<style type="text/css">
#cbi_apply_overlay {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
display: none;
z-index: 20000;
}
#cbi_apply_overlay .alert-message {
position: relative;
top: 10%;
width: 60%;
margin: auto;
display: flex;
flex-wrap: wrap;
min-height: 32px;
align-items: center;
}
#cbi_apply_overlay .alert-message > h4,
#cbi_apply_overlay .alert-message > p,
#cbi_apply_overlay .alert-message > div {
flex-basis: 100%;
}
#cbi_apply_overlay .alert-message > img {
margin-right: 1em;
flex-basis: 32px;
}
body.apply-overlay-active {
overflow: hidden;
height: 100vh;
}
body.apply-overlay-active #cbi_apply_overlay {
display: block;
}
</style>
<script type="text/javascript" src="<%=resource%>/cbi.js?v=git-18.138.59467-72fe5dd"></script>
<script type="text/javascript">//<![CDATA[
var xhr = new XHR(),
uci_apply_auth = { sid: '<%=luci.dispatcher.context.authsession%>', token: '<%=token%>' },
@ -55,28 +10,22 @@
was_xhr_poll_running = false;
function uci_status_message(type, content) {
var overlay = document.getElementById('cbi_apply_overlay') || document.body.appendChild(E('<div id="cbi_apply_overlay"><div class="alert-message"></div></div>')),
message = overlay.querySelector('.alert-message');
if (type) {
var message = showModal('', '');
if (message && type) {
if (!message.classList.contains(type)) {
message.classList.remove('notice');
message.classList.remove('warning');
message.classList.add(type);
}
message.classList.add('alert-message');
DOMTokenList.prototype.add.apply(message.classList, type.split(/\s+/));
if (content)
message.innerHTML = content;
document.body.classList.add('apply-overlay-active');
if (!was_xhr_poll_running) {
was_xhr_poll_running = XHR.running();
XHR.halt();
}
}
else {
document.body.classList.remove('apply-overlay-active');
hideModal();
if (was_xhr_poll_running)
XHR.run();
@ -85,19 +34,18 @@
function uci_rollback(checked) {
if (checked) {
uci_status_message('warning',
'<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
'<%:Failed to confirm apply within %ds, waiting for rollback…%>'.format(uci_apply_rollback));
uci_status_message('warning spinning',
'<p><%:Failed to confirm apply within %ds, waiting for rollback…%></p>'.format(uci_apply_rollback));
var call = function(r, data, duration) {
if (r.status === 204) {
uci_status_message('warning',
'<h4><%:Configuration has been rolled back!%></h4>' +
'<p><%:The device could not be reached within %d seconds after applying the pending changes, which caused the configuration to be rolled back for safety reasons. If you believe that the configuration changes are correct nonetheless, perform an unchecked configuration apply. Alternatively, you can dismiss this warning and edit changes before attempting to apply again, or revert all pending changes to keep the currently working configuration state.%></p>'.format(uci_apply_rollback) +
'<p><%:The device could not be reached within %d seconds after applying the pending changes, which caused the configuration to be rolled back for safety reasons. If you believe that the configuration changes are correct nonetheless, proceed by applying anyway. Alternatively, you can dismiss this warning and edit changes before attempting to apply again, or revert all pending changes to keep the currently working configuration state.%></p>'.format(uci_apply_rollback) +
'<div class="right">' +
'<input type="button" class="btn" onclick="uci_status_message(false)" value="<%:Dismiss%>" /> ' +
'<input type="button" class="btn cbi-button-action important" onclick="uci_revert()" value="<%:Revert changes%>" /> ' +
'<input type="button" class="btn cbi-button-negative important" onclick="uci_apply(false)" value="<%:Apply unchecked%>" />' +
'<input type="button" class="btn cbi-button-negative important" onclick="uci_apply(false)" value="<%:Apply anyway%>" />' +
'</div>');
return;
@ -126,6 +74,7 @@
var call = function(r, data, duration) {
if (Date.now() >= deadline) {
window.clearTimeout(tt);
uci_rollback(checked);
return;
}
@ -133,7 +82,7 @@
var indicator = document.querySelector('.uci_change_indicator');
if (indicator) indicator.style.display = 'none';
uci_status_message('notice', '<%:Configuration has been applied.%>');
uci_status_message('notice', '<p><%:Configuration has been applied.%></p>');
window.clearTimeout(tt);
window.setTimeout(function() {
@ -156,9 +105,8 @@
var tick = function() {
var now = Date.now();
uci_status_message('notice',
'<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
'<%:Waiting for configuration to get applied… %ds%>'.format(Math.max(Math.floor((deadline - Date.now()) / 1000), 0)));
uci_status_message('notice spinning',
'<p><%:Waiting for configuration to be applied… %ds%></p>'.format(Math.max(Math.floor((deadline - Date.now()) / 1000), 0)));
if (now >= deadline)
return;
@ -174,9 +122,7 @@
}
function uci_apply(checked) {
uci_status_message('notice',
'<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
'<%:Starting configuration apply…%>');
uci_status_message('notice spinning', '<p><%:Starting configuration apply…%></p>');
xhr.post('<%=url("admin/uci")%>/' + (checked ? 'apply_rollback' : 'apply_unchecked'), uci_apply_auth, function(r, tok) {
if (r.status === (checked ? 200 : 204)) {
@ -186,7 +132,7 @@
uci_confirm(checked, Date.now() + uci_apply_rollback * 1000);
}
else if (checked && r.status === 204) {
uci_status_message('notice', '<%:There are no changes to apply.%>');
uci_status_message('notice', '<p><%:There are no changes to apply.%></p>');
window.setTimeout(function() {
<% if redirect_ok then -%>
location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');
@ -196,20 +142,18 @@
}, uci_apply_display * 1000);
}
else {
uci_status_message('warning', '<%_Apply request failed with status <code>%h</code>%>'.format(r.responseText || r.statusText || r.status));
uci_status_message('warning', '<p><%_Apply request failed with status <code>%h</code>%></p>'.format(r.responseText || r.statusText || r.status));
window.setTimeout(function() { uci_status_message(false); }, uci_apply_display * 1000);
}
});
}
function uci_revert() {
uci_status_message('notice',
'<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
'<%:Reverting configuration…%>');
uci_status_message('notice spinning', '<p><%:Reverting configuration…%></p>');
xhr.post('<%=url("admin/uci/revert")%>', uci_apply_auth, function(r) {
if (r.status === 200) {
uci_status_message('notice', '<%:Changes have been reverted.%>');
uci_status_message('notice', '<p><%:Changes have been reverted.%></p>');
window.setTimeout(function() {
<% if redirect_ok then -%>
location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');
@ -219,7 +163,7 @@
}, uci_apply_display * 1000);
}
else {
uci_status_message('warning', '<%_Revert request failed with status <code>%h</code>%>'.format(r.statusText || r.status));
uci_status_message('warning', '<p><%_Revert request failed with status <code>%h</code>%></p>'.format(r.statusText || r.status));
window.setTimeout(function() { uci_status_message(false); }, uci_apply_display * 1000);
}
});

View file

@ -1,8 +1,10 @@
<% local v = self:cfgvalue(section) -%>
<%+cbi/valueheader%>
<input class="cbi-input-text" type="text"<%= attr("value", v) .. attr("name", cbid) .. attr("id", cbid) %> />
<script type="text/javascript">
cbi_init()
cbi_browser_init('<%=cbid%>', '<%=resource%>', '<%=url('admin/filebrowser')%>'<%=self.default_path and ", '"..self.default_path.."'"%>);
</script>
<input class="cbi-input-text" type="text"<%=
attr("id", cbid) ..
attr("name", cbid) ..
attr("value", self:cfgvalue(section) or self.default) ..
attr("data-browser", self.default_path or "")
%> />
<%+cbi/valuefooter%>

View file

@ -6,7 +6,7 @@
<div class="td cbi-value-field<% if self.error and self.error[section] then %> cbi-value-error<% end %>"<%=
attr("data-name", self.option) ..
ifattr(ftype and #ftype > 0, "data-type", ftype) ..
ifattr(title and #title > 0, "data-title", title) ..
ifattr(descr and #descr > 0, "data-description", descr)
ifattr(title and #title > 0, "data-title", title, true) ..
ifattr(descr and #descr > 0, "data-description", descr, true)
%>>
<div id="cbi-<%=self.config.."-"..section.."-"..self.option%>" data-index="<%=self.index%>" data-depends="<%=pcdata(self:deplist2json(section))%>">

View file

@ -30,7 +30,7 @@
<li<%=
attr("data-index", i) ..
attr("data-depends", self:deplist2json(section, self.deplist[i])) ..
attr("value", key) ..
attr("data-value", key) ..
ifattr(selected[key], "selected", "selected")
%>>
<%=pcdata(self.vallist[i])%>

View file

@ -6,22 +6,8 @@
self.keylist, self.vallist,
self.datatype, self.optional or self.rmempty
})) ..
attr("data-values", luci.util.serialize_json(self:cfgvalue(section))) ..
ifattr(self.size, "data-size", self.size) ..
ifattr(self.placeholder, "data-placeholder", self.placeholder)
%>>
<%
local vals = self:cfgvalue(section) or {}
for i=1, #vals + 1 do
local val = vals[i]
if (val and #val > 0) or (i == 1) then
%>
<input class="cbi-input-text" value="<%=pcdata(val)%>" data-update="change" type="text"<%=
attr("id", cbid .. "." .. i) ..
attr("name", cbid) ..
ifattr(self.size, "size") ..
ifattr(i == 1 and self.placeholder, "placeholder", self.placeholder)
%> /><br />
<% end end %>
</div>
%>></div>
<%+cbi/valuefooter%>

View file

@ -63,7 +63,7 @@
if empty then
%>
<label class="zonebadge zonebadge-empty">
<strong><%=zone:forward():upper()%></strong>
<strong><%=def:forward():upper()%></strong>
</label>
<% end %>
</div>

View file

@ -30,7 +30,7 @@
ifattr(self.rmempty or self.optional, "optional", "optional")
%>>
<script type="item-template"><!--
<li value="{{value}}">
<li data-value="{{value}}">
<span class="zonebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">
<strong>{{value}}:</strong><em>(<%:create%>)</em>
</span>
@ -38,7 +38,7 @@
--></script>
<ul>
<% if self.allowlocal then %>
<li value=""<%=ifattr(checked[""], "selected", "selected")%>>
<li data-value=""<%=ifattr(checked[""], "selected", "selected")%>>
<span style="background-color:<%=fwm.zone.get_color()%>" class="zonebadge">
<strong><%:Device%></strong>
<% if self.allowany and self.allowlocal then -%>
@ -48,14 +48,14 @@
</span>
</li>
<% elseif self.widget ~= "checkbox" and (self.rmempty or self.optional) then %>
<li value=""<%=ifattr(checked[""], "selected", "selected")%>>
<li data-value=""<%=ifattr(checked[""], "selected", "selected")%>>
<span class="zonebadge">
<em><%:unspecified%></em>
</span>
</li>
<% end %>
<% if self.allowany then %>
<li value="*"<%=ifattr(checked["*"], "selected", "selected")%>>
<li data-value="*"<%=ifattr(checked["*"], "selected", "selected")%>>
<span style="background-color:<%=fwm.zone.get_color()%>" class="zonebadge">
<strong><%:Any zone%></strong>
<% if self.allowany and self.allowlocal then %>(<%:forward%>)<% end %>
@ -67,7 +67,7 @@
if zone:name() ~= self.exclude then
selected = selected or (value == zone:name())
%>
<li<%=attr("value", zone:name()) .. ifattr(checked[zone:name()], "selected", "selected")%>>
<li<%=attr("data-value", zone:name()) .. ifattr(checked[zone:name()], "selected", "selected")%>>
<span style="background-color:<%=zone:get_color()%>" class="zonebadge">
<strong><%=zone:name()%>:</strong>
<%-
@ -94,11 +94,11 @@
<% end end %>
<% if self.widget ~= "checkbox" and not self.nocreate then %>
<li value="-">
<li data-value="-">
<span class="zonebadge">
<em><%:create%>:</em>
<input type="password" style="display:none" />
<input class="create-item-input" type="text" />
<input class="create-item-input" type="text" data-type="and(uciname,maxlength(11))" data-optional="true" />
</span>
</li>
<% end %>

View file

@ -0,0 +1,27 @@
<%+cbi/valueheader%>
<script type="text/javascript">
function switchToCIDRList(ev) {
var input = ev.target.previousElementSibling,
usecidr = document.getElementById(input.id + '_usecidr');
ev.preventDefault();
usecidr.value = '1';
cbi_d_update();
}
</script>
<input data-update="change"<%=
attr("id", cbid) ..
attr("name", cbid) ..
attr("type", "text") ..
attr("class", "cbi-input-text") ..
attr("value", self:cfgvalue(section) or self.default) ..
ifattr(self.size, "size") ..
ifattr(self.placeholder, "placeholder") ..
ifattr(self.datatype, "data-type", self.datatype) ..
ifattr(self.datatype, "data-optional", self.optional or self.rmempty) ..
ifattr(self.combobox_manual, "data-manual", self.combobox_manual) ..
ifattr(#self.keylist > 0, "data-choices", { self.keylist, self.vallist })
%> /><!--
--><button class="cbi-button cbi-button-neutral" title="<%:Switch to CIDR list notation%>" aria-label="<%:Switch to CIDR list notation%>" onclick="switchToCIDRList(event)"></button>
<%+cbi/valuefooter%>

View file

@ -3,25 +3,25 @@
<%- end end -%>
<div class="cbi-map" id="cbi-<%=self.config%>">
<% if self.title and #self.title > 0 then %><h2 name="content"><%=self.title%></h2><% end %>
<% if self.description and #self.description > 0 then %><div class="cbi-map-descr"><%=self.description%></div><% end %>
<% if self.title and #self.title > 0 then %>
<h2 name="content"><%=self.title%></h2>
<% end %>
<% if self.description and #self.description > 0 then %>
<div class="cbi-map-descr"><%=self.description%></div>
<% end %>
<% if self.tabbed then %>
<ul class="cbi-tabmenu map">
<%- self.selected_tab = luci.http.formvalue("tab.m-" .. self.config) %>
<% for i, section in ipairs(self.children) do %>
<%- if not self.selected_tab then self.selected_tab = section.sectiontype end %>
<li id="tab.m-<%=self.config%>.<%=section.section or section.sectiontype%>" class="cbi-tab<%=(section.sectiontype == self.selected_tab) and '' or '-disabled'%>">
<a onclick="this.blur(); return cbi_t_switch('m-<%=self.config%>', '<%=section.section or section.sectiontype%>')" href="<%=REQUEST_URI%>?tab.m-<%=self.config%>=<%=section.section or section.sectiontype%>"><%=section.title or section.section or section.sectiontype %></a>
<% if section.sectiontype == self.selected_tab then %><input type="hidden" id="tab.m-<%=self.config%>" name="tab.m-<%=self.config%>" value="<%=section.section or section.sectiontype%>" /><% end %>
</li>
<div>
<% for i, section in ipairs(self.children) do
tab = section.section or section.sectiontype %>
<div class="cbi-tabcontainer"<%=
attr("id", "container.m-%s.%s" %{ self.config, tab }) ..
attr("data-tab", tab) ..
attr("data-tab-title", section.title or tab)
%>>
<% section:render() %>
</div>
<% end %>
</ul>
<% for i, section in ipairs(self.children) do %>
<div class="cbi-tabcontainer" id="container.m-<%=self.config%>.<%=section.section or section.sectiontype%>"<% if section.sectiontype ~= self.selected_tab then %> style="display:none"<% end %>>
<% section:render() %>
</div>
<script type="text/javascript">cbi_t_add('m-<%=self.config%>', '<%=section.section or section.sectiontype%>')</script>
<% end %>
</div>
<% if not self.save then -%>
<div class="cbi-section-error">

View file

@ -41,13 +41,13 @@
<input type="hidden" name="<%=cbeid%>" value="1" />
<div class="cbi-dropdown" display-items="5" placeholder="<%:-- please select -- %>"<%=
<div class="cbi-dropdown" display-items="10" placeholder="<%:-- please select -- %>"<%=
attr("name", cbid) ..
ifattr(self.widget == "checkbox", "multiple", "multiple") ..
ifattr(self.widget == "checkbox", "optional", "optional")
%>>
<script type="item-template"><!--
<li value="{{value}}">
<li data-value="{{value}}">
<img title="<%:Custom Interface%>: &quot;{{value}}&quot;" src="<%=resource%>/icons/ethernet_disabled.png" />
<span class="hide-open">{{value}}</span>
<span class="hide-close"><%:Custom Interface%>: "{{value}}"</span>
@ -61,7 +61,7 @@
iface:name() ~= self.exclude
then %>
<li<%=
attr("value", iface:name()) ..
attr("data-value", iface:name()) ..
ifattr(checked[iface:name()], "selected", "selected")
%>>
<img<%=attr("title", iface:get_i18n())%> src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" />
@ -78,7 +78,7 @@
</li>
<% end end %>
<% if not self.nocreate then %>
<li value="">
<li data-value="">
<img title="<%:Custom Interface%>" src="<%=resource%>/icons/ethernet_disabled.png" />
<span><%:Custom Interface%>:</span>
<input type="password" style="display:none" />

View file

@ -20,13 +20,13 @@
end
-%>
<div class="cbi-dropdown" display-items="5" placeholder="<%:-- please select -- %>"<%=
<div class="cbi-dropdown" display-items="10" placeholder="<%:-- please select -- %>"<%=
attr("name", cbid) ..
ifattr(self.widget == "checkbox", "multiple", "multiple") ..
ifattr(self.widget == "checkbox", "optional", "optional")
%>>
<script type="item-template"><!--
<li value="{{value}}">
<li data-value="{{value}}">
<span class="ifacebadge" style="background:repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px)">
{{value}}: <em>(<%:create%>)</em>
</span>
@ -34,7 +34,7 @@
--></script>
<ul>
<% if self.widget ~= "checkbox" then %>
<li value=""<%= ifattr(not value, "selected", "selected") %>>
<li data-value=""<%= ifattr(not value, "selected", "selected") %>>
<em><%:unspecified%></em>
</li>
<% end %>
@ -44,7 +44,7 @@
(net:name() ~= self.exclude) and
(not self.novirtual or not net:is_virtual())
then %>
<li<%= attr("value", net:name()) .. ifattr(checked[net:name()], "selected", "selected") %>>
<li<%= attr("data-value", net:name()) .. ifattr(checked[net:name()], "selected", "selected") %>>
<span class="ifacebadge"><%=net:name()%>:
<%
local empty = true
@ -63,7 +63,7 @@
<% end end %>
<% if not self.nocreate then %>
<li value="-"<%= ifattr(not value and self.widget ~= "checkbox", "selected", "selected") %>>
<li data-value="-"<%= ifattr(not value and self.widget ~= "checkbox", "selected", "selected") %>>
<em>
<%- if self.widget == "checkbox" then -%>
<%:create:%>

View file

@ -11,7 +11,6 @@
<input type="submit" class="cbi-button" name="cbi.rns.<%=self.config%>.<%=section%>" value="<%:Delete%>" />
</div>
<%- end %>
<%+cbi/tabmenu%>
<div class="cbi-section-node<% if self.tabs then %> cbi-section-node-tabbed<% end %>" id="cbi-<%=self.config%>-<%=section%>">
<%+cbi/ucisection%>
</div>

View file

@ -1,7 +1,14 @@
<% for tab, data in pairs(self.tabs) do %>
<div class="cbi-tabcontainer" id="container.<%=self.config%>.<%=section%>.<%=tab%>"<% if tab ~= self.selected_tab then %> style="display:none"<% end %>>
<% if data.description then %><div class="cbi-tab-descr"><%=data.description%></div><% end %>
<% for _, tab in ipairs(self.tab_names) do data = self.tabs[tab] %>
<div class="cbi-tabcontainer"<%=
attr("id", "container.%s.%s.%s" %{ self.config, section, tab }) ..
attr("data-tab", tab) ..
attr("data-tab-title", data.title) ..
attr("data-tab-active", tostring(tab == self.selected_tab))
%>>
<% if data.description then %>
<div class="cbi-tab-descr"><%=data.description%></div>
<% end %>
<% self:render_tab(tab, section, scope or {}) %>
</div>
<script type="text/javascript">cbi_t_add('<%=self.config%>.<%=section%>', '<%=tab%>')</script>
<% end %>

View file

@ -1,12 +0,0 @@
<%- if self.tabs then %>
<ul class="cbi-tabmenu">
<%- self.selected_tab = luci.http.formvalue("tab." .. self.config .. "." .. section) %>
<%- for _, tab in ipairs(self.tab_names) do if #self.tabs[tab].childs > 0 then %>
<%- if not self.selected_tab then self.selected_tab = tab end %>
<li id="tab.<%=self.config%>.<%=section%>.<%=tab%>" class="cbi-tab<%=(tab == self.selected_tab) and '' or '-disabled'%>">
<a onclick="this.blur(); return cbi_t_switch('<%=self.config%>.<%=section%>', '<%=tab%>')" href="<%=REQUEST_URI%>?tab.<%=self.config%>.<%=section%>=<%=tab%>"><%=self.tabs[tab].title%></a>
<% if tab == self.selected_tab then %><input type="hidden" id="tab.<%=self.config%>.<%=section%>" name="tab.<%=self.config%>.<%=section%>" value="<%=tab%>" /><% end %>
</li>
<% end end -%>
</ul>
<% end -%>

View file

@ -127,7 +127,7 @@ end
section = k
local sectionname = striptags((type(self.sectiontitle) == "function") and self:sectiontitle(section) or k)
local sectiontitle = ifattr(sectionname and (not self.anonymous or self.sectiontitle), "data-title", sectionname)
local sectiontitle = ifattr(sectionname and (not self.anonymous or self.sectiontitle), "data-title", sectionname, true)
local colorclass = (self.extedit or self.rowcolors) and rowstyle() or ""
local scope = {
valueheader = "cbi/cell_valueheader",

View file

@ -2,6 +2,11 @@
<% if self.title and #self.title > 0 then -%>
<legend><%=self.title%></legend>
<%- end %>
<% if self.error_msg and #self.error_msg > 0 then -%>
<div class="cbi-section-error">
<%=self.error_msg%>
</div>
<%- end %>
<% if self.description and #self.description > 0 then -%>
<div class="cbi-section-descr"><%=self.description%></div>
<%- end %>
@ -18,8 +23,6 @@
<h3><%=section:upper()%></h3>
<%- end %>
<%+cbi/tabmenu%>
<div class="cbi-section-node<% if self.tabs then %> cbi-section-node-tabbed<% end %>" id="cbi-<%=self.config%>-<%=section%>">
<%+cbi/ucisection%>
</div>

View file

@ -1,6 +1,6 @@
<%+cbi/valueheader%>
<%- if self.password then -%>
<input type="password" style="position:absolute; left:-4000px"<%=
<input type="password" style="position:absolute; left:-1000px" aria-hidden="true" tabindex="-1"<%=
attr("name", "password." .. cbid)
%> />
<%- end -%>
@ -21,6 +21,6 @@
ifattr(#self.keylist > 0, "data-choices", { self.keylist, self.vallist })
%> />
<%- if self.password then -%>
<div class="cbi-button cbi-button-neutral" title="<%:Reveal/hide password%>" onclick="var e = this.previousElementSibling; e.type = (e.type === 'password') ? 'text' : 'password'"></div>
<button class="cbi-button cbi-button-neutral" title="<%:Reveal/hide password%>" aria-label="<%:Reveal/hide password%>" onclick="var e = this.previousElementSibling; e.type = (e.type === 'password') ? 'text' : 'password'; event.preventDefault()"></button>
<% end %>
<%+cbi/valuefooter%>

View file

@ -0,0 +1,168 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
var freqlist = <%= luci.http.write_json(self.iwinfo.freqlist) %>;
var hwmodes = <%= luci.http.write_json(self.iwinfo.hwmodelist or {}) %>;
var htmodes = <%= luci.http.write_json(self.iwinfo.htmodelist) %>;
var channels = {
'11g': [
'auto', 'auto', true
],
'11a': [
'auto', 'auto', true
]
};
for (var i = 0; i < freqlist.length; i++)
channels[(freqlist[i].mhz > 2484) ? '11a' : '11g'].push(
freqlist[i].channel,
'%d (%d MHz)'.format(freqlist[i].channel, freqlist[i].mhz),
!freqlist[i].restricted
);
var modes = [
'', 'Legacy', true,
'n', 'N', hwmodes.n,
'ac', 'AC', hwmodes.ac
];
var htmodes = {
'': [
'', '-', true
],
'n': [
'HT20', '20 MHz', htmodes.HT20,
'HT40', '40 MHz', htmodes.HT40
],
'ac': [
'VHT20', '20 MHz', htmodes.VHT20,
'VHT40', '40 MHz', htmodes.VHT40,
'VHT80', '80 MHz', htmodes.VHT80,
'VHT160', '160 MHz', htmodes.VHT160
]
};
var bands = {
'': [
'11g', '2.4 GHz', (channels['11g'].length > 3),
'11a', '5 GHz', (channels['11a'].length > 3)
],
'n': [
'11g', '2.4 GHz', (channels['11g'].length > 3),
'11a', '5 GHz', (channels['11a'].length > 3)
],
'ac': [
'11a', '5 GHz', true
]
};
function cbi_set_values(sel, vals)
{
if (sel.vals)
sel.vals.selected = sel.selectedIndex;
while (sel.options[0])
sel.remove(0);
for (var i = 0; vals && i < vals.length; i += 3)
{
if (!vals[i+2])
continue;
var opt = document.createElement('option');
opt.value = vals[i+0];
opt.text = vals[i+1];
sel.add(opt);
}
if (!isNaN(vals.selected))
sel.selectedIndex = vals.selected;
sel.parentNode.style.display = (sel.options.length <= 1) ? 'none' : '';
sel.vals = vals;
}
function cbi_toggle_wifi_mode(id)
{
cbi_toggle_wifi_htmode(id);
cbi_toggle_wifi_band(id);
}
function cbi_toggle_wifi_htmode(id)
{
var mode = document.getElementById(id + '.mode');
var bwdt = document.getElementById(id + '.htmode');
cbi_set_values(bwdt, htmodes[mode.value]);
}
function cbi_toggle_wifi_band(id)
{
var mode = document.getElementById(id + '.mode');
var band = document.getElementById(id + '.band');
cbi_set_values(band, bands[mode.value]);
cbi_toggle_wifi_channel(id);
}
function cbi_toggle_wifi_channel(id)
{
var band = document.getElementById(id + '.band');
var chan = document.getElementById(id + '.channel');
cbi_set_values(chan, channels[band.value]);
}
function cbi_init_wifi(id)
{
var mode = document.getElementById(id + '.mode');
var band = document.getElementById(id + '.band');
var chan = document.getElementById(id + '.channel');
var bwdt = document.getElementById(id + '.htmode');
cbi_set_values(mode, modes);
if (/VHT20|VHT40|VHT80|VHT160/.test(<%= luci.http.write_json(self.map:get(section, "htmode")) %>))
mode.value = 'ac';
else if (/HT20|HT40/.test(<%= luci.http.write_json(self.map:get(section, "htmode")) %>))
mode.value = 'n';
else
mode.value = '';
cbi_toggle_wifi_mode(id);
if (/a/.test(<%= luci.http.write_json(self.map:get(section, "hwmode")) %>))
band.value = '11a';
else
band.value = '11g';
cbi_toggle_wifi_band(id);
bwdt.value = <%= luci.http.write_json(self.map:get(section, "htmode")) %>;
chan.value = <%= luci.http.write_json(self.map:get(section, "channel")) %>;
}
//]]></script>
<label style="float:left; margin-right:3px">
<%:Mode%><br />
<select style="width:auto" id="<%= cbid %>.mode" name="<%= cbid %>.mode" onchange="cbi_toggle_wifi_mode('<%= cbid %>')"></select>
</label>
<label style="float:left; margin-right:3px">
<%:Band%><br />
<select style="width:auto" id="<%= cbid %>.band" name="<%= cbid %>.band" onchange="cbi_toggle_wifi_band('<%= cbid %>')"></select>
</label>
<label style="float:left; margin-right:3px">
<%:Channel%><br />
<select style="width:auto" id="<%= cbid %>.channel" name="<%= cbid %>.channel"></select>
</label>
<label style="float:left; margin-right:3px">
<%:Width%><br />
<select style="width:auto" id="<%= cbid %>.htmode" name="<%= cbid %>.htmode"></select>
</label>
<br style="clear:left" />
<script type="text/javascript">cbi_init_wifi('<%= cbid %>');</script>
<%+cbi/valuefooter%>

View file

@ -0,0 +1,11 @@
<%#
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
Copyright 2018 Daniel F. Dickinson <cshored@thecshore.com>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<p>Component not present.</p>
<%+footer%>

View file

@ -10,3 +10,15 @@
luci.dispatcher.context.template_header_sent = true
end
%>
<script type="text/javascript" src="<%=resource%>/luci.js"></script>
<script type="text/javascript">
L = new LuCI(<%= luci.http.write_json({
token = token,
resource = resource,
scriptname = luci.http.getenv("SCRIPT_NAME"),
pathinfo = luci.http.getenv("PATH_INFO"),
requestpath = luci.dispatcher.context.requestpath,
pollinterval = luci.config.main.pollinterval or 5
}) %>);
</script>

View file

@ -0,0 +1,95 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(-1, '<%=url('admin/dhcplease_status')%>', null,
function(x, st)
{
var tb = document.getElementById('lease_status_table');
if (st && st[0] && tb)
{
var rows = [];
for (var i = 0; i < st[0].length; i++)
{
var timestr;
if (st[0][i].expires === false)
timestr = '<em><%:unlimited%></em>';
else if (st[0][i].expires <= 0)
timestr = '<em><%:expired%></em>';
else
timestr = String.format('%t', st[0][i].expires);
rows.push([
st[0][i].hostname || '?',
st[0][i].ipaddr,
st[0][i].macaddr,
timestr
]);
}
cbi_update_table(tb, rows, '<em><%:There are no active leases.%></em>');
}
var tb6 = document.getElementById('lease6_status_table');
if (st && st[1] && tb6)
{
tb6.parentNode.style.display = 'block';
var rows = [];
for (var i = 0; i < st[1].length; i++)
{
var timestr;
if (st[1][i].expires === false)
timestr = '<em><%:unlimited%></em>';
else if (st[1][i].expires <= 0)
timestr = '<em><%:expired%></em>';
else
timestr = String.format('%t', st[1][i].expires);
var name = st[1][i].hostname,
hint = st[1][i].host_hint;
rows.push([
hint ? '%h (%h)'.format(name || '?', hint) : (name || '?'),
st[1][i].ip6addr,
st[1][i].duid,
timestr
]);
}
cbi_update_table(tb6, rows, '<em><%:There are no active leases.%></em>');
}
}
);
//]]></script>
<div class="cbi-section">
<h3><%:Active DHCP Leases%></h3>
<div class="table" id="lease_status_table">
<div class="tr table-titles">
<div class="th"><%:Hostname%></div>
<div class="th"><%:IPv4-Address%></div>
<div class="th"><%:MAC-Address%></div>
<div class="th"><%:Leasetime remaining%></div>
</div>
<div class="tr placeholder">
<div class="td"><em><%:Collecting data...%></em></div>
</div>
</div>
</div>
<div class="cbi-section" style="display:none">
<h3><%:Active DHCPv6 Leases%></h3>
<div class="table" id="lease6_status_table">
<div class="tr table-titles">
<div class="th"><%:Host%></div>
<div class="th"><%:IPv6-Address%></div>
<div class="th"><%:DUID%></div>
<div class="th"><%:Leasetime remaining%></div>
</div>
<div class="tr placeholder">
<div class="td"><em><%:Collecting data...%></em></div>
</div>
</div>
</div>

View file

@ -0,0 +1,120 @@
<%
local supports_deauth = {}
local _, v
for _, v in ipairs(luci.util.ubus()) do
local iface = v:match("^hostapd%.(.+)$")
if iface then
local funcs = luci.util.ubus(v)
if type(funcs) == "table" and funcs.del_client then
supports_deauth[iface] = true
end
end
end
%>
<script type="text/javascript">//<![CDATA[
var supports_deauth = <%= luci.http.write_json(supports_deauth) %>;
function wifirate(bss, rx) {
var p = rx ? 'rx_' : 'tx_',
s = '%.1f <%:Mbit/s%>, %d<%:MHz%>'
.format(bss[p+'rate'] / 1000, bss[p+'mhz']),
ht = bss[p+'ht'], vht = bss[p+'vht'],
mhz = bss[p+'mhz'], nss = bss[p+'nss'],
mcs = bss[p+'mcs'], sgi = bss[p+'short_gi'];
if (ht || vht) {
if (vht) s += ', VHT-MCS %d'.format(mcs);
if (nss) s += ', VHT-NSS %d'.format(nss);
if (ht) s += ', MCS %s'.format(mcs);
if (sgi) s += ', <%:Short GI%>';
}
return s;
}
function handleDeauth(ev) {
(new XHR()).post('<%=url('admin/wireless_deauth')%>', {
token: '<%=token%>',
iface: ev.target.getAttribute('data-iface'),
bssid: ev.target.getAttribute('data-bssid')
}, function() {
ev.target.disabled = true;
});
}
XHR.poll(-1, '<%=url('admin/wireless_assoclist')%>', null,
function(x, st)
{
var tb = document.getElementById('wifi_assoclist_table');
if (st && tb)
{
var rows = [];
st.forEach(function(bss) {
var icon;
var q = (-1 * (bss.noise - bss.signal)) / 5;
if (q < 1)
icon = "<%=resource%>/icons/signal-0.png";
else if (q < 2)
icon = "<%=resource%>/icons/signal-0-25.png";
else if (q < 3)
icon = "<%=resource%>/icons/signal-25-50.png";
else if (q < 4)
icon = "<%=resource%>/icons/signal-50-75.png";
else
icon = "<%=resource%>/icons/signal-75-100.png";
rows.push([
'<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> <a href="%s">%h</a><small>&#160;(%h)</small></span>'.format(
bss.radio,
bss.link,
bss.name,
bss.ifname),
bss.bssid,
bss.host_hint ? '%h (%h)'.format(bss.host_name || '?', bss.host_hint) : (bss.host_name || '?'),
'<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>'.format(
bss.signal,
bss.noise,
bss.signal - bss.noise,
icon,
bss.signal,
bss.noise),
E('span', {}, [
E('span', wifirate(bss, true)),
E('br'),
E('span', wifirate(bss, false))
]),
supports_deauth[bss.ifname] ? E('input', {
type: 'button',
class: 'cbi-button cbi-button-remove',
value: '<%:Disconnect%>',
'data-bssid': bss.bssid,
'data-iface': bss.ifname,
click: handleDeauth
}) : '-'
]);
});
cbi_update_table(tb, rows, '<em><%:No information available%></em>');
}
}
);
//]]></script>
<div class="table" id="wifi_assoclist_table">
<div class="tr table-titles">
<div class="th nowrap"><%:Network%></div>
<div class="th hide-xs"><%:MAC-Address%></div>
<div class="th nowrap"><%:Host%></div>
<div class="th nowrap"><%:Signal%> / <%:Noise%></div>
<div class="th nowrap"><%:RX Rate%> / <%:TX Rate%></div>
<% if next(supports_deauth) then %>
<div class="th right"><%:Disconnect%></div>
<% end %>
</div>
<div class="tr placeholder">
<div class="td"><em><%:Collecting data...%></em></div>
</div>
</div>