X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fcbi%2Fluasrc%2Fcbi.lua;h=9a32dd68d04ecfbfed3ebfa0b1d579d228a95807;hp=f7725c53488b49868c424167a6856387a92b0a13;hb=935f4a805a484a3325016493e87c82e6b0180fa8;hpb=15f4fa76d5c468e7def2d3c38d148945ce980030 diff --git a/libs/cbi/luasrc/cbi.lua b/libs/cbi/luasrc/cbi.lua index f7725c534..9a32dd68d 100644 --- a/libs/cbi/luasrc/cbi.lua +++ b/libs/cbi/luasrc/cbi.lua @@ -92,10 +92,10 @@ function Node._i18n(self, config, section, option, title, description) -- i18n loaded? if type(luci.i18n) == "table" then - local key = config:gsub("[^%w]+", "") + local key = config and config:gsub("[^%w]+", "") or "" if section then key = key .. "_" .. section:lower():gsub("[^%w]+", "") end - if option then key = key .. "_" .. option:lower():gsub("[^%w]+", "") end + if option then key = key .. "_" .. tostring(option):lower():gsub("[^%w]+", "") end self.title = title or luci.i18n.translate( key, option or section or config ) self.description = description or luci.i18n.translate( key .. "_desc", "" ) @@ -140,6 +140,10 @@ function Template.__init__(self, template) self.template = template end +function Template.render(self) + luci.template.render(self.template, {self=self}) +end + --[[ Map - A map describing a configuration file @@ -153,11 +157,20 @@ function Map.__init__(self, config, ...) self.config = config self.parsechain = {self.config} self.template = "cbi/map" - if not uci.load(self.config) then + if not uci.load_config(self.config) then error("Unable to read UCI data: " .. self.config) end end +function Map.render(self, ...) + if self.stateful then + uci.load_state(self.config) + else + uci.load_config(self.config) + end + Node.render(self, ...) +end + -- Chain foreign config function Map.chain(self, config) @@ -166,9 +179,16 @@ end -- Use optimized UCI writing function Map.parse(self, ...) + if self.stateful then + uci.load_state(self.config) + else + uci.load_config(self.config) + end + Node.parse(self, ...) + for i, config in ipairs(self.parsechain) do - uci.save(config) + uci.save_config(config) end if luci.http.formvalue("cbi.apply") then for i, config in ipairs(self.parsechain) do @@ -178,8 +198,7 @@ function Map.parse(self, ...) end -- Refresh data because commit changes section names - uci.unload(config) - uci.load(config) + uci.load_config(config) end -- Reparse sections @@ -236,10 +255,14 @@ function Map.get(self, section, option) end end --- UCI stateget -function Map.stateget(self, section, option) - return uci.get_statevalue(self.config, section, option) -end + +--[[ +Page - A simple node +]]-- + +Page = class(Node) +Page.__init__ = Node.__init__ +Page.parse = function() end --[[ @@ -256,11 +279,17 @@ function SimpleForm.__init__(self, config, title, description, data) end function SimpleForm.parse(self, ...) - Node.parse(self, 1, ...) + if luci.http.formvalue("cbi.submit") then + Node.parse(self, 1, ...) + end local valid = true - for i, v in ipairs(self.children) do - valid = valid and not v.tag_missing[1] and not v.tag_invalid[1] + for k, j in ipairs(self.children) do + for i, v in ipairs(j.children) do + valid = valid + and (not v.tag_missing or not v.tag_missing[1]) + and (not v.tag_invalid or not v.tag_invalid[1]) + end end local state = @@ -268,7 +297,7 @@ function SimpleForm.parse(self, ...) or valid and 1 or -1 - self.dorender = self:handle(state) + self.dorender = not self.handle or self:handle(state, self.data) ~= false end function SimpleForm.render(self, ...) @@ -277,11 +306,33 @@ function SimpleForm.render(self, ...) end end --- Creates a child section +function SimpleForm.section(self, class, ...) + if instanceof(class, AbstractSection) then + local obj = class(self, ...) + self:append(obj) + return obj + else + error("class must be a descendent of AbstractSection") + end +end + +-- Creates a child field function SimpleForm.field(self, class, ...) + local section + for k, v in ipairs(self.children) do + if instanceof(v, SimpleSection) then + section = v + break + end + end + if not section then + section = self:section(SimpleSection) + end + if instanceof(class, AbstractValue) then local obj = class(self, ...) - self:append(obj) + obj.track_missing = true + section:append(obj) return obj else error("class must be a descendent of AbstractValue") @@ -430,6 +481,54 @@ function AbstractSection.create(self, section) end +SimpleSection = class(AbstractSection) + +function SimpleSection.__init__(self, form, ...) + AbstractSection.__init__(self, form, nil, ...) + self.template = "cbi/nullsection" +end + + +Table = class(AbstractSection) + +function Table.__init__(self, form, data, ...) + local datasource = {} + datasource.config = "table" + self.data = data + + function datasource.get(self, section, option) + return data[section] and data[section][option] + end + + function datasource.del(...) + return true + end + + AbstractSection.__init__(self, datasource, "table", ...) + self.template = "cbi/tblsection" + self.rowcolors = true + self.anonymous = true +end + +function Table.parse(self) + for i, k in ipairs(self:cfgsections()) do + if luci.http.formvalue("cbi.submit") then + Node.parse(self, k) + end + end +end + +function Table.cfgsections(self) + local sections = {} + + for i, v in luci.util.kspairs(self.data) do + table.insert(sections, i) + end + + return sections +end + + --[[ NamedSection - A fixed configuration section defined by its name @@ -608,18 +707,32 @@ function AbstractValue.__init__(self, map, option, ...) self.config = map.config self.tag_invalid = {} self.tag_missing = {} + self.tag_error = {} self.deps = {} + self.track_missing = false self.rmempty = false self.default = nil self.size = nil self.optional = false - self.stateful = false end -- Add a dependencie to another section field function AbstractValue.depends(self, field, value) - table.insert(self.deps, {field=field, value=value}) + local deps + if type(field) == "string" then + deps = {} + deps[field] = value + else + deps = field + end + + table.insert(self.deps, {deps=deps, add=""}) +end + +-- Generates the unique CBID +function AbstractValue.cbid(self, section) + return "cbid."..self.map.config.."."..section.."."..self.option end -- Return whether this object should be created @@ -630,8 +743,7 @@ end -- Returns the formvalue for this object function AbstractValue.formvalue(self, section) - local key = "cbid."..self.map.config.."."..section.."."..self.option - return luci.http.formvalue(key) + return luci.http.formvalue(self:cbid(section)) end function AbstractValue.additional(self, value) @@ -647,18 +759,18 @@ function AbstractValue.parse(self, section) local cvalue = self:cfgvalue(section) if fvalue and fvalue ~= "" then -- If we have a form value, write it to UCI - fvalue = self:transform(self:validate(fvalue)) + fvalue = self:transform(self:validate(fvalue, section)) if not fvalue then self.tag_invalid[section] = true end - if fvalue and not (fvalue == self:cfgvalue(section)) then + if fvalue and not (fvalue == cvalue) then self:write(section, fvalue) end else -- Unset the UCI or error if self.rmempty or self.optional then self:remove(section) - elseif not fvalue or fvalue ~= cvalue then - --self.tag_missing[section] = true + elseif self.track_missing and (not fvalue or fvalue ~= cvalue) then + self.tag_missing[section] = true end end end @@ -668,18 +780,16 @@ function AbstractValue.render(self, s, scope) if not self.optional or self:cfgvalue(s) or self:formcreated(s) then scope = scope or {} scope.section = s - scope.cbid = "cbid." .. self.config .. - "." .. s .. - "." .. self.option + scope.cbid = self:cbid(s) scope.ifattr = function(cond,key,val) if cond then return string.format( ' %s="%s"', tostring(key), - tostring( val + luci.util.pcdata(tostring( val or scope[key] or (type(self[key]) ~= "function" and self[key]) - or "" ) + or "" )) ) else return '' @@ -696,9 +806,7 @@ end -- Return the UCI value of this object function AbstractValue.cfgvalue(self, section) - return self.stateful - and self.map:stateget(section, self.option) - or self.map:get(section, self.option) + return self.map:get(section, self.option) end -- Validate the form value @@ -806,10 +914,14 @@ function ListValue.__init__(self, ...) self.widget = "select" end -function ListValue.value(self, key, val) +function ListValue.value(self, key, val, ...) val = val or key table.insert(self.keylist, tostring(key)) table.insert(self.vallist, tostring(val)) + + for i, deps in ipairs({...}) do + table.insert(self.deps, {add = "-"..key, deps=deps}) + end end function ListValue.validate(self, val) @@ -887,3 +999,15 @@ function TextValue.__init__(self, ...) AbstractValue.__init__(self, ...) self.template = "cbi/tvalue" end + +--[[ +Button +]]-- +Button = class(AbstractValue) + +function Button.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/button" + self.inputstyle = nil + self.rmempty = true +end \ No newline at end of file