gluon-web-model: add dependency support for sections
- Add a dependency array to section template - Lift dependency handling from AbstractValue to Node - Split resolve_depends() into a function handling dependencies of a node itself (resolve_node_depends()), which now is used for all nodes, and the existing recursive descent through the node tree - When any node's dependencies are not satisfied, all descendents are reset recursively, meaning that an option in a section that is hidden will always be ignored, as if the option's own dependencies were unsatisfied Fixes: #1349
This commit is contained in:
parent
35950b44b7
commit
11a3b56617
@ -1,4 +1,4 @@
|
|||||||
<fieldset class="gluon-section">
|
<fieldset class="gluon-section" id="<%=id%>" data-index="<%=self.index%>"<%= attr("data-depends", self:deplist()) %>>
|
||||||
<% if self.title and #self.title > 0 then -%>
|
<% if self.title and #self.title > 0 then -%>
|
||||||
<legend><%|self.title%></legend>
|
<legend><%|self.title%></legend>
|
||||||
<%- end %>
|
<%- end %>
|
||||||
|
@ -47,6 +47,7 @@ M.Node = Node
|
|||||||
|
|
||||||
function Node:__init__(name, title, description)
|
function Node:__init__(name, title, description)
|
||||||
self.children = {}
|
self.children = {}
|
||||||
|
self.deps = {}
|
||||||
self.title = title or ""
|
self.title = title or ""
|
||||||
self.description = description or ""
|
self.description = description or ""
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -71,6 +72,12 @@ function Node:id()
|
|||||||
return prefix.."."..self:id_suffix()
|
return prefix.."."..self:id_suffix()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Node:reset()
|
||||||
|
for _, child in ipairs(self.children) do
|
||||||
|
child:reset()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function Node:parse(http)
|
function Node:parse(http)
|
||||||
for _, child in ipairs(self.children) do
|
for _, child in ipairs(self.children) do
|
||||||
child:parse(http)
|
child:parse(http)
|
||||||
@ -80,8 +87,8 @@ end
|
|||||||
function Node:render(renderer, scope)
|
function Node:render(renderer, scope)
|
||||||
if self.template then
|
if self.template then
|
||||||
local env = setmetatable({
|
local env = setmetatable({
|
||||||
self = self,
|
self = self,
|
||||||
id = self:id(),
|
id = self:id(),
|
||||||
scope = scope,
|
scope = scope,
|
||||||
}, {__index = scope})
|
}, {__index = scope})
|
||||||
renderer.render(self.template, env, self.package)
|
renderer.render(self.template, env, self.package)
|
||||||
@ -94,14 +101,63 @@ function Node:render_children(renderer, scope)
|
|||||||
end
|
end
|
||||||
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()
|
function Node:resolve_depends()
|
||||||
local updated = false
|
local updated = self:resolve_node_depends()
|
||||||
|
|
||||||
for _, node in ipairs(self.children) do
|
for _, node in ipairs(self.children) do
|
||||||
updated = updated or node:resolve_depends()
|
updated = updated or node:resolve_depends()
|
||||||
end
|
end
|
||||||
|
|
||||||
return updated
|
return updated
|
||||||
end
|
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()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
function Node:handle()
|
function Node:handle()
|
||||||
for _, node in ipairs(self.children) do
|
for _, node in ipairs(self.children) do
|
||||||
node:handle()
|
node:handle()
|
||||||
@ -123,7 +179,6 @@ M.AbstractValue = AbstractValue
|
|||||||
|
|
||||||
function AbstractValue:__init__(...)
|
function AbstractValue:__init__(...)
|
||||||
Node.__init__(self, ...)
|
Node.__init__(self, ...)
|
||||||
self.deps = {}
|
|
||||||
|
|
||||||
self.default = nil
|
self.default = nil
|
||||||
self.size = nil
|
self.size = nil
|
||||||
@ -134,33 +189,6 @@ function AbstractValue:__init__(...)
|
|||||||
self.state = M.FORM_NODATA
|
self.state = M.FORM_NODATA
|
||||||
end
|
end
|
||||||
|
|
||||||
function AbstractValue:depends(field, value)
|
|
||||||
local deps
|
|
||||||
if instanceof(field, Node) then
|
|
||||||
deps = { [field] = value }
|
|
||||||
else
|
|
||||||
deps = field
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(self.deps, deps)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AbstractValue:deplist(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 AbstractValue:defaultvalue()
|
function AbstractValue:defaultvalue()
|
||||||
return self.default
|
return self.default
|
||||||
end
|
end
|
||||||
@ -214,24 +242,12 @@ function AbstractValue:parse(http)
|
|||||||
self.state = M.FORM_VALID
|
self.state = M.FORM_VALID
|
||||||
end
|
end
|
||||||
|
|
||||||
function AbstractValue:resolve_depends()
|
function AbstractValue:resolve_node_depends()
|
||||||
if self.state == M.FORM_NODATA or #self.deps == 0 then
|
if self.state == M.FORM_NODATA then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, d in ipairs(self.deps) do
|
return Node.resolve_node_depends(self)
|
||||||
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()
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function AbstractValue:validate()
|
function AbstractValue:validate()
|
||||||
|
Loading…
Reference in New Issue
Block a user