diff options
Diffstat (limited to 'modules/luci-base/luasrc')
-rw-r--r-- | modules/luci-base/luasrc/cbi.lua | 46 | ||||
-rw-r--r-- | modules/luci-base/luasrc/dispatcher.lua | 11 | ||||
-rw-r--r-- | modules/luci-base/luasrc/model/uci.lua | 10 | ||||
-rw-r--r-- | modules/luci-base/luasrc/util.lua | 106 | ||||
-rw-r--r-- | modules/luci-base/luasrc/view/cbi/apply_widget.htm | 148 | ||||
-rw-r--r-- | modules/luci-base/luasrc/view/cbi/dropdown.htm | 42 | ||||
-rw-r--r-- | modules/luci-base/luasrc/view/cbi/firewall_zonelist.htm | 79 | ||||
-rw-r--r-- | modules/luci-base/luasrc/view/cbi/map.htm | 2 | ||||
-rw-r--r-- | modules/luci-base/luasrc/view/cbi/network_ifacelist.htm | 102 | ||||
-rw-r--r-- | modules/luci-base/luasrc/view/cbi/network_netlist.htm | 90 | ||||
-rw-r--r-- | modules/luci-base/luasrc/view/sysauth.htm | 4 |
11 files changed, 371 insertions, 269 deletions
diff --git a/modules/luci-base/luasrc/cbi.lua b/modules/luci-base/luasrc/cbi.lua index 4728642118..d275c5b275 100644 --- a/modules/luci-base/luasrc/cbi.lua +++ b/modules/luci-base/luasrc/cbi.lua @@ -1226,13 +1226,14 @@ function TypedSection.parse(self, novld) local stval = RESORT_PREFIX .. self.config .. "." .. self.sectiontype local order = self.map:formvalue(stval) if order and #order > 0 then - local sid - local num = 0 + local sids, sid = { }, nil for sid in util.imatch(order) do - self.map.uci:reorder(self.config, sid, num) - num = num + 1 + sids[#sids+1] = sid + end + if #sids > 0 then + self.map.uci:reorder(self.config, sids) + self.changed = true end - self.changed = (num > 0) end end @@ -1416,6 +1417,12 @@ function AbstractValue.parse(self, section, novld) self:add_error(section, "invalid", val_err) end + if self.alias then + self.section.aliased = self.section.aliased or {} + self.section.aliased[section] = self.section.aliased[section] or {} + self.section.aliased[section][self.alias] = true + end + if fvalue and (self.forcewrite or not (fvalue == cvalue)) then if self:write(section, fvalue) then -- Push events @@ -1425,10 +1432,16 @@ function AbstractValue.parse(self, section, novld) end else -- Unset the UCI or error if self.rmempty or self.optional then - if self:remove(section) then - -- Push events - self.section.changed = true - --luci.util.append(self.map.events, self.events) + if not self.alias or + not self.section.aliased or + not self.section.aliased[section] or + not self.section.aliased[section][self.alias] + then + if self:remove(section) then + -- Push events + self.section.changed = true + --luci.util.append(self.map.events, self.events) + end end elseif cvalue ~= fvalue and not novld then -- trigger validator with nil value to get custom user error msg. @@ -1454,7 +1467,7 @@ function AbstractValue.cfgvalue(self, section) if self.tag_error[section] then value = self:formvalue(section) else - value = self.map:get(section, self.option) + value = self.map:get(section, self.alias or self.option) end if not value then @@ -1495,12 +1508,12 @@ AbstractValue.transform = AbstractValue.validate -- Write to UCI function AbstractValue.write(self, section, value) - return self.map:set(section, self.option, value) + return self.map:set(section, self.alias or self.option, value) end -- Remove from UCI function AbstractValue.remove(self, section) - return self.map:del(section, self.option) + return self.map:del(section, self.alias or self.option) end @@ -1833,6 +1846,15 @@ function DynamicList.formvalue(self, section) end +DropDown = class(MultiValue) + +function DropDown.__init__(self, ...) + ListValue.__init__(self, ...) + self.template = "cbi/dropdown" + self.delimiter = " " +end + + --[[ TextValue - A multi-line value rows: Rows diff --git a/modules/luci-base/luasrc/dispatcher.lua b/modules/luci-base/luasrc/dispatcher.lua index 2c58b0ab3d..6850d7e3a9 100644 --- a/modules/luci-base/luasrc/dispatcher.lua +++ b/modules/luci-base/luasrc/dispatcher.lua @@ -358,7 +358,7 @@ function dispatch(request) elseif key == "REQUEST_URI" then return build_url(unpack(ctx.requestpath)) elseif key == "FULL_REQUEST_URI" then - local url = { http.getenv("SCRIPT_NAME") or "" , http.getenv("PATH_INFO") } + local url = { http.getenv("SCRIPT_NAME") or "", http.getenv("PATH_INFO") } local query = http.getenv("QUERY_STRING") if query and #query > 0 then url[#url+1] = "?" @@ -507,10 +507,11 @@ function dispatch(request) else ok, err = util.copcall(target, unpack(args)) end - assert(ok, - "Failed to execute " .. (type(c.target) == "function" and "function" or c.target.type or "unknown") .. - " dispatcher target for entry '/" .. table.concat(request, "/") .. "'.\n" .. - "The called action terminated with an exception:\n" .. tostring(err or "(unknown)")) + if not ok then + error500("Failed to execute " .. (type(c.target) == "function" and "function" or c.target.type or "unknown") .. + " dispatcher target for entry '/" .. table.concat(request, "/") .. "'.\n" .. + "The called action terminated with an exception:\n" .. tostring(err or "(unknown)")) + end else local root = node() if not root or not root.target then diff --git a/modules/luci-base/luasrc/model/uci.lua b/modules/luci-base/luasrc/model/uci.lua index 461ba9d5a3..92c0d8f699 100644 --- a/modules/luci-base/luasrc/model/uci.lua +++ b/modules/luci-base/luasrc/model/uci.lua @@ -8,7 +8,7 @@ local table = require "table" local setmetatable, rawget, rawset = setmetatable, rawget, rawset local require, getmetatable, assert = require, getmetatable, assert -local error, pairs, ipairs = error, pairs, ipairs +local error, pairs, ipairs, select = error, pairs, ipairs, select local type, tostring, tonumber, unpack = type, tostring, tonumber, unpack -- The typical workflow for UCI is: Get a cursor instance from the @@ -106,7 +106,7 @@ function changes(self, config) local _, change for _, change in ipairs(changes) do local operation, section, option, value = unpack(change) - if option and value and operation ~= "add" then + if option and operation ~= "add" then res[package][section] = res[package][section] or { } if operation == "list-add" then @@ -373,15 +373,15 @@ function add(self, config, stype) return self:section(config, stype) end -function set(self, config, section, option, value) - if value == nil then +function set(self, config, section, option, ...) + if select('#', ...) == 0 then local sname, err = self:section(config, option, section) return (not not sname), err else local _, err = call("set", { config = config, section = section, - values = { [option] = value } + values = { [option] = select(1, ...) } }) return (err == nil), ERRSTR[err] end diff --git a/modules/luci-base/luasrc/util.lua b/modules/luci-base/luasrc/util.lua index ce42af2fb0..10428b0b35 100644 --- a/modules/luci-base/luasrc/util.lua +++ b/modules/luci-base/luasrc/util.lua @@ -100,6 +100,8 @@ end -- Scope manipulation routines -- +coxpt = setmetatable({}, { __mode = "kv" }) + local tl_meta = { __mode = "k", @@ -697,73 +699,69 @@ function checklib(fullpathexe, wantedlib) return false end +------------------------------------------------------------------------------- +-- Coroutine safe xpcall and pcall versions -- --- Coroutine safe xpcall and pcall versions modified for Luci --- original version: --- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org) +-- Encapsulates the protected calls with a coroutine based loop, so errors can +-- be dealed without the usual Lua 5.x pcall/xpcall issues with coroutines +-- yielding inside the call to pcall or xpcall. -- --- Copyright © 2005 Kepler Project. --- Permission is hereby granted, free of charge, to any person obtaining a --- copy of this software and associated documentation files (the "Software"), --- to deal in the Software without restriction, including without limitation --- the rights to use, copy, modify, merge, publish, distribute, sublicense, --- and/or sell copies of the Software, and to permit persons to whom the --- Software is furnished to do so, subject to the following conditions: +-- Authors: Roberto Ierusalimschy and Andre Carregal +-- Contributors: Thomas Harning Jr., Ignacio Burgueño, Fabio Mascarenhas -- --- The above copyright notice and this permission notice shall be --- included in all copies or substantial portions of the Software. +-- Copyright 2005 - Kepler Project -- --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, --- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES --- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. --- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, --- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, --- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE --- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -local performResume, handleReturnValue -local oldpcall, oldxpcall = pcall, xpcall -coxpt = {} -setmetatable(coxpt, {__mode = "kv"}) - --- Identity function for copcall -local function copcall_id(trace, ...) - return ... -end - --- values of either the function or the error handler -function coxpcall(f, err, ...) - local res, co = oldpcall(coroutine.create, f) - if not res then - local params = {...} - local newf = function() return f(unpack(params)) end - co = coroutine.create(newf) - end - local c = coroutine.running() - coxpt[co] = coxpt[c] or c or 0 +-- $Id: coxpcall.lua,v 1.13 2008/05/19 19:20:02 mascarenhas Exp $ +------------------------------------------------------------------------------- - return performResume(err, co, ...) -end - --- values of the function or the error object -function copcall(f, ...) - return coxpcall(f, copcall_id, ...) -end +------------------------------------------------------------------------------- +-- Implements xpcall with coroutines +------------------------------------------------------------------------------- +local coromap = setmetatable({}, { __mode = "k" }) --- Handle return value of protected call -function handleReturnValue(err, co, status, ...) +local function handleReturnValue(err, co, status, ...) if not status then return false, err(debug.traceback(co, (...)), ...) end - - if coroutine.status(co) ~= 'suspended' then + if coroutine.status(co) == 'suspended' then + return performResume(err, co, coroutine.yield(...)) + else return true, ... end - - return performResume(err, co, coroutine.yield(...)) end --- Resume execution of protected function call function performResume(err, co, ...) return handleReturnValue(err, co, coroutine.resume(co, ...)) end + +local function id(trace, ...) + return trace +end + +function coxpcall(f, err, ...) + local current = coroutine.running() + if not current then + if err == id then + return pcall(f, ...) + else + if select("#", ...) > 0 then + local oldf, params = f, { ... } + f = function() return oldf(unpack(params)) end + end + return xpcall(f, err) + end + else + local res, co = pcall(coroutine.create, f) + if not res then + local newf = function(...) return f(...) end + co = coroutine.create(newf) + end + coromap[co] = current + coxpt[co] = coxpt[current] or current or 0 + return performResume(err, co, ...) + end +end + +function copcall(f, ...) + return coxpcall(f, id, ...) +end diff --git a/modules/luci-base/luasrc/view/cbi/apply_widget.htm b/modules/luci-base/luasrc/view/cbi/apply_widget.htm index 543ef0b80b..702512f495 100644 --- a/modules/luci-base/luasrc/view/cbi/apply_widget.htm +++ b/modules/luci-base/luasrc/view/cbi/apply_widget.htm @@ -1,59 +1,98 @@ <% export("cbi_apply_widget", function(redirect_ok) -%> <style type="text/css"> - #cbi_apply_status { + .alert-message.notice { + background: linear-gradient(#fff 0%, #eee 100%); + } + + #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; - margin: 1.5em 0 1.5em 0; } - #cbi_apply_status > h4, - #cbi_apply_status > p, - #cbi_apply_status > div { + #cbi_apply_overlay .alert-message > h4, + #cbi_apply_overlay .alert-message > p, + #cbi_apply_overlay .alert-message > div { flex-basis: 100%; } - #cbi_apply_status > img { + #cbi_apply_overlay .alert-message > img { margin-right: 1em; flex-basis: 32px; } - #cbi_apply_status + script + .cbi-section { - margin-top: -1em; + body.apply-overlay-active { + overflow: hidden; + height: 100vh; } - .alert-message.notice { - background: linear-gradient(#fff 0%, #eee 100%); + body.apply-overlay-active #cbi_apply_overlay { + display: block; } </style> -<script type="text/javascript" src="<%=resource%>/cbi.js"></script> +<script type="text/javascript" src="<%=resource%>/cbi.js?v=git-18.138.59467-72fe5dd"></script> <script type="text/javascript">//<![CDATA[ var xhr = new XHR(), - stat, indicator, uci_apply_auth = { sid: '<%=luci.dispatcher.context.authsession%>', token: '<%=token%>' }, uci_apply_rollback = <%=math.max(luci.config and luci.config.apply and luci.config.apply.rollback or 30, 30)%>, uci_apply_holdoff = <%=math.max(luci.config and luci.config.apply and luci.config.apply.holdoff or 4, 1)%>, uci_apply_timeout = <%=math.max(luci.config and luci.config.apply and luci.config.apply.timeout or 5, 1)%>, uci_apply_display = <%=math.max(luci.config and luci.config.apply and luci.config.apply.display or 1.5, 1)%>; + 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 (message && type) { + if (!message.classList.contains(type)) { + message.classList.remove('notice'); + message.classList.remove('warning'); + message.classList.add(type); + } + + if (content) + message.innerHTML = content; + + document.body.classList.add('apply-overlay-active'); + } + else { + document.body.classList.remove('apply-overlay-active'); + } + } + function uci_rollback(checked) { if (checked) { - stat.classList.remove('notice'); - stat.classList.add('warning'); - stat.innerHTML = '<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', + '<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' + + '<%:Failed to confirm apply within %ds, waiting for rollback…%>'.format(uci_apply_rollback)); var call = function(r) { if (r.status === 204) { - stat.innerHTML = '<h4><%:Configuration has been rolled back!%></h4>' + + 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) + '<div class="right">' + - '<input type="button" class="btn" onclick="this.parentNode.parentNode.style.display=\'none\'" value="<%:Dismiss%>" /> ' + + '<input type="button" class="btn" onclick="uci_status_message(false)" value="<%:Dismiss%>" /> ' + '<input type="button" class="btn" onclick="uci_revert()" value="<%:Revert changes%>" /> ' + '<input type="button" class="btn danger" onclick="uci_apply(false)" value="<%:Apply unchecked%>" />' + - '</div>'; + '</div>'); return; } @@ -64,10 +103,9 @@ call({ status: 0 }); } else { - stat.classList.remove('notice'); - stat.classList.add('warning'); - stat.innerHTML = '<h4><%:Device unreachable!%></h4>' + - '<p><%:Could not regain access to the device after applying the configuration changes. You might need to reconnect if you modified network related settings such as the IP address or wireless security credentials.%></p>'; + uci_status_message('warning', + '<h4><%:Device unreachable!%></h4>' + + '<p><%:Could not regain access to the device after applying the configuration changes. You might need to reconnect if you modified network related settings such as the IP address or wireless security credentials.%></p>'); } } @@ -75,12 +113,7 @@ var tt; var ts = Date.now(); - stat = document.getElementById('cbi_apply_status'); - stat.style.display = ''; - stat.classList.remove('warning'); - stat.classList.add('notice'); - - indicator = document.querySelector('.uci_change_indicator'); + uci_status_message('notice'); var call = function(r) { if (Date.now() >= deadline) { @@ -88,15 +121,18 @@ return; } else if (r && (r.status === 200 || r.status === 204)) { - if (indicator) - indicator.style.display = 'none'; + var indicator = document.querySelector('.uci_change_indicator'); + if (indicator) indicator.style.display = 'none'; - stat.innerHTML = '<%:Configuration has been applied.%>'; + uci_status_message('notice', '<%:Configuration has been applied.%>'); window.clearTimeout(tt); window.setTimeout(function() { - stat.style.display = 'none'; - <% if redirect_ok then %>location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');<% end %> + <% if redirect_ok then -%> + location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>'); + <%- else -%> + window.location = window.location.href.split('#')[0]; + <% end %> }, uci_apply_display * 1000); return; @@ -108,8 +144,9 @@ var tick = function() { var now = Date.now(); - stat.innerHTML = '<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', + '<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))); if (now >= deadline) return; @@ -125,43 +162,39 @@ } function uci_apply(checked) { - stat = document.getElementById('cbi_apply_status'); - stat.style.display = ''; - stat.classList.remove('warning'); - stat.classList.add('notice'); - stat.innerHTML = '<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' + - '<%:Starting configuration apply…%>'; + uci_status_message('notice', + '<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' + + '<%:Starting configuration apply…%>'); xhr.post('<%=url("admin/uci")%>/' + (checked ? 'apply_rollback' : 'apply_unchecked'), uci_apply_auth, function(r) { if (r.status === (checked ? 200 : 204)) { uci_confirm(checked, Date.now() + uci_apply_rollback * 1000); } else if (checked && r.status === 204) { - stat.innerHTML = '<%:There are no changes to apply.%>'; + uci_status_message('notice', '<%:There are no changes to apply.%>'); window.setTimeout(function() { - stat.style.display = 'none'; - <% if redirect_ok then %>location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');<% end %> + <% if redirect_ok then -%> + location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>'); + <%- else -%> + uci_status_message(false); + <%- end %> }, uci_apply_display * 1000); } else { - stat.classList.add('warning'); - stat.classList.remove('notice'); - stat.innerHTML = '<%_Apply request failed with status <code>%h</code>%>'.format(r.responseText || r.statusText || r.status); + uci_status_message('warning', '<%_Apply request failed with status <code>%h</code>%>'.format(r.responseText || r.statusText || r.status)); + window.setTimeout(function() { uci_status_message(false); }, uci_apply_display * 1000); } }); } function uci_revert() { - stat = document.getElementById('cbi_apply_status'); - stat.style.display = ''; - stat.classList.remove('warning'); - stat.classList.add('notice'); - stat.innerHTML = '<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' + - '<%:Reverting configuration…%>'; + uci_status_message('notice', + '<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' + + '<%:Reverting configuration…%>'); xhr.post('<%=url("admin/uci/revert")%>', uci_apply_auth, function(r) { if (r.status === 200) { - stat.innerHTML = '<%:Changes have been reverted.%>'; + uci_status_message('notice', '<%:Changes have been reverted.%>'); window.setTimeout(function() { <% if redirect_ok then -%> location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>'); @@ -171,9 +204,8 @@ }, uci_apply_display * 1000); } else { - stat.classList.add('warning'); - stat.classList.remove('notice'); - stat.innerHTML = '<%_Revert request failed with status <code>%h</code>%>'.format(r.statusText || r.status); + uci_status_message('warning', '<%_Revert request failed with status <code>%h</code>%>'.format(r.statusText || r.status)); + window.setTimeout(function() { uci_status_message(false); }, uci_apply_display * 1000); } }); } diff --git a/modules/luci-base/luasrc/view/cbi/dropdown.htm b/modules/luci-base/luasrc/view/cbi/dropdown.htm new file mode 100644 index 0000000000..bdf7248375 --- /dev/null +++ b/modules/luci-base/luasrc/view/cbi/dropdown.htm @@ -0,0 +1,42 @@ +<%+cbi/valueheader%> + +<%- + local selected = { } + + if self.multiple then + local val + for val in luci.util.imatch(self:cfgvalue(section)) do + selected[val] = true + end + else + selected[self:cfgvalue(section)] = true + end + + if not next(selected) and self.default then + selected[self.default] = true + end +-%> + +<div class="cbi-dropdown"<%= + attr("name", cbid) .. + attr("display-items", self.display or self.size or 3) .. + attr("dropdown-items", self.dropdown or self.display or self.size or 5) .. + attr("placeholder", self.placeholder or translate("-- please select --")) .. + ifattr(self.multiple, "multiple", "multiple") .. + ifattr(self.optional or self.rmempty, "optional", "optional") +%>> + <ul> + <% local i, key; for i, key in pairs(self.keylist) do %> + <li<%= + attr("data-index", i) .. + attr("data-depends", self:deplist2json(section, self.deplist[i])) .. + attr("value", key) .. + ifattr(selected[key], "selected", "selected") + %>> + <%=pcdata(self.vallist[i])%> + </li> + <% end %> + </ul> +</div> + +<%+cbi/valuefooter%> diff --git a/modules/luci-base/luasrc/view/cbi/firewall_zonelist.htm b/modules/luci-base/luasrc/view/cbi/firewall_zonelist.htm index b4260707ef..3a108020b6 100644 --- a/modules/luci-base/luasrc/view/cbi/firewall_zonelist.htm +++ b/modules/luci-base/luasrc/view/cbi/firewall_zonelist.htm @@ -24,26 +24,42 @@ end -%> -<span> - <ul style="margin:0; list-style-type:none; text-align:left"> +<div class="cbi-dropdown" dropdown-items="5" placeholder="<%:-- please select -- %>"<%= + attr("name", cbid) .. + ifattr(self.widget == "checkbox", "multiple", "multiple") .. + ifattr(self.rmempty or self.optional, "optional", "optional") +%>> + <script type="item-template"><!-- + <li 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> + </li> + --></script> + <ul> <% if self.allowlocal then %> - <li style="padding:0.5em"> - <input class="cbi-input-radio" data-update="click change"<%=attr("type", self.widget or "radio") .. attr("id", cbid .. "_empty") .. attr("name", cbid) .. attr("value", "") .. ifattr(checked[""], "checked", "checked")%> />   - <label<%=attr("for", cbid .. "_empty")%>></label> - <label<%=attr("for", cbid .. "_empty")%> style="background-color:<%=fwm.zone.get_color()%>" class="zonebadge"> + <li 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 %>(<%:input%>)<% end %> - </label> + <% if self.allowany and self.allowlocal then -%> + (<%= self.alias ~= "dest" + and translate("output") or translate("input") %>) + <%- end %> + </span> + </li> + <% elseif self.widget ~= "checkbox" and (self.rmempty or self.optional) then %> + <li value=""<%=ifattr(checked[""], "selected", "selected")%>> + <span class="zonebadge"> + <em><%:unspecified%></em> + </span> </li> <% end %> <% if self.allowany then %> - <li style="padding:0.5em"> - <input class="cbi-input-radio" data-update="click change"<%=attr("type", self.widget or "radio") .. attr("id", cbid .. "_any") .. attr("name", cbid) .. attr("value", "*") .. ifattr(checked["*"], "checked", "checked")%> />   - <label<%=attr("for", cbid .. "_any")%>></label> - <label<%=attr("for", cbid .. "_any")%> style="background-color:<%=fwm.zone.get_color()%>" class="zonebadge"> + <li 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 %> - </label> + </span> </li> <% end %> <% @@ -51,45 +67,42 @@ if zone:name() ~= self.exclude then selected = selected or (value == zone:name()) %> - <li style="padding:0.5em"> - <input class="cbi-input-radio" data-update="click change"<%=attr("type", self.widget or "radio") .. attr("id", cbid .. "." .. zone:name()) .. attr("name", cbid) .. attr("value", zone:name()) .. ifattr(checked[zone:name()], "checked", "checked")%> />   - <label<%=attr("for", cbid .. "." .. zone:name())%>></label> - <label<%=attr("for", cbid .. "." .. zone:name())%> style="background-color:<%=zone:get_color()%>" class="zonebadge"> + <li<%=attr("value", zone:name()) .. ifattr(checked[zone:name()], "selected", "selected")%>> + <span style="background-color:<%=zone:get_color()%>" class="zonebadge"> <strong><%=zone:name()%>:</strong> - <% + <%- local zempty = true for _, net in ipairs(zone:get_networks()) do net = nwm:get_network(net) if net then zempty = false - %> + -%> <span class="ifacebadge<% if net:name() == self.network then %> ifacebadge-active<% end %>"><%=net:name()%>: - <% + <%- local nempty = true for _, iface in ipairs(net:is_bridge() and net:get_interfaces() or { net:get_interface() }) do nempty = false %> - <img<%=attr("title", iface:get_i18n())%> style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" /> + <img<%=attr("title", iface:get_i18n())%> src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" /> <% end %> - <% if nempty then %><em><%:(empty)%></em><% end %> + <% if nempty then %><em><%:(empty)%></em><% end -%> </span> - <% end end %> - <% if zempty then %><em><%:(empty)%></em><% end %> - </label> + <%- end end -%> + <%- if zempty then %><em><%:(empty)%></em><% end -%> + </span> </li> <% end end %> <% if self.widget ~= "checkbox" and not self.nocreate then %> - <li style="padding:0.5em"> - <input class="cbi-input-radio" data-update="click change" type="radio"<%=attr("id", cbid .. "_new") .. attr("name", cbid) .. attr("value", "-") .. ifattr(not selected, "checked", "checked")%> />   - <label<%=attr("for", cbid .. "_new")%>></label> - <div onclick="document.getElementById('<%=cbid%>_new').checked=true" class="zonebadge" style="background-color:<%=fwm.zone.get_color()%>"> - <em><%:unspecified -or- create:%> </em> - <input type="text"<%=attr("name", cbid .. ".newzone") .. ifattr(not selected, "value", luci.http.formvalue(cbid .. ".newzone") or self.default)%> onfocus="document.getElementById('<%=cbid%>_new').checked=true" /> - </div> + <li value="-"> + <span class="zonebadge"> + <em><%:create%>:</em> + <input type="password" style="display:none" /> + <input class="create-item-input" type="text" /> + </span> </li> <% end %> </ul> -</span> +</div> <%+cbi/valuefooter%> diff --git a/modules/luci-base/luasrc/view/cbi/map.htm b/modules/luci-base/luasrc/view/cbi/map.htm index 69ef3615a2..02b47f5455 100644 --- a/modules/luci-base/luasrc/view/cbi/map.htm +++ b/modules/luci-base/luasrc/view/cbi/map.htm @@ -1,5 +1,5 @@ <%- if firstmap and messages then local msg; for _, msg in ipairs(messages) do -%> - <div class="errorbox"><%=pcdata(msg)%></div> + <div class="alert-message warning"><%=pcdata(msg)%></div> <%- end end -%> <div class="cbi-map" id="cbi-<%=self.config%>"> diff --git a/modules/luci-base/luasrc/view/cbi/network_ifacelist.htm b/modules/luci-base/luasrc/view/cbi/network_ifacelist.htm index 62dbde7dd4..abfa33e1ed 100644 --- a/modules/luci-base/luasrc/view/cbi/network_ifacelist.htm +++ b/modules/luci-base/luasrc/view/cbi/network_ifacelist.htm @@ -19,7 +19,9 @@ if value then for value in utl.imatch(value) do - checked[value] = true + for value in utl.imatch(value) do + checked[value] = true + end end else local n = self.network and net:get_network(self.network) @@ -33,57 +35,51 @@ -%> <input type="hidden" name="<%=cbeid%>" value="1" /> -<ul style="margin:0; list-style-type:none"> - <% for _, iface in ipairs(ifaces) do - local link = iface:adminlink() - if (not self.nobridges or not iface:is_bridge()) and - (not self.noinactive or iface:is_up()) and - iface:name() ~= self.exclude - then %> - <li> - <input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%= - attr("type", self.widget or "radio") .. - attr("id", cbid .. "." .. iface:name()) .. - attr("name", cbid) .. attr("value", iface:name()) .. - ifattr(checked[iface:name()], "checked", "checked") - %> /> - <%- if not self.widget or self.widget == "checkbox" or self.widget == "radio" then -%> - <label<%=attr("for", cbid .. "." .. iface:name())%>></label> - <%- end -%> -   - <label<%=attr("for", cbid .. "." .. iface:name())%>> - <% if link then -%><a href="<%=link%>"><% end -%> - <img<%=attr("title", iface:get_i18n())%> style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" /> - <% if link then -%></a><% end -%> - <%=pcdata(iface:get_i18n())%> - <% local ns = iface:get_networks(); if #ns > 0 then %>( - <%- local i, n; for i, n in ipairs(ns) do -%> - <%-= (i>1) and ', ' -%> - <a href="<%=n:adminlink()%>"><%=n:name()%></a> - <%- end -%> - )<% end %> - </label> - </li> - <% end end %> - <% if not self.nocreate then %> - <li> - <input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%= - attr("type", self.widget or "radio") .. - attr("id", cbid .. "_custom") .. - attr("name", cbid) .. - attr("value", " ") - %> /> - <%- if not self.widget or self.widget == "checkbox" or self.widget == "radio" then -%> - <label<%=attr("for", cbid .. "_custom")%>></label> - <%- end -%> -   - <label<%=attr("for", cbid .. "_custom")%>> - <img title="<%:Custom Interface%>" style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/ethernet_disabled.png" /> - <%:Custom Interface%>: - </label> - <input type="text" style="width:50px" onfocus="document.getElementById('<%=cbid%>_custom').checked=true" onblur="var x=document.getElementById('<%=cbid%>_custom'); x.value=this.value; x.checked=true" /> - </li> - <% end %> -</ul> + +<div class="cbi-dropdown" display-items="5" 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}}"> + <img title="<%:Custom Interface%>: "{{value}}"" src="<%=resource%>/icons/ethernet_disabled.png" /> + <span class="hide-open">{{value}}</span> + <span class="hide-close"><%:Custom Interface%>: "{{value}}"</span> + </li> + --></script> + <ul> + <% for _, iface in ipairs(ifaces) do + if (not self.nobridges or not iface:is_bridge()) and + (not self.noinactive or iface:is_up()) and + iface:name() ~= self.exclude + then %> + <li<%= + attr("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" /> + <span class="hide-open"><%=pcdata(iface:name())%></span> + <span class="hide-close"> + <%=pcdata(iface:get_i18n())%> + <% local ns = iface:get_networks(); if #ns > 0 then %>( + <%- local i, n; for i, n in ipairs(ns) do -%> + <%-= (i>1) and ', ' -%> + <a href="<%=n:adminlink()%>"><%=n:name()%></a> + <%- end -%> + )<% end %> + </span> + </li> + <% end end %> + <% if not self.nocreate then %> + <li value=""> + <img title="<%:Custom Interface%>" src="<%=resource%>/icons/ethernet_disabled.png" /> + <span><%:Custom Interface%>:</span> + <input type="password" style="display:none" /> + <input class="create-item-input" type="text" /> + </li> + <% end %> + </ul> +</div> <%+cbi/valuefooter%> diff --git a/modules/luci-base/luasrc/view/cbi/network_netlist.htm b/modules/luci-base/luasrc/view/cbi/network_netlist.htm index 8bf1a70a20..ba6ebb8434 100644 --- a/modules/luci-base/luasrc/view/cbi/network_netlist.htm +++ b/modules/luci-base/luasrc/view/cbi/network_netlist.htm @@ -20,66 +20,62 @@ end -%> -<ul style="margin:0; list-style-type:none; text-align:left"> - <% for _, net in ipairs(networks) do - if (net:name() ~= "loopback") and - (net:name() ~= self.exclude) and - (not self.novirtual or not net:is_virtual()) - then %> - <li style="padding:0.25em 0"> - <input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%= - attr("type", self.widget or "radio") .. - attr("id", cbid .. "." .. net:name()) .. - attr("name", cbid) .. attr("value", net:name()) .. - ifattr(checked[net:name()], "checked", "checked") - %> />   - <label<%=attr("for", cbid .. "." .. net:name())%>> +<div class="cbi-dropdown" display-items="5" 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}}"> + <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> + </li> + --></script> + <ul> + <% if self.widget ~= "checkbox" then %> + <li value=""<%= ifattr(not value, "selected", "selected") %>> + <em><%:unspecified%></em> + </li> + <% end %> + + <% for _, net in ipairs(networks) do + if (net:name() ~= "loopback") and + (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") %>> <span class="ifacebadge"><%=net:name()%>: <% local empty = true for _, iface in ipairs(net:is_bridge() and net:get_interfaces() or { net:get_interface() }) do if not iface:is_bridge() then empty = false - %> + -%> <img<%=attr("title", iface:get_i18n())%> style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" /> - <% end end %> - <% if empty then %><em><%:(no interfaces attached)%></em><% end %> + <%- end end %> + <% if empty then %> + <em class="hide-close"><%:(no interfaces attached)%></em> + <em class="hide-open">-</em> + <% end %> </span> - </label> - </li> - <% end end %> + </li> + <% end end %> - <% if not self.nocreate then %> - <li style="padding:0.25em 0"> - <input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%=attr("type", self.widget or "radio") .. attr("id", cbid .. "_new") .. attr("name", cbid) .. attr("value", "-") .. ifattr(not value and self.widget ~= "checkbox", "checked", "checked")%> />   - <%- if not self.widget or self.widget == "checkbox" or self.widget == "radio" then -%> - <label<%=attr("for", cbid .. "_new")%>></label> - <%- end -%> - <div style="padding:0.5em; display:inline"> - <label<%=attr("for", cbid .. "_new")%>><em> + <% if not self.nocreate then %> + <li value="-"<%= ifattr(not value and self.widget ~= "checkbox", "selected", "selected") %>> + <em> <%- if self.widget == "checkbox" then -%> <%:create:%> <%- else -%> <%:unspecified -or- create:%> - <%- end -%> </em></label> + <%- end -%> + </em> <input style="display:none" type="password" /> - <input style="width:6em" type="text"<%=attr("name", cbid .. ".newnet")%> onfocus="document.getElementById('<%=cbid%>_new').checked=true" /> - </div> - </li> - <% elseif self.widget ~= "checkbox" and self.unspecified then %> - <li style="padding:0.25em 0"> - <input class="cbi-input-<%=self.widget or "radio"%>" data-update="click change"<%= - attr("type", self.widget or "radio") .. - attr("id", cbid .. "_uns") .. - attr("name", cbid) .. - attr("value", "") .. - ifattr(not value or #value == 0, "checked", "checked") - %> />   - <div style="padding:0.5em; display:inline"> - <label<%=attr("for", cbid .. "_uns")%>><em><%:unspecified%></em></label> - </div> - </li> - <% end %> -</ul> + <input class="create-item-input" type="text" /> + </li> + <% end %> + </ul> +</div> <%+cbi/valuefooter%> diff --git a/modules/luci-base/luasrc/view/sysauth.htm b/modules/luci-base/luasrc/view/sysauth.htm index b3ec9b7617..e7a741aaab 100644 --- a/modules/luci-base/luasrc/view/sysauth.htm +++ b/modules/luci-base/luasrc/view/sysauth.htm @@ -8,7 +8,9 @@ <form method="post" action="<%=pcdata(FULL_REQUEST_URI)%>"> <%- if fuser then %> - <div class="errorbox"><%:Invalid username and/or password! Please try again.%></div> + <div class="alert-message warning"> + <p><%:Invalid username and/or password! Please try again.%></p> + </div> <% end -%> <div class="cbi-map"> |