From: Steven Barth Date: Thu, 27 Mar 2008 23:14:01 +0000 (+0000) Subject: * Major CBI improvements X-Git-Tag: 0.8.0~1194 X-Git-Url: http://git.openwrt.org/?p=project%2Fluci.git;a=commitdiff_plain;h=077db659bbcb7cee6bbc4c4dbaed9776261190a0 * Major CBI improvements --- diff --git a/Makefile b/Makefile index bc765c9682..2e986d8cbc 100644 --- a/Makefile +++ b/Makefile @@ -20,18 +20,11 @@ all: compile dist-compile: compile dist dist-source: source dist -examples-compile: compile examples -examples-source: source examples - - dist: cp src/ffluci/controller/* dist/ffluci/controller/ -R cp src/ffluci/i18n/* dist/ffluci/i18n/ cp src/ffluci/view/* dist/ffluci/view/ -R cp src/ffluci/model/cbi/* dist/ffluci/model/cbi/ -R - -examples: - cp examples/* dist/ -R compile: mkdir -p $(DIRECTORIES) diff --git a/contrib/ffluci.uci b/contrib/ffluci.uci index ecd72f6ed3..c887b1b33e 100644 --- a/contrib/ffluci.uci +++ b/contrib/ffluci.uci @@ -4,13 +4,13 @@ config core main config public contact - option nickname - - option name - - option mail - - option phone - - option location - - option geo - - option note - + option nickname + option name + option mail + option phone + option location + option geo + option note config event uci_oncommit diff --git a/contrib/media/cascade.css b/contrib/media/cascade.css index b0131dc581..55d6f76bd1 100644 --- a/contrib/media/cascade.css +++ b/contrib/media/cascade.css @@ -179,27 +179,31 @@ code { margin-top: 1em; } -.cbi-section-create { - margin-bottom: 3em; +.cbi-section-remove { + text-align: right; } .cbi-value-title { line-height: 1.75em; + width: 15em; + font-weight: bold; } .cbi-value-field { - margin-left: 10em; - text-align: center; + text-align: left; line-height: 1.75em; } -.cbi-value-field input, .cbi-value-field select, .cbi-optionals select, .cbi-optionals input { +.cbi-value-field input, .cbi-value-field select, +.cbi-optionals select, .cbi-optionals input, +.cbi-section-remove input, .cbi-section-create input { font-size: 0.8em; } .cbi-value-description { font-style: italic; font-size: 0.8em; + margin-bottom: 0.5em; } .cbi-form-separator { @@ -211,6 +215,7 @@ code { background: #f7f7f7; border: 1px solid #d7d7d7; overflow: auto; + margn-bottom: 0%; } .cbi-section-node h3 { @@ -220,10 +225,12 @@ code { .cbi-error { color: red; font-weight: bold; + font-size: 0.8em; + margin-bottom: 0.75em; } .cbi-optionals { - margin-top: 2em; + margin-top: 1em; } .cbi-optionals option { diff --git a/contrib/media/cbi.js b/contrib/media/cbi.js new file mode 100644 index 0000000000..f9e463bca1 --- /dev/null +++ b/contrib/media/cbi.js @@ -0,0 +1,36 @@ +var cbi_d = {}; + +function cbi_d_add(field, target, value) { + if (!cbi_d[target]) { + cbi_d[target] = {}; + } + if (!cbi_d[target][value]) { + cbi_d[target][value] = []; + } + cbi_d[target][value].push(field); +} + +function cbi_d_update(target) { + if (!cbi_d[target]) { + return; + } + + for (var x in cbi_d[target]) { + for (var i=0; i value pairs +function TypedSection.depends(self, option, value) + table.insert(self.deps, {option=option, value=value}) +end + +-- Excludes several sections by name +function TypedSection.exclude(self, field) + self.excludes[field] = true +end + function TypedSection.parse(self) if self.addremove then -- Create @@ -368,10 +389,17 @@ function TypedSection.parse(self) end else if name then - name = ffluci.util.validate(name, self.valid) + -- Ignore if it already exists + if self:cfgvalue(name) then + name = nil; + end + + name = self:checkscope(name) + if not name then self.err_invalid = true end + if name and name:len() > 0 then self:create(name) end @@ -383,7 +411,7 @@ function TypedSection.parse(self) name = ffluci.http.formvalue(crval) if type(name) == "table" then for k,v in pairs(name) do - if ffluci.util.validate(k, self.valid) then + if self:cfgvalue(k) and self:checkscope(k) then self:remove(k) end end @@ -404,20 +432,37 @@ function TypedSection.render_children(self, section) end end --- Return all matching UCI sections for this TypedSection -function TypedSection.cfgsections(self) - local sections = {} - for k, v in pairs(self.map:get()) do - if v[".type"] == self.sectiontype then - if ffluci.util.validate(k, self.scope) then - sections[k] = v +-- Verifies scope of sections +function TypedSection.checkscope(self, section) + -- Check if we are not excluded + if self.excludes[section] then + return nil + end + + -- Check if at least one dependency is met + if #self.deps > 0 and self:cfgvalue(section) then + local stat = false + + for k, v in ipairs(self.deps) do + if self:cfgvalue(section)[v.option] == v.value then + stat = true end end + + if not stat then + return nil + end end - return sections + + return self:validate(section) end +-- Dummy validate function +function TypedSection.validate(self, section) + return section +end + --[[ AbstractValue - An abstract Value Type @@ -437,14 +482,25 @@ function AbstractValue.__init__(self, map, option, ...) self.map = map self.config = map.config self.tag_invalid = {} + self.deps = {} - self.valid = nil - self.depends = nil - self.default = " " + self.rmempty = false + self.default = nil self.size = nil self.optional = false end +-- Add a dependencie to another section field +function AbstractValue.depends(self, field, value) + table.insert(self.deps, {field=field, value=value}) +end + +-- Return whether this object should be created +function AbstractValue.formcreated(self, section) + local key = "cbi.opt."..self.config.."."..section + return (ffluci.http.formvalue(key) == self.option) +end + -- Returns the formvalue for this object function AbstractValue.formvalue(self, section) local key = "cbid."..self.map.config.."."..section.."."..self.option @@ -453,12 +509,8 @@ end function AbstractValue.parse(self, section) local fvalue = self:formvalue(section) - if fvalue == "" then - fvalue = nil - end - - if fvalue then -- If we have a form value, validate it and write it to UCI + if fvalue and fvalue ~= "" then -- If we have a form value, write it to UCI fvalue = self:validate(fvalue) if not fvalue then self.tag_invalid[section] = true @@ -469,16 +521,14 @@ function AbstractValue.parse(self, section) elseif ffluci.http.formvalue("cbi.submit") then -- Unset the UCI or error if self.rmempty or self.optional then self:remove(section) - else - self.tag_invalid[section] = true end end end -- Render if this value exists or if it is mandatory -function AbstractValue.render(self, section) - if not self.optional or self:cfgvalue(section) then - ffluci.template.render(self.template, {self=self, section=section}) +function AbstractValue.render(self, s) + if not self.optional or self:cfgvalue(s) or self:formcreated(s) then + ffluci.template.render(self.template, {self=self, section=s}) end end @@ -488,8 +538,8 @@ function AbstractValue.cfgvalue(self, section) end -- Validate the form value -function AbstractValue.validate(self, val) - return ffluci.util.validate(val, self.valid) +function AbstractValue.validate(self, value) + return value end -- Write to UCI @@ -529,7 +579,7 @@ function Value.validate(self, val) val = nil end - return ffluci.util.validate(val, self.valid, self.isnumber, self.isinteger) + return ffluci.util.validate(val, self.isnumber, self.isinteger) end @@ -585,7 +635,7 @@ function ListValue.__init__(self, ...) self.widget = "select" end -function ListValue.add_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)) @@ -618,7 +668,7 @@ function MultiValue.__init__(self, ...) self.delimiter = " " end -function MultiValue.add_value(self, key, val) +function MultiValue.value(self, key, val) val = val or key table.insert(self.keylist, tostring(key)) table.insert(self.vallist, tostring(val)) diff --git a/src/ffluci/controller/admin/network.lua b/src/ffluci/controller/admin/network.lua index f76dce5555..2774dfdb02 100644 --- a/src/ffluci/controller/admin/network.lua +++ b/src/ffluci/controller/admin/network.lua @@ -5,6 +5,7 @@ menu = { order = 20, entries = { {action = "vlan", descr = "VLAN"}, - {action = "ifaces", descr = "Schnittstellen"} + {action = "ifaces", descr = "Schnittstellen"}, + {action = "ptp", descr = "PPPoE / PPTP"}, } } \ No newline at end of file diff --git a/src/ffluci/controller/admin/uci.lua b/src/ffluci/controller/admin/uci.lua index db70eb6a63..a1eb0d7d72 100644 --- a/src/ffluci/controller/admin/uci.lua +++ b/src/ffluci/controller/admin/uci.lua @@ -10,7 +10,7 @@ function action_apply() -- Collect files to be applied for i, line in ipairs(ffluci.util.split(changes)) do - local r = line:match("^[^.]+") + local r = line:match("^-?([^.]+)") if r then apply[r] = true end @@ -41,7 +41,7 @@ function action_revert() -- Collect files to be reverted for i, line in ipairs(ffluci.util.split(changes)) do - local r = line:match("^[^.]+") + local r = line:match("^-?([^.]+)") if r then revert[r] = true end diff --git a/src/ffluci/model/cbi/admin_network/ifaces.lua b/src/ffluci/model/cbi/admin_network/ifaces.lua index f1d8086359..62e72462f8 100644 --- a/src/ffluci/model/cbi/admin_network/ifaces.lua +++ b/src/ffluci/model/cbi/admin_network/ifaces.lua @@ -1,15 +1,32 @@ +-- ToDo: Translate, Add descriptions and help texts m = Map("network", "Schnittstellen") s = m:section(TypedSection, "interface") s.addremove = true +s:exclude("loopback") +s:depends("proto", "static") +s:depends("proto", "dhcp") p = s:option(ListValue, "proto", "Protokoll") -p:add_value("static", "statisch") -p:add_value("dhcp", "DHCP") -s:option(Value, "ipaddr", "IP-Adresse").optional = 1 -s:option(Value, "netmask", "Netzmaske").optional = 1 -s:option(Value, "gateway", "Gateway").optional = 1 -s:option(Value, "dns", "DNS").optional = 1 -s:option(Value, "mtu", "MTU").optional = 1 +p:value("static", "statisch") +p:value("dhcp", "DHCP") + +s:option(Value, "ifname", "Schnittstelle") + +s:option(Value, "ipaddr", "IP-Adresse") + +s:option(Value, "netmask", "Netzmaske"):depends("proto", "static") + +gw = s:option(Value, "gateway", "Gateway") +gw:depends("proto", "static") +gw.rmempty = true + +dns = s:option(Value, "dns", "DNS-Server") +dns:depends("proto", "static") +dns.optional = true + +mtu = s:option(Value, "mtu", "MTU") +mtu.optional = true +mtu.isinteger = true return m \ No newline at end of file diff --git a/src/ffluci/model/cbi/admin_network/ptp.lua b/src/ffluci/model/cbi/admin_network/ptp.lua new file mode 100644 index 0000000000..78fcf94b9e --- /dev/null +++ b/src/ffluci/model/cbi/admin_network/ptp.lua @@ -0,0 +1,31 @@ +-- ToDo: Translate, Add descriptions and help texts +m = Map("network", "Punkt-zu-Punkt Verbindungen") + +s = m:section(TypedSection, "interface") +s.addremove = true +s:depends("proto", "pppoe") +s:depends("proto", "pptp") + +p = s:option(ListValue, "proto", "Protokoll") +p:value("pppoe", "PPPoE") +p:value("pptp", "PPTP") +p.default = "pppoe" + +s:option(Value, "ifname", "Schnittstelle") + +s:option(Value, "username", "Benutzername") +s:option(Value, "password", "Passwort") + +s:option(Value, "keepalive", "Keep-Alive").optional = true + +s:option(Value, "demand", "Dial on Demand (idle time)").optional = true + +srv = s:option(Value, "server", "PPTP-Server") +srv:depends("proto", "pptp") +srv.optional = true + +mtu = s:option(Value, "mtu", "MTU") +mtu.optional = true +mtu.isinteger = true + +return m \ No newline at end of file diff --git a/src/ffluci/model/cbi/admin_network/vlan.lua b/src/ffluci/model/cbi/admin_network/vlan.lua index 6a01152109..3186f2d9bb 100644 --- a/src/ffluci/model/cbi/admin_network/vlan.lua +++ b/src/ffluci/model/cbi/admin_network/vlan.lua @@ -1,12 +1,10 @@ +-- ToDo: Autodetect things, maybe use MultiValue instead, Translate, Add descriptions m = Map("network", "VLAN", "Konfguriert den Switch des Routers.") s = m:section(TypedSection, "switch") --- ToDo: Autodetect things, maybe use MultiValue instead for i = 0, 15 do - local c = s:option(Value, "vlan"..i, "vlan"..i) - c.default = "5" - c.optional = true + s:option(Value, "vlan"..i, "vlan"..i).optional = true end return m \ No newline at end of file diff --git a/src/ffluci/model/uci.lua b/src/ffluci/model/uci.lua index 75d34c5d6d..6585c66cb4 100644 --- a/src/ffluci/model/uci.lua +++ b/src/ffluci/model/uci.lua @@ -7,6 +7,9 @@ is comparable to the syntax of the uci application Any return value of false or nil can be interpreted as an error + +ToDo: Reimplement in Lua + FileId: $Id$ diff --git a/src/ffluci/util.lua b/src/ffluci/util.lua index f2180e7c00..85092f065c 100644 --- a/src/ffluci/util.lua +++ b/src/ffluci/util.lua @@ -203,7 +203,7 @@ end -- Validates a variable -function validate(value, valid, cast_number, cast_int) +function validate(value, cast_number, cast_int) if cast_number or cast_int then value = tonumber(value) end @@ -212,15 +212,6 @@ function validate(value, valid, cast_number, cast_int) value = nil end - - if type(valid) == "function" then - value = valid(value) - elseif type(valid) == "table" then - if not contains(valid, value) then - value = nil - end - end - return value end diff --git a/src/ffluci/view/cbi/footer.htm b/src/ffluci/view/cbi/footer.htm index d6e49678eb..0629bd6d60 100644 --- a/src/ffluci/view/cbi/footer.htm +++ b/src/ffluci/view/cbi/footer.htm @@ -1,4 +1,5 @@ + <%+footer%> \ No newline at end of file diff --git a/src/ffluci/view/cbi/fvalue.htm b/src/ffluci/view/cbi/fvalue.htm index 6cf9a8d87c..cce116af33 100644 --- a/src/ffluci/view/cbi/fvalue.htm +++ b/src/ffluci/view/cbi/fvalue.htm @@ -1,10 +1,11 @@ -
-
-
<%=self.title%>
-
<%=self.description%>
-
+
"> +
<%=self.title%>
- "<% if self:cfgvalue(section) == self.enabled then %> checked="checked"<% end %> value="1" /> + " name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self:cfgvalue(section) == self.enabled then %> checked="checked"<% end %> value="1" /> +
<%=self.description%>
-
-
\ No newline at end of file +
+ <% if #self.deps > 0 then %><% end %> \ No newline at end of file diff --git a/src/ffluci/view/cbi/header.htm b/src/ffluci/view/cbi/header.htm index 2731b6c2f5..e926b20916 100644 --- a/src/ffluci/view/cbi/header.htm +++ b/src/ffluci/view/cbi/header.htm @@ -1,4 +1,5 @@ <%+header%>
"> + diff --git a/src/ffluci/view/cbi/lvalue.htm b/src/ffluci/view/cbi/lvalue.htm index f2a5ff9750..943a18886a 100644 --- a/src/ffluci/view/cbi/lvalue.htm +++ b/src/ffluci/view/cbi/lvalue.htm @@ -1,9 +1,8 @@ -
+
">
<%=self.title%>
-
<%=self.description%>
<% if self.widget == "select" then %> - " name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self.size then %> size="<%=self.size%>"<% end %>> <%for i, key in pairs(self.keylist) do%> selected="selected"<% end %> value="<%=key%>"><%=self.vallist[i]%> <% end %> @@ -16,6 +15,10 @@ <% if c == self.size then c = 0 %>
<% end end %> <% end %> +
<%=self.description%>
-
-
\ No newline at end of file +
+ <% if #self.deps > 0 then %><% end %> \ No newline at end of file diff --git a/src/ffluci/view/cbi/mvalue.htm b/src/ffluci/view/cbi/mvalue.htm index de7bd0c61d..7becb4f48b 100644 --- a/src/ffluci/view/cbi/mvalue.htm +++ b/src/ffluci/view/cbi/mvalue.htm @@ -1,11 +1,8 @@ <% local v = self:valuelist(section) %> -
-
-
<%=self.title%>
-
<%=self.description%>
-
+
"> +
<%=self.title%>
<% if self.widget == "select" then %> +
<% end %>
<% self:render_children(self.section) %> <% if #self.optionals[self.section] > 0 or self.dynamic then %>
+ <% if self.dynamic then %> <% else %> <% end %> -
<% end %> -
- <% if self.addremove then %> - - <% end %>
<% elseif self.addremove then %> diff --git a/src/ffluci/view/cbi/tsection.htm b/src/ffluci/view/cbi/tsection.htm index 9205095313..15272f05f6 100644 --- a/src/ffluci/view/cbi/tsection.htm +++ b/src/ffluci/view/cbi/tsection.htm @@ -2,8 +2,11 @@

