* 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:
Steven Barth 2008-03-21 19:30:53 +00:00
parent 6e0df95e27
commit c8426cfa3c
10 changed files with 157 additions and 61 deletions

View file

@ -25,22 +25,50 @@ limitations under the License.
]]--
module("ffluci.cbi", package.seeall)
require("ffluci.template")
require("ffluci.util")
require("ffluci.http")
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
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 = class()
function Node.__init__(self, title, description)
self.children = {}
self.title = title
self.description = description
self.title = title or ""
self.description = description or ""
self.template = "cbi/node"
end
@ -55,7 +83,7 @@ function Node.parse(self)
end
function Node.render(self)
ffluci.template.render(self.template)
ffluci.template.render(self.template, {self=self})
end
@ -83,7 +111,7 @@ function Map.section(self, class, ...)
end
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
end
@ -173,7 +201,7 @@ function AbstractValue.formvalue(self)
end
function AbstractValue.ucivalue(self)
return self.map.read()[self.section][self.option]
return self.map:read()[self.section][self.option]
end
function AbstractValue.validate(self, value)

View file

@ -1,2 +1 @@
module(..., package.seeall)
dispatcher = require("ffluci.dispatcher").simpleview
module(..., package.seeall)

View file

@ -95,6 +95,7 @@ function dispatch(req)
return error404()
else
module.request = request
module.dispatcher = module.dispatcher or dynamic
setfenv(module.dispatcher, module)
return module.dispatcher(request)
end
@ -139,18 +140,9 @@ function httpdispatch()
dispatch({category=cat, module=mod, action=act})
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
-- Dispatchers --
-- The Action Dispatcher searches the module for any function called
-- action_"request.action" and calls it
@ -165,4 +157,68 @@ function action(request)
else
disp.error404()
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

View file

@ -124,12 +124,13 @@ function compile(template)
end
-- Oldstyle render shortcut
function render(name, ...)
function render(name, scope, ...)
scope = scope or getfenv(2)
local s, t = pcall(Template, name)
if not s then
error("Unable to load template: " .. name)
else
t:render(...)
t:render(scope, ...)
end
end
@ -208,6 +209,7 @@ function Template.render(self, scope)
local oldfenv = getfenv(self.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, self.viewns)

View file

@ -114,7 +114,6 @@ end
function extfenv(f, key, obj)
local scope = getfenv(f)
scope[key] = obj
setfenv(f, scope)
end
@ -131,13 +130,20 @@ function instanceof(object, class)
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"
function updfenv(f, extscope)
local scope = getfenv(f)
for k, v in pairs(extscope) do
scope[k] = v
end
setfenv(f, scope)
end

View file

@ -1,11 +1,11 @@
<div class="cbi-lvalue">
<div class="cbi-lvalue-title"><%=self.title%></div>
<div class="cbi-lvalue-field">
<select name="<%=self.config.."."..self.section.."."..self.option%>">
<%for k, v in self.list do%>
<option value="<%=k%>"><%=v%></option>
<div class="cbi-lvalue">
<div class="cbi-lvalue-title"><%=self.title%></div>
<div class="cbi-lvalue-field">
<select name="cbid.<%=self.config.."."..self.section.."."..self.option%>">
<%for k, v in pairs(self.list) do%>
<option value="<%=k%>"><%=v%></option>
<% end %>
</select>
</div>
<div class="cbi-value-description"><%=self.description%></div>
</div>
</select>
</div>
<div class="cbi-value-description"><%=self.description%></div>
</div>

View file

@ -1,7 +1,10 @@
<div class="cbi-map" id="cbi-<%=self.config%>">
<form method="post" action="<%=os.getenv("REQUEST_URI")%>">
<h1><%=self.title%></h1>
<div class="cbi-map-descr"><%=self.description%></div>
<div class="cbi-map" id="cbi-<%=self.config%>">
<form method="post" action="<%=os.getenv("REQUEST_URI")%>">
<h1><%=self.title%></h1>
<div class="cbi-map-descr"><%=self.description%></div>
<br />
<% for k, node in ipairs(self.children) do node:render() end %>
</form>
</div>
<br />
<input type="submit" /> <input type="reset" />
</form>
</div>

View file

@ -1,5 +1,7 @@
<div class="cbi-nsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>-<%=self.section%>">
<h2><%=self.title%></h2>
<div class="cbi-nsection-descr"><%=self.description%></div>
<div class="cbi-nsection" id="cbi-<%=self.config%>-<%=self.section%>">
<h2><%=self.title%></h2>
<div class="cbi-nsection-descr"><%=self.description%></div>
<div class="cbi-nsection-options">
<% for k, node in ipairs(self.children) do node:render() end %>
</div>
</div>
</div>

View file

@ -2,20 +2,20 @@
local allsections = self.map:read()
local sections = {}
for k, v in pairs(allsections) do
if v[".type"] == sectiontype then
if v[".type"] == self.sectiontype then
sections[k] = v
end
end
%>
<div class="cbi-tsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<h2><%=self.title%></h2>
<div class="cbi-tsection-descr"><%=self.description%></div>
<div class="cbi-tsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<h2><%=self.title%></h2>
<div class="cbi-tsection-descr"><%=self.description%></div>
<% for k, v in pairs(sections) do %>
<div class="cbi-tsection-node" id="cbi-<%=self.config%>-<%=k%>">
<% for k, node in ipairs(self.children) do
<div class="cbi-tsection-node" id="cbi-<%=self.config%>-<%=k%>">
<% for i, node in ipairs(self.children) do
node.section = k
node:render(k)
node:render()
end %>
</div>
</div>
<% end %>
</div>
</div>

View file

@ -1,7 +1,7 @@
<div class="cbi-value">
<div class="cbi-value-title"><%=self.title%></div>
<div class="cbi-value-field">
<input type="text" name="<%=self.config.."."..self.section.."."..self.option%>" value="<%=self:ucivalue()%>" />
</div>
<div class="cbi-value-description"><%=self.description%></div>
</div>
<div class="cbi-value">
<div class="cbi-value-title"><%=self.title%></div>
<div class="cbi-value-field">
<input type="text" name="cbid.<%=self.config.."."..self.section.."."..self.option%>" value="<%=(self:ucivalue() or "")%>" />
</div>
<div class="cbi-value-description"><%=self.description%></div>
</div>