luci-base: dispatcher: introduce firstnode() dispatching target

The firstnode target will dispatch the request to the first eligible menu
subtree node that is not a redirect to another node, a special action or
post security enabled page.

That action is specifically useful for global category toplevel nodes like
"admin" which are supposed to simply direct access to the first installed
page node without having to hardcode specific choices.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2018-09-19 19:58:45 +02:00
parent 58d97b5e27
commit 11f7817d33

View file

@ -724,35 +724,84 @@ end
-- Subdispatchers -- -- Subdispatchers --
function _firstchild() function _find_eligible_node(root, prefix, deep, types, descend)
local _, cur_name, cur_node
local childs = { }
for cur_name, cur_node in pairs(root.nodes) do
childs[#childs+1] = {
node = cur_node,
name = cur_name,
order = cur_node.order or 100
}
end
table.sort(childs, function(a, b)
if a.order == b.order then
return a.name < b.name
else
return a.order < b.order
end
end)
if not root.leaf and deep ~= nil then
local sub_path = { unpack(prefix) }
if deep == false then
deep = nil
end
for _, cur_node in ipairs(childs) do
sub_path[#prefix+1] = cur_node.name
local res_path = _find_eligible_node(cur_node.node, sub_path,
deep, types, true)
if res_path then
return res_path
end
end
end
if descend and
(not types or
(type(root.target) == "table" and
util.contains(types, root.target.type)))
then
return prefix
end
end
function _find_node(recurse, types)
local path = { unpack(context.path) } local path = { unpack(context.path) }
local name = table.concat(path, ".") local name = table.concat(path, ".")
local node = context.treecache[name] local node = context.treecache[name]
local lowest path = _find_eligible_node(node, path, recurse, types)
if node and node.nodes and next(node.nodes) then
local k, v if path then
for k, v in pairs(node.nodes) do dispatch(path)
if not lowest or else
(v.order or 100) < (node.nodes[lowest].order or 100) require "luci.template".render("empty_node_placeholder")
then
lowest = k
end
end end
end end
if lowest == nil then function _firstchild()
require "luci.template".render("empty_node_placeholder") return _find_node(false, nil)
else
path[#path+1] = lowest
dispatch(path)
end
end end
function firstchild() function firstchild()
return { type = "firstchild", target = _firstchild } return { type = "firstchild", target = _firstchild }
end end
function _firstnode()
return _find_node(true, { "cbi", "form", "template", "arcombine" })
end
function firstnode()
return { type = "firstnode", target = _firstnode }
end
function alias(...) function alias(...)
local req = {...} local req = {...}
return function(...) return function(...)