<%=self.title%>

<%=self.description%>
<% for k, v in pairs(self:cfgsections()) do%> -
+ <% if self.addremove then %>
+ +
<% end %> <% if not self.anonymous then %>

<%=k%>

<% end %> +
<% self:render_children(k) %> <% if #self.optionals[k] > 0 or self.dynamic then %>
@@ -11,19 +14,19 @@ <% else %> <% end %> - +
<% end %> -
- <% if self.addremove then %> - - <% end %>

<% end %> diff --git a/src/ffluci/view/cbi/value.htm b/src/ffluci/view/cbi/value.htm index ae4cd0eb59..d027bb4489 100644 --- a/src/ffluci/view/cbi/value.htm +++ b/src/ffluci/view/cbi/value.htm @@ -1,9 +1,12 @@ -
+
">
<%=self.title%>
-
<%=self.description%>
- size="<%=self.size%>" <% end %><% if self.maxlength then %>maxlength="<%=self.maxlength%>" <% end %>name="cbid.<%=self.config.."."..section.."."..self.option%>" value="<%=(self:cfgvalue(section) or "")%>" /> + size="<%=self.size%>" <% end %><% if self.maxlength then %>maxlength="<%=self.maxlength%>" <% end %>name="cbid.<%=self.config.."."..section.."."..self.option%>" value="<%=(self:cfgvalue(section) or "")%>" /> +
<%=self.description%>
-
<% if self.tag_invalid[section] then %>
<%:cbi_invalid Fehler: Ungültige Eingabe%>
<% end %> -
\ No newline at end of file +
+ <% if #self.deps > 0 then %><% end %>