* ffluci.cbi: updates
* ffluci.template: fixed a bug where different template scopes were not separated correctly * Added ffluci.dispatcher.cbi and ffluci.dispatcher.dynamic
This commit is contained in:
parent
6e0df95e27
commit
c8426cfa3c
10 changed files with 157 additions and 61 deletions
|
@ -25,22 +25,50 @@ limitations under the License.
|
||||||
|
|
||||||
]]--
|
]]--
|
||||||
module("ffluci.cbi", package.seeall)
|
module("ffluci.cbi", package.seeall)
|
||||||
|
|
||||||
require("ffluci.template")
|
require("ffluci.template")
|
||||||
require("ffluci.util")
|
require("ffluci.util")
|
||||||
require("ffluci.http")
|
require("ffluci.http")
|
||||||
require("ffluci.model.uci")
|
require("ffluci.model.uci")
|
||||||
local Template = ffluci.template.Template
|
|
||||||
local class = ffluci.util.class
|
local Template = ffluci.template.Template
|
||||||
|
local class = ffluci.util.class
|
||||||
local instanceof = ffluci.util.instanceof
|
local instanceof = ffluci.util.instanceof
|
||||||
|
|
||||||
|
|
||||||
|
function load(cbimap)
|
||||||
|
require("ffluci.fs")
|
||||||
|
require("ffluci.i18n")
|
||||||
|
|
||||||
|
local cbidir = ffluci.fs.dirname(ffluci.util.__file__()) .. "model/cbi/"
|
||||||
|
local func = loadfile(cbidir..cbimap..".lua")
|
||||||
|
|
||||||
|
if not func then
|
||||||
|
error("Unable to load CBI map: " .. cbimap)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
ffluci.util.resfenv(func)
|
||||||
|
ffluci.util.updfenv(func, ffluci.cbi)
|
||||||
|
ffluci.util.extfenv(func, "translate", ffluci.i18n.translate)
|
||||||
|
|
||||||
|
local map = func()
|
||||||
|
|
||||||
|
if not instanceof(map, Map) then
|
||||||
|
error("CBI map returns no valid map object!")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return map
|
||||||
|
end
|
||||||
|
|
||||||
-- Node pseudo abstract class
|
-- Node pseudo abstract class
|
||||||
Node = class()
|
Node = class()
|
||||||
|
|
||||||
function Node.__init__(self, title, description)
|
function Node.__init__(self, title, description)
|
||||||
self.children = {}
|
self.children = {}
|
||||||
self.title = title
|
self.title = title or ""
|
||||||
self.description = description
|
self.description = description or ""
|
||||||
self.template = "cbi/node"
|
self.template = "cbi/node"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -55,7 +83,7 @@ function Node.parse(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Node.render(self)
|
function Node.render(self)
|
||||||
ffluci.template.render(self.template)
|
ffluci.template.render(self.template, {self=self})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,7 +111,7 @@ function Map.section(self, class, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Map.read(self)
|
function Map.read(self)
|
||||||
self.ucidata = self.ucidata or ffluci.model.uci.show(self.config)
|
self.ucidata = self.ucidata or ffluci.model.uci.show(self.config)[self.config]
|
||||||
return self.ucidata
|
return self.ucidata
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -173,7 +201,7 @@ function AbstractValue.formvalue(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function AbstractValue.ucivalue(self)
|
function AbstractValue.ucivalue(self)
|
||||||
return self.map.read()[self.section][self.option]
|
return self.map:read()[self.section][self.option]
|
||||||
end
|
end
|
||||||
|
|
||||||
function AbstractValue.validate(self, value)
|
function AbstractValue.validate(self, value)
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
module(..., package.seeall)
|
module(..., package.seeall)
|
||||||
dispatcher = require("ffluci.dispatcher").simpleview
|
|
|
@ -95,6 +95,7 @@ function dispatch(req)
|
||||||
return error404()
|
return error404()
|
||||||
else
|
else
|
||||||
module.request = request
|
module.request = request
|
||||||
|
module.dispatcher = module.dispatcher or dynamic
|
||||||
setfenv(module.dispatcher, module)
|
setfenv(module.dispatcher, module)
|
||||||
return module.dispatcher(request)
|
return module.dispatcher(request)
|
||||||
end
|
end
|
||||||
|
@ -139,18 +140,9 @@ function httpdispatch()
|
||||||
dispatch({category=cat, module=mod, action=act})
|
dispatch({category=cat, module=mod, action=act})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The Simple View Dispatcher directly renders the template
|
|
||||||
-- which is placed in ffluci/views/"request.module"/"request.action"
|
-- Dispatchers --
|
||||||
function simpleview(request)
|
|
||||||
local i18n = require("ffluci.i18n")
|
|
||||||
local tmpl = require("ffluci.template")
|
|
||||||
local disp = require("ffluci.dispatcher")
|
|
||||||
|
|
||||||
i18n.loadc(request.module)
|
|
||||||
if not pcall(tmpl.render, request.module .. "/" .. request.action) then
|
|
||||||
disp.error404()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- The Action Dispatcher searches the module for any function called
|
-- The Action Dispatcher searches the module for any function called
|
||||||
-- action_"request.action" and calls it
|
-- action_"request.action" and calls it
|
||||||
|
@ -165,4 +157,68 @@ function action(request)
|
||||||
else
|
else
|
||||||
disp.error404()
|
disp.error404()
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The CBI dispatcher directly parses and renders the CBI map which is
|
||||||
|
-- placed in ffluci/modles/cbi/"request.module"/"request.action"
|
||||||
|
function cbi(request)
|
||||||
|
local i18n = require("ffluci.i18n")
|
||||||
|
local disp = require("ffluci.dispatcher")
|
||||||
|
local tmpl = require("ffluci.template")
|
||||||
|
local cbi = require("ffluci.cbi")
|
||||||
|
|
||||||
|
i18n.loadc(request.module)
|
||||||
|
|
||||||
|
stat, map = pcall(cbi.load, request.module.."/"..request.action)
|
||||||
|
if stat then
|
||||||
|
tmpl.render("header")
|
||||||
|
map:render()
|
||||||
|
tmpl.render("footer")
|
||||||
|
else
|
||||||
|
disp.error404()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The dynamic dispatchers combines the action, simpleview and cbi dispatchers
|
||||||
|
-- in one dispatcher. It tries to lookup the request in this order.
|
||||||
|
function dynamic(request)
|
||||||
|
local i18n = require("ffluci.i18n")
|
||||||
|
local disp = require("ffluci.dispatcher")
|
||||||
|
local tmpl = require("ffluci.template")
|
||||||
|
local cbi = require("ffluci.cbi")
|
||||||
|
|
||||||
|
i18n.loadc(request.module)
|
||||||
|
|
||||||
|
local action = getfenv()["action_" .. request.action:gsub("-", "_")]
|
||||||
|
if action then
|
||||||
|
action()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if pcall(tmpl.render, request.module .. "/" .. request.action) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
stat, map = pcall(cbi.load, request.module.."/"..request.action)
|
||||||
|
if stat then
|
||||||
|
tmpl.render("header")
|
||||||
|
map:render()
|
||||||
|
tmpl.render("footer")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
disp.error404()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The Simple View Dispatcher directly renders the template
|
||||||
|
-- which is placed in ffluci/views/"request.module"/"request.action"
|
||||||
|
function simpleview(request)
|
||||||
|
local i18n = require("ffluci.i18n")
|
||||||
|
local tmpl = require("ffluci.template")
|
||||||
|
local disp = require("ffluci.dispatcher")
|
||||||
|
|
||||||
|
i18n.loadc(request.module)
|
||||||
|
if not pcall(tmpl.render, request.module .. "/" .. request.action) then
|
||||||
|
disp.error404()
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -124,12 +124,13 @@ function compile(template)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Oldstyle render shortcut
|
-- Oldstyle render shortcut
|
||||||
function render(name, ...)
|
function render(name, scope, ...)
|
||||||
|
scope = scope or getfenv(2)
|
||||||
local s, t = pcall(Template, name)
|
local s, t = pcall(Template, name)
|
||||||
if not s then
|
if not s then
|
||||||
error("Unable to load template: " .. name)
|
error("Unable to load template: " .. name)
|
||||||
else
|
else
|
||||||
t:render(...)
|
t:render(scope, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -208,6 +209,7 @@ function Template.render(self, scope)
|
||||||
local oldfenv = getfenv(self.template)
|
local oldfenv = getfenv(self.template)
|
||||||
|
|
||||||
-- Put our predefined objects in the scope of the template
|
-- Put our predefined objects in the scope of the template
|
||||||
|
ffluci.util.resfenv(self.template)
|
||||||
ffluci.util.updfenv(self.template, scope)
|
ffluci.util.updfenv(self.template, scope)
|
||||||
ffluci.util.updfenv(self.template, self.viewns)
|
ffluci.util.updfenv(self.template, self.viewns)
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,6 @@ end
|
||||||
function extfenv(f, key, obj)
|
function extfenv(f, key, obj)
|
||||||
local scope = getfenv(f)
|
local scope = getfenv(f)
|
||||||
scope[key] = obj
|
scope[key] = obj
|
||||||
setfenv(f, scope)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,13 +130,20 @@ function instanceof(object, class)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Resets the scope of f doing a shallow copy of its scope into a new table
|
||||||
|
function resfenv(f)
|
||||||
|
local scope = getfenv(f)
|
||||||
|
setfenv(f, {})
|
||||||
|
updfenv(f, scope)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Updates the scope of f with "extscope"
|
-- Updates the scope of f with "extscope"
|
||||||
function updfenv(f, extscope)
|
function updfenv(f, extscope)
|
||||||
local scope = getfenv(f)
|
local scope = getfenv(f)
|
||||||
for k, v in pairs(extscope) do
|
for k, v in pairs(extscope) do
|
||||||
scope[k] = v
|
scope[k] = v
|
||||||
end
|
end
|
||||||
setfenv(f, scope)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<div class="cbi-lvalue">
|
<div class="cbi-lvalue">
|
||||||
<div class="cbi-lvalue-title"><%=self.title%></div>
|
<div class="cbi-lvalue-title"><%=self.title%></div>
|
||||||
<div class="cbi-lvalue-field">
|
<div class="cbi-lvalue-field">
|
||||||
<select name="<%=self.config.."."..self.section.."."..self.option%>">
|
<select name="cbid.<%=self.config.."."..self.section.."."..self.option%>">
|
||||||
<%for k, v in self.list do%>
|
<%for k, v in pairs(self.list) do%>
|
||||||
<option value="<%=k%>"><%=v%></option>
|
<option value="<%=k%>"><%=v%></option>
|
||||||
<% end %>
|
<% end %>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="cbi-value-description"><%=self.description%></div>
|
<div class="cbi-value-description"><%=self.description%></div>
|
||||||
</div>
|
</div>
|
|
@ -1,7 +1,10 @@
|
||||||
<div class="cbi-map" id="cbi-<%=self.config%>">
|
<div class="cbi-map" id="cbi-<%=self.config%>">
|
||||||
<form method="post" action="<%=os.getenv("REQUEST_URI")%>">
|
<form method="post" action="<%=os.getenv("REQUEST_URI")%>">
|
||||||
<h1><%=self.title%></h1>
|
<h1><%=self.title%></h1>
|
||||||
<div class="cbi-map-descr"><%=self.description%></div>
|
<div class="cbi-map-descr"><%=self.description%></div>
|
||||||
|
<br />
|
||||||
<% for k, node in ipairs(self.children) do node:render() end %>
|
<% for k, node in ipairs(self.children) do node:render() end %>
|
||||||
</form>
|
<br />
|
||||||
</div>
|
<input type="submit" /> <input type="reset" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<div class="cbi-nsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>-<%=self.section%>">
|
<div class="cbi-nsection" id="cbi-<%=self.config%>-<%=self.section%>">
|
||||||
<h2><%=self.title%></h2>
|
<h2><%=self.title%></h2>
|
||||||
<div class="cbi-nsection-descr"><%=self.description%></div>
|
<div class="cbi-nsection-descr"><%=self.description%></div>
|
||||||
|
<div class="cbi-nsection-options">
|
||||||
<% for k, node in ipairs(self.children) do node:render() end %>
|
<% for k, node in ipairs(self.children) do node:render() end %>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -2,20 +2,20 @@
|
||||||
local allsections = self.map:read()
|
local allsections = self.map:read()
|
||||||
local sections = {}
|
local sections = {}
|
||||||
for k, v in pairs(allsections) do
|
for k, v in pairs(allsections) do
|
||||||
if v[".type"] == sectiontype then
|
if v[".type"] == self.sectiontype then
|
||||||
sections[k] = v
|
sections[k] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
%>
|
%>
|
||||||
<div class="cbi-tsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
|
<div class="cbi-tsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
|
||||||
<h2><%=self.title%></h2>
|
<h2><%=self.title%></h2>
|
||||||
<div class="cbi-tsection-descr"><%=self.description%></div>
|
<div class="cbi-tsection-descr"><%=self.description%></div>
|
||||||
<% for k, v in pairs(sections) do %>
|
<% for k, v in pairs(sections) do %>
|
||||||
<div class="cbi-tsection-node" id="cbi-<%=self.config%>-<%=k%>">
|
<div class="cbi-tsection-node" id="cbi-<%=self.config%>-<%=k%>">
|
||||||
<% for k, node in ipairs(self.children) do
|
<% for i, node in ipairs(self.children) do
|
||||||
node.section = k
|
node.section = k
|
||||||
node:render(k)
|
node:render()
|
||||||
end %>
|
end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="cbi-value">
|
<div class="cbi-value">
|
||||||
<div class="cbi-value-title"><%=self.title%></div>
|
<div class="cbi-value-title"><%=self.title%></div>
|
||||||
<div class="cbi-value-field">
|
<div class="cbi-value-field">
|
||||||
<input type="text" name="<%=self.config.."."..self.section.."."..self.option%>" value="<%=self:ucivalue()%>" />
|
<input type="text" name="cbid.<%=self.config.."."..self.section.."."..self.option%>" value="<%=(self:ucivalue() or "")%>" />
|
||||||
</div>
|
</div>
|
||||||
<div class="cbi-value-description"><%=self.description%></div>
|
<div class="cbi-value-description"><%=self.description%></div>
|
||||||
</div>
|
</div>
|
Loading…
Reference in a new issue