libs/cbi: Major Improvements
authorSteven Barth <steven@midlink.org>
Sat, 9 Aug 2008 14:14:04 +0000 (14:14 +0000)
committerSteven Barth <steven@midlink.org>
Sat, 9 Aug 2008 14:14:04 +0000 (14:14 +0000)
Added initial support for non-UCI-based forms (luci.cbi.SimpleForm)
Minor API improvements
Now correctly tagging "empty mandatory field" errors

i18n/english/luasrc/i18n/cbi.en.lua
i18n/english/luasrc/i18n/default.en.lua
i18n/german/luasrc/i18n/cbi.de.lua
i18n/german/luasrc/i18n/default.de.lua
libs/cbi/luasrc/cbi.lua
libs/cbi/luasrc/view/cbi/full_valuefooter.htm
libs/cbi/luasrc/view/cbi/simpleform.htm [new file with mode: 0644]
libs/web/luasrc/dispatcher.lua

index 012d7c5f6b0b16914b0dc61ca4c52d4e65996c62..9c84a8950f67b0cdfd0dd771e6a6d2723aaa17db 100644 (file)
@@ -1,6 +1,7 @@
 cbi_add = "Add entry"
 cbi_del = "Remove entry"
 cbi_invalid = "Error: Invalid input value"
+cbi_missing = "Error: This field is mandatory"
 cbi_addopt = "-- Additional Field --"
 cbi_optional = " (optional)"
 cbi_sectempty = "This section contains no values yet"
index 8f472d9c1823b80bf235a106344269a9c4752089..89b7c6321bcfb6532e6937dcbdb2db76e6047f8a 100644 (file)
@@ -89,6 +89,7 @@ settings = "Settings"
 start = "Start"
 static = "static"
 statistics = "Statistics"
+submit = "Submit"
 syslog = "System Log"
 system = "System"
 
index f2ed5ecd245af5bbededc76a07de900c450e4b0c..8b3265061a7c81bee4a709f993381ffd4e705be9 100644 (file)
@@ -1,6 +1,7 @@
 cbi_add = "Eintrag hinzufügen"
 cbi_del = "Eintrag entfernen"
-cbi_invalid = "Error: Ungültige Eingabe"
+cbi_invalid = "Fehler: Ungültige Eingabe"
+cbi_missing = "Fehler: Dieses Feld muss ausgefüllt werden"
 cbi_addopt = "-- Zusätzliches Feld --"
 cbi_sectempty = "Diese Sektion enthält noch keine Einträge"
 cbi_manual = "-- benutzerdefiniert --"
index 554975c6bb9c787ad5f2061f48909db93b68c416..08ef89e6945efcac31e1d0c063075d66e4435d9b 100644 (file)
@@ -90,6 +90,7 @@ settings = "Einstellungen"
 start = "Start"
 static = "statisch"
 statistics = "Statistiken"
+submit = "Absenden"
 syslog = "Systemprotokoll"
 system = "System"
 
index 4b4bf39059836a40c5be62b3375b7eab2ca6bca4..0ec2ff815de7095fe94c56fefc5ac6ff9498d62c 100644 (file)
@@ -35,6 +35,9 @@ local uci        = luci.model.uci
 local class      = luci.util.class
 local instanceof = luci.util.instanceof
 
+FORM_NODATA  =  0
+FORM_VALID   =  1
+FORM_INVALID = -1
 
 -- Loads a CBI map from given file, creating an environment and returns it
 function load(cbimap, ...)
@@ -61,7 +64,7 @@ function load(cbimap, ...)
        local maps = {func()}
 
        for i, map in ipairs(maps) do
-               if not instanceof(map, Map) then
+               if not instanceof(map, Node) then
                        error("CBI map returns no valid map object!")
                        return nil
                end
@@ -231,6 +234,68 @@ function Map.get(self, section, option)
 end
 
 
+--[[
+SimpleForm - A Simple non-UCI form
+]]--
+SimpleForm = class(Node)
+
+function SimpleForm.__init__(self, config, title, description, data)
+       Node.__init__(self, title, description)
+       self.config = config
+       self.data = data or {}
+       self.template = "cbi/simpleform"
+       self.dorender = true
+end
+
+function SimpleForm.parse(self, ...)
+       Node.parse(self, 1, ...)
+               
+       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]
+       end
+       
+       local state = 
+               not luci.http.formvalue("cbi.submit") and 0
+               or valid and 1
+               or -1
+
+       self.dorender = self:handle(state)
+end
+
+function SimpleForm.render(self, ...)
+       if self.dorender then
+               Node.render(self, ...)
+       end
+end
+
+-- Creates a child section
+function SimpleForm.field(self, class, ...)
+       if instanceof(class, AbstractValue) then
+               local obj  = class(self, ...)
+               self:append(obj)
+               return obj
+       else
+               error("class must be a descendent of AbstractValue")
+       end
+end
+
+function SimpleForm.set(self, section, option, value)
+       self.data[option] = value
+end
+
+
+function SimpleForm.del(self, section, option)
+       self.data[option] = nil
+end
+
+
+function SimpleForm.get(self, section, option)
+       return self.data[option]
+end
+
+
+
 --[[
 AbstractSection
 ]]--
@@ -534,12 +599,13 @@ function AbstractValue.__init__(self, map, option, ...)
        self.map    = map
        self.config = map.config
        self.tag_invalid = {}
+       self.tag_missing = {}
        self.deps = {}
 
-       self.rmempty  = false
-       self.default  = nil
-       self.size     = nil
-       self.optional = false
+       self.rmempty   = false
+       self.default   = nil
+       self.size      = nil
+       self.optional  = false
 end
 
 -- Add a dependencie to another section field
@@ -559,11 +625,20 @@ function AbstractValue.formvalue(self, section)
        return luci.http.formvalue(key)
 end
 
+function AbstractValue.additional(self, value)
+       self.optional = value
+end
+
+function AbstractValue.mandatory(self, value)
+       self.rmempty = not value
+end
+
 function AbstractValue.parse(self, section)
        local fvalue = self:formvalue(section)
+       local cvalue = self:cfgvalue(section)
 
        if fvalue and fvalue ~= "" then -- If we have a form value, write it to UCI
-               fvalue = self:validate(fvalue)
+               fvalue = self:transform(self:validate(fvalue))
                if not fvalue then
                        self.tag_invalid[section] = true
                end
@@ -573,6 +648,8 @@ function AbstractValue.parse(self, section)
        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
                end
        end
 end
@@ -618,6 +695,9 @@ function AbstractValue.validate(self, value)
        return value
 end
 
+AbstractValue.transform = AbstractValue.validate
+
+
 -- Write to UCI
 function AbstractValue.write(self, section, value)
        return self.map:set(section, self.option, value)
index 8924beccdf3b90264ccfd2f12552cff17a7b3341..a7b56e29445784573a042e7e361315abf8f9962e 100644 (file)
@@ -21,6 +21,9 @@ $Id$
        <% if self.tag_invalid[section] then -%>
                <div class="cbi-error"><%:cbi_invalid%></div>
        <%- end %>
+       <% if self.tag_missing[section] then -%>
+               <div class="cbi-error"><%:cbi_missing%></div>
+       <%- end %>
 </div>
 
 <% if #self.deps > 0 then -%>
diff --git a/libs/cbi/luasrc/view/cbi/simpleform.htm b/libs/cbi/luasrc/view/cbi/simpleform.htm
new file mode 100644 (file)
index 0000000..38df61b
--- /dev/null
@@ -0,0 +1,46 @@
+<%#
+LuCI - Lua Configuration Interface
+Copyright 2008 Steven Barth <steven@midlink.org>
+Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+$Id$
+
+-%>
+
+<form method="post" action="<%=luci.http.getenv("REQUEST_URI")%>">
+       <div>
+               <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+               <input type="hidden" name="cbi.submit" value="1" />
+               <input type="submit" value="<%:save%>" class="hidden" />
+       </div>
+       <div class="cbi-map" id="cbi-<%=self.config%>">
+               <h1><%=self.title%></h1>
+               <div class="cbi-map-descr"><%=self.description%></div>
+               <fieldset class="cbi-section">
+                       <div class="cbi-section-node">
+                               <% self:render_children(1, scope or {}) %>
+                       </div>
+                       <br />
+               </fieldset>
+               <br />
+       </div>
+       <div>
+<%- if self.submit ~= false then %>
+               <input type="submit" value="
+       <%- if not self.submit then -%><%-:submit-%><%-else-%><%=self.submit%><%end%>
+       " />
+<% end %>
+<%- if self.reset ~= false then %>
+               <input type="reset" value="
+       <%- if not self.reset then -%><%-:reset-%><%-else-%><%=self.reset%><%end%>
+       " />
+<% end %>
+               <script type="text/javascript">cbi_d_init();</script>
+       </div>
+</form>
index 9ba74c49c91e09ed25dc101d007c73918c3a1678..d9917c2a87f94c1d825925fa8999b3d6e9b25bb1 100644 (file)
@@ -461,3 +461,32 @@ function cbi(model)
                luci.template.render("cbi/footer")
        end
 end
+
+--- Create a CBI form model dispatching target.
+-- @param      model   CBI form model tpo be rendered
+function form(model)
+       require("luci.cbi")
+       require("luci.template")
+
+       return function(...)
+               local stat, maps = luci.util.copcall(luci.cbi.load, model, ...)
+               if not stat then
+                       error500(maps)
+                       return true
+               end
+
+               for i, res in ipairs(maps) do
+                       local stat, err = luci.util.copcall(res.parse, res)
+                       if not stat then
+                               error500(err)
+                               return true
+                       end
+               end
+
+               luci.template.render("header")
+               for i, res in ipairs(maps) do
+                       res:render()
+               end
+               luci.template.render("footer")
+       end
+end