diff options
30 files changed, 344 insertions, 128 deletions
@@ -1,14 +1,14 @@ LUAC = luac LUAC_OPTIONS = -s -FILES = ffluci/config.lua +FILES = -CFILES = ffluci/util.lua ffluci/http.lua \ -ffluci/fs.lua ffluci/i18n.lua ffluci/model/uci.lua \ +CFILES = ffluci/util.lua ffluci/http.lua ffluci/fs.lua \ +ffluci/model/uci.lua ffluci/config.lua ffluci/i18n.lua \ ffluci/template.lua ffluci/cbi.lua ffluci/dispatcher.lua \ ffluci/menu.lua ffluci/init.lua ffluci/sys.lua -DIRECTORIES = dist/ffluci/model dist/ffluci/controller dist/ffluci/i18n dist/ffluci/view +DIRECTORIES = dist/ffluci/model/cbi dist/ffluci/controller dist/ffluci/i18n dist/ffluci/view INFILES = $(CFILES:%=src/%) OUTFILE = ffluci/init.lua @@ -28,6 +28,7 @@ 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 @@ -1,6 +1,6 @@ FFLuCI - Freifunk Lua Configuration Interface -This is a leightweight MVC-Webframework for small embedded device. +This is a leightweight MVC-Webframework for small embedded devices. It uses the the Lua programming language and relies on Haserl. It consists of several parts: @@ -25,6 +25,13 @@ Template engine > See src/ffluci/template.lua for details > See src/view/ for examples + + +Configuration Bind Interface (CBI) + Generates and validates XHTML-Forms out of an UCI model description + Makes it very easy to create webinterface pages that manipulate UCI files + + > See src/ffluci/cbi.lua i18n Translation support diff --git a/contrib/ffluci.uci b/contrib/ffluci.uci new file mode 100644 index 0000000000..ecd72f6ed3 --- /dev/null +++ b/contrib/ffluci.uci @@ -0,0 +1,20 @@ +config core main + option lang de + option mediaurlbase /ffluci/media + + +config public contact + option nickname - + option name - + option mail - + option phone - + option location - + option geo - + option note - + + +config event uci_oncommit + option network "/etc/init.d/network restart" + option wireless "/etc/init.d/network restart" + option olsrd "/etc/init.d/olsrd restart" + option dhcp "/etc/init.d/dhcp restart"
\ No newline at end of file diff --git a/contrib/media/cascade.css b/contrib/media/cascade.css index 8b192ba7c8..b0131dc581 100644 --- a/contrib/media/cascade.css +++ b/contrib/media/cascade.css @@ -9,6 +9,7 @@ h1 { margin: 0%; font-size: 1.4em; font-weight: bold; + margin-bottom: 0.5em; } h2 { @@ -17,6 +18,10 @@ h2 { font-weight: bold; } +h3 { + margin: 0%; +} + #header { padding: 0.2em; height: 4.5em; @@ -156,6 +161,19 @@ h2 { display: none; } +.inline { + display: inline; +} + +code { + display: block; + background: #f7f7f7; + border: 1px solid #d7d7d7; + margin: 1em 1.75em; + padding: 1em; + overflow: auto; + white-space: pre; +} .cbi-section { margin-top: 1em; @@ -166,34 +184,37 @@ h2 { } .cbi-value-title { - font-weight: bold; line-height: 1.75em; } .cbi-value-field { - text-align: right; - vertical-align: center; + margin-left: 10em; + text-align: center; line-height: 1.75em; } +.cbi-value-field input, .cbi-value-field select, .cbi-optionals select, .cbi-optionals input { + font-size: 0.8em; +} + .cbi-value-description { - clear: both; font-style: italic; font-size: 0.8em; } -.cbi-value { - margin-bottom: 1em; -} - .cbi-form-separator { margin-top: 1em; } .cbi-section-node { - margin-top: 1em; - border: none; - background-color: #eeeeee; + display: block; + background: #f7f7f7; + border: 1px solid #d7d7d7; + overflow: auto; +} + +.cbi-section-node h3 { + margin-bottom: 0.5em; } .cbi-error { @@ -205,11 +226,6 @@ h2 { margin-top: 2em; } -.cbi-optionals select { - height: 1.5em; - width: 20em; -} - .cbi-optionals option { font-size: 0.8em; }
\ No newline at end of file diff --git a/contrib/media/css/public_index.css b/contrib/media/css/public_index.css new file mode 100644 index 0000000000..a415537a64 --- /dev/null +++ b/contrib/media/css/public_index.css @@ -0,0 +1,3 @@ +.contact th { + text-align: left; +}
\ No newline at end of file diff --git a/contrib/package/ffluci/Makefile b/contrib/package/ffluci/Makefile index 9803d3e6b2..677c865ce1 100644 --- a/contrib/package/ffluci/Makefile +++ b/contrib/package/ffluci/Makefile @@ -39,7 +39,9 @@ define Package/ffluci/install $(CP) $(PKG_BUILD_DIR)/contrib/media $(1)/www/ffluci/ -R $(INSTALL_BIN) $(PKG_BUILD_DIR)/contrib/ffluci $(1)/www/cgi-bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/contrib/index.cgi $(1)/www/cgi-bin + $(CP) $(PKG_BUILD_DIR)/contrib/ffluci.uci $(1)/etc/config/luci $(CP) -a ./ipkg/ffluci.postinst $(1)/CONTROL/postinst + $(CP) -a ./ipkg/conffiles $(1)/CONTROL/conffiles endef $(eval $(call BuildPackage,ffluci)) diff --git a/contrib/package/ffluci/ipkg/conffiles b/contrib/package/ffluci/ipkg/conffiles new file mode 100644 index 0000000000..5258af4d86 --- /dev/null +++ b/contrib/package/ffluci/ipkg/conffiles @@ -0,0 +1 @@ +/etc/config/luci
\ No newline at end of file diff --git a/src/ffluci/cbi.lua b/src/ffluci/cbi.lua index 7588a7fd6d..22a4019e40 100644 --- a/src/ffluci/cbi.lua +++ b/src/ffluci/cbi.lua @@ -168,7 +168,9 @@ end -- UCI get (cached) function Map.get(self, section, option) - if option and self.ucidata[section] then + if not section then + return self.ucidata + elseif option and self.ucidata[section] then return self.ucidata[section][option] else return self.ucidata[section] @@ -188,8 +190,8 @@ function AbstractSection.__init__(self, map, sectiontype, ...) self.config = map.config self.optionals = {} - self.addremove = true self.optional = true + self.addremove = false self.dynamic = false end @@ -210,14 +212,16 @@ function AbstractSection.parse_optionals(self, section) return end + self.optionals[section] = {} + local field = ffluci.http.formvalue("cbi.opt."..self.config.."."..section) for k,v in ipairs(self.children) do - if v.optional and not v:ucivalue(section) then + if v.optional and not v:cfgvalue(section) then if field == v.option then self.map:set(section, field, v.default) field = nil else - table.insert(self.optionals, v) + table.insert(self.optionals[section], v) end end end @@ -239,7 +243,7 @@ function AbstractSection.parse_dynamic(self, section) return end - local arr = ffluci.util.clone(self:ucivalue(section)) + local arr = ffluci.util.clone(self:cfgvalue(section)) local form = ffluci.http.formvalue("cbid."..self.config.."."..section) if type(form) == "table" then for k,v in pairs(form) do @@ -263,10 +267,20 @@ function AbstractSection.parse_dynamic(self, section) end -- Returns the section's UCI table -function AbstractSection.ucivalue(self, section) +function AbstractSection.cfgvalue(self, section) return self.map:get(section) end +-- Removes the section +function AbstractSection.remove(self, section) + return self.map:del(section) +end + +-- Creates the section +function AbstractSection.create(self, section) + return self.map:set(section, nil, self.sectiontype) +end + --[[ @@ -282,42 +296,33 @@ function NamedSection.__init__(self, map, section, ...) self.addremove = false end -function NamedSection.parse(self) - local active = self:ucivalue(self.section) +function NamedSection.parse(self) + local s = self.section + local active = self:cfgvalue(s) + if self.addremove then - local path = self.config.."."..self.section + local path = self.config.."."..s if active then -- Remove the section - if ffluci.http.formvalue("cbi.rns."..path) and self:remove() then + if ffluci.http.formvalue("cbi.rns."..path) and self:remove(s) then return end else -- Create and apply default values - if ffluci.http.formvalue("cbi.cns."..path) and self:create() then + if ffluci.http.formvalue("cbi.cns."..path) and self:create(s) then for k,v in pairs(self.children) do - v:write(self.section, v.default) + v:write(s, v.default) end end end end if active then - AbstractSection.parse_dynamic(self, self.section) - Node.parse(self, self.section) - AbstractSection.parse_optionals(self, self.section) + AbstractSection.parse_dynamic(self, s) + Node.parse(self, s) + AbstractSection.parse_optionals(self, s) end end --- Removes the section -function NamedSection.remove(self) - return self.map:del(self.section) -end - --- Creates the section -function NamedSection.create(self) - return self.map:set(self.section, nil, self.sectiontype) -end - - --[[ TypedSection - A (set of) configuration section(s) defined by the type @@ -385,18 +390,13 @@ function TypedSection.parse(self) end end - for k, v in pairs(self:ucisections()) do + for k, v in pairs(self:cfgsections()) do AbstractSection.parse_dynamic(self, k) Node.parse(self, k) AbstractSection.parse_optionals(self, k) end end --- Remove a section -function TypedSection.remove(self, name) - return self.map:del(name) -end - -- Render the children function TypedSection.render_children(self, section) for k, node in ipairs(self.children) do @@ -405,9 +405,9 @@ function TypedSection.render_children(self, section) end -- Return all matching UCI sections for this TypedSection -function TypedSection.ucisections(self) +function TypedSection.cfgsections(self) local sections = {} - for k, v in pairs(self.map.ucidata) do + 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 @@ -440,7 +440,7 @@ function AbstractValue.__init__(self, map, option, ...) self.valid = nil self.depends = nil - self.default = nil + self.default = " " self.size = nil self.optional = false end @@ -463,7 +463,7 @@ function AbstractValue.parse(self, section) if not fvalue then self.tag_invalid[section] = true end - if fvalue and not (fvalue == self:ucivalue(section)) then + if fvalue and not (fvalue == self:cfgvalue(section)) then self:write(section, fvalue) end elseif ffluci.http.formvalue("cbi.submit") then -- Unset the UCI or error @@ -477,13 +477,13 @@ end -- Render if this value exists or if it is mandatory function AbstractValue.render(self, section) - if not self.optional or self:ucivalue(section) then + if not self.optional or self:cfgvalue(section) then ffluci.template.render(self.template, {self=self, section=section}) end end -- Return the UCI value of this object -function AbstractValue.ucivalue(self, section) +function AbstractValue.cfgvalue(self, section) return self.map:get(section, self.option) end @@ -559,7 +559,7 @@ function Flag.parse(self, section) end if fvalue == self.enabled or (not self.optional and not self.rmempty) then - if not(fvalue == self:ucivalue(section)) then + if not(fvalue == self:cfgvalue(section)) then self:write(section, fvalue) end else @@ -625,7 +625,7 @@ function MultiValue.add_value(self, key, val) end function MultiValue.valuelist(self, section) - local val = self:ucivalue(section) + local val = self:cfgvalue(section) if not(type(val) == "string") then return {} diff --git a/src/ffluci/config.lua b/src/ffluci/config.lua index f63dc1fad5..8b94db8089 100644 --- a/src/ffluci/config.lua +++ b/src/ffluci/config.lua @@ -2,10 +2,8 @@ FFLuCI - Configuration Description: -Some FFLuCI configuration values +Some FFLuCI configuration values read from uci file "luci" -ToDo: -Port over to UCI FileId: $Id$ @@ -28,10 +26,22 @@ limitations under the License. ]]-- module("ffluci.config", package.seeall) +require("ffluci.model.uci") +require("ffluci.util") + +-- Warning! This is only for fallback and compatibility purporses! -- +main = {} -- This is where stylesheets and images go -mediaurlbase = "/ffluci/media" +main.mediaurlbase = "/ffluci/media" -- Does anybody think about browser autodetect here? -- Too bad busybox doesn't populate HTTP_ACCEPT_LANGUAGE -lang = "de"
\ No newline at end of file +main.lang = "de" + + +-- Now overwrite with UCI values +local ucidata = ffluci.model.uci.show("luci") +if ucidata and ucidata.luci then + ffluci.util.update(ffluci.config, ucidata.luci) +end
\ No newline at end of file diff --git a/src/ffluci/controller/admin/index.lua b/src/ffluci/controller/admin/index.lua new file mode 100644 index 0000000000..3ee564f640 --- /dev/null +++ b/src/ffluci/controller/admin/index.lua @@ -0,0 +1,9 @@ +module(..., package.seeall) + +menu = { + descr = "Übersicht", + order = 10, + entries = { + {action = "contact", descr = "Kontakt"} + } +}
\ No newline at end of file diff --git a/src/ffluci/controller/admin/network.lua b/src/ffluci/controller/admin/network.lua new file mode 100644 index 0000000000..f76dce5555 --- /dev/null +++ b/src/ffluci/controller/admin/network.lua @@ -0,0 +1,10 @@ +module(..., package.seeall) + +menu = { + descr = "Netzwerk", + order = 20, + entries = { + {action = "vlan", descr = "VLAN"}, + {action = "ifaces", descr = "Schnittstellen"} + } +}
\ No newline at end of file diff --git a/src/ffluci/controller/admin/uci.lua b/src/ffluci/controller/admin/uci.lua new file mode 100644 index 0000000000..db70eb6a63 --- /dev/null +++ b/src/ffluci/controller/admin/uci.lua @@ -0,0 +1,57 @@ +module("ffluci.controller.admin.uci", package.seeall) + +-- This function has a higher priority than the admin_uci/apply template +function action_apply() + local changes = ffluci.model.uci.changes() + local output = "" + + if changes then + local apply = {} + + -- Collect files to be applied + for i, line in ipairs(ffluci.util.split(changes)) do + local r = line:match("^[^.]+") + if r then + apply[r] = true + end + end + + -- Commit changes + ffluci.model.uci.commit() + + -- Search for post-commit commands + if ffluci.config.uci_oncommit then + for k, v in pairs(apply) do + local cmd = ffluci.config.uci_oncommit[k] + if cmd then + output = output .. ffluci.util.exec(cmd) + end + end + end + end + + ffluci.template.render("admin_uci/apply", {changes=changes, output=output}) +end + + +function action_revert() + local changes = ffluci.model.uci.changes() + if changes then + local revert = {} + + -- Collect files to be reverted + for i, line in ipairs(ffluci.util.split(changes)) do + local r = line:match("^[^.]+") + if r then + revert[r] = true + end + end + + -- Revert them + for k, v in pairs(revert) do + ffluci.model.uci.revert(k) + end + end + + ffluci.template.render("admin_uci/revert", {changes=changes}) +end
\ No newline at end of file diff --git a/src/ffluci/controller/public/index.lua b/src/ffluci/controller/public/index.lua index 4f8160a4c9..3ee564f640 100644 --- a/src/ffluci/controller/public/index.lua +++ b/src/ffluci/controller/public/index.lua @@ -1 +1,9 @@ -module(..., package.seeall)
\ No newline at end of file +module(..., package.seeall) + +menu = { + descr = "Übersicht", + order = 10, + entries = { + {action = "contact", descr = "Kontakt"} + } +}
\ No newline at end of file diff --git a/src/ffluci/i18n.lua b/src/ffluci/i18n.lua index 2a18c27d59..1abe22fd79 100644 --- a/src/ffluci/i18n.lua +++ b/src/ffluci/i18n.lua @@ -52,7 +52,7 @@ end -- Same as load but autocompletes the filename with .LANG from config.lang function loadc(file) - return load(file .. "." .. ffluci.config.lang) + return load(file .. "." .. ffluci.config.main.lang) end -- Returns the i18n-value defined by "key" or if there is no such: "default" diff --git a/src/ffluci/model/cbi/admin_index/contact.lua b/src/ffluci/model/cbi/admin_index/contact.lua new file mode 100644 index 0000000000..55f5098a55 --- /dev/null +++ b/src/ffluci/model/cbi/admin_index/contact.lua @@ -0,0 +1,15 @@ +m = Map("luci", "Kontakt", [[Diese Daten sind auf der öffentlichen Kontaktseite +sichtbar. Alle Felder sind natürlich freiwillig. Du kannst soviel oder so wenig +über dich angeben, wie du möchtest.]]) + +c = m:section(NamedSection, "contact") + +c:option(Value, "nickname", "Pseudonym") +c:option(Value, "name", "Name") +c:option(Value, "mail", "E-Mail") +c:option(Value, "phone", "Telefon") +c:option(Value, "location", "Standort") +c:option(Value, "geo", "Koordinaten", "Bitte als Breite;Länge angeben") +c:option(Value, "note", "Notiz") + +return m
\ No newline at end of file diff --git a/src/ffluci/model/uci.lua b/src/ffluci/model/uci.lua index 2d6702b577..75d34c5d6d 100644 --- a/src/ffluci/model/uci.lua +++ b/src/ffluci/model/uci.lua @@ -61,11 +61,11 @@ end -- Wrapper for "uci changes" function Session.changes(self, config) - return self:_uci3("changes " .. _path(config)) + return self:_uci("changes " .. _path(config)) end -function change(...) - return default:change(...) +function changes(...) + return default:changes(...) end @@ -105,7 +105,7 @@ function Session.revert(self, config) end function revert(...) - return self:revert(...) + return default:revert(...) end diff --git a/src/ffluci/template.lua b/src/ffluci/template.lua index 17f36194fd..f7131488ef 100644 --- a/src/ffluci/template.lua +++ b/src/ffluci/template.lua @@ -52,9 +52,9 @@ compiler_enable_bytecode = false -- Define the namespace for template modules viewns = { translate = ffluci.i18n.translate, - config = ffluci.model.uci.get, + config = function(...) return ffluci.model.uci.get(...) or "" end, controller = os.getenv("SCRIPT_NAME"), - media = ffluci.config.mediaurlbase, + media = ffluci.config.main.mediaurlbase, write = io.write, include = function(name) Template(name):render(getfenv(2)) end, } @@ -108,7 +108,7 @@ function compile(template) elseif p == "~" then re = sanitize(v):gsub("~(.-)%.(.-)%.(.+)", r_uci) elseif p == "=" then - re = r_pexec:format(string.sub(v, 2)) + re = r_pexec:format(v:sub(2)) else re = r_exec:format(v) end @@ -120,6 +120,10 @@ function compile(template) template = string.dump(tf) end + c = c or 1 + ffluci.fs.writefile("/tmp/"..tostring(c), template) + c = c+1 + return template end diff --git a/src/ffluci/util.lua b/src/ffluci/util.lua index 082310fbfa..f2180e7c00 100644 --- a/src/ffluci/util.lua +++ b/src/ffluci/util.lua @@ -152,9 +152,7 @@ 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) + setfenv(f, clone(getfenv(f))) end @@ -166,31 +164,41 @@ end -- Splits a string into an array (Taken from lua-users.org) function split(str, pat) - local t = {} - local fpat = "(.-)" .. pat - local last_end = 1 - local s, e, cap = str:find(fpat, 1) - while s do - if s ~= 1 or cap ~= "" then - table.insert(t,cap) - end - last_end = e+1 - s, e, cap = str:find(fpat, last_end) - end - if last_end <= #str then - cap = str:sub(last_end) - table.insert(t, cap) - end - return t + pat = pat or "\n" + + local t = {} + local fpat = "(.-)" .. pat + local last_end = 1 + local s, e, cap = str:find(fpat, 1) + + while s do + if s ~= 1 or cap ~= "" then + table.insert(t,cap) + end + last_end = e+1 + s, e, cap = str:find(fpat, last_end) + end + + if last_end <= #str then + cap = str:sub(last_end) + table.insert(t, cap) + end + + return t +end + + +-- Updates given table with new values +function update(t, updates) + for k, v in pairs(updates) do + t[k] = v + end 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 + update(getfenv(f), extscope) end diff --git a/src/ffluci/view/admin_uci/apply.htm b/src/ffluci/view/admin_uci/apply.htm new file mode 100644 index 0000000000..43777c6c6d --- /dev/null +++ b/src/ffluci/view/admin_uci/apply.htm @@ -0,0 +1,6 @@ +<%+header%> +<h1><%:config Konfiguration%></h1> +<p><%:uci_applied Die folgenden Änderungen wurden übernommen:%></p> +<code><%=(changes or "-")%> +<%=output%></code> +<%+footer%>
\ No newline at end of file diff --git a/src/ffluci/view/admin_uci/changes.htm b/src/ffluci/view/admin_uci/changes.htm new file mode 100644 index 0000000000..3bbcd0e5fb --- /dev/null +++ b/src/ffluci/view/admin_uci/changes.htm @@ -0,0 +1,11 @@ +<%+header%> +<h1><%:config Konfiguration%></h1> +<h2><%:changes Änderungen%></h2> +<code><%=(ffluci.model.uci.changes() or "-")%></code> +<form class="inline" method="get" action="<%=controller%>/admin/uci/apply"> + <input type="submit" value="<%:apply Anwenden%>" /> +</form> +<form class="inline" method="get" action="<%=controller%>/admin/uci/revert"> + <input type="submit" value="<%:revert Verwerfen%>" /> +</form> +<%+footer%>
\ No newline at end of file diff --git a/src/ffluci/view/admin_uci/revert.htm b/src/ffluci/view/admin_uci/revert.htm new file mode 100644 index 0000000000..f5eabc71b7 --- /dev/null +++ b/src/ffluci/view/admin_uci/revert.htm @@ -0,0 +1,5 @@ +<%+header%> +<h1><%:config Konfiguration%></h1> +<p><%:uci_reverted Die folgenden Änderungen wurden verworfen:%></p> +<code><%=(changes or "-")%></code> +<%+footer%>
\ No newline at end of file diff --git a/src/ffluci/view/cbi/footer.htm b/src/ffluci/view/cbi/footer.htm index 230a17da86..d6e49678eb 100644 --- a/src/ffluci/view/cbi/footer.htm +++ b/src/ffluci/view/cbi/footer.htm @@ -1,5 +1,4 @@ - <hr class="cbi-form-separator" /> - <input type="submit" value="<%:cbi_save Speichern%>" /> - <input type="reset" value="<%:cbi_reset Zurücksetzen%>" /> + <input type="submit" value="<%:save Speichern%>" /> + <input type="reset" value="<%:reset Zurücksetzen%>" /> </form> <%+footer%>
\ No newline at end of file diff --git a/src/ffluci/view/cbi/fvalue.htm b/src/ffluci/view/cbi/fvalue.htm index 8c8a2dfba0..6cf9a8d87c 100644 --- a/src/ffluci/view/cbi/fvalue.htm +++ b/src/ffluci/view/cbi/fvalue.htm @@ -4,7 +4,7 @@ <div class="cbi-value-description"><%=self.description%></div> </div> <div class="cbi-value-field"> - <input type="checkbox" name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self:ucivalue(section) == self.enabled then %> checked="checked"<% end %> value="1" /> + <input type="checkbox" name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self:cfgvalue(section) == self.enabled then %> checked="checked"<% end %> value="1" /> </div> <div class="clear"></div> </div>
\ No newline at end of file diff --git a/src/ffluci/view/cbi/lvalue.htm b/src/ffluci/view/cbi/lvalue.htm index abe5080174..f2a5ff9750 100644 --- a/src/ffluci/view/cbi/lvalue.htm +++ b/src/ffluci/view/cbi/lvalue.htm @@ -1,20 +1,18 @@ <div class="cbi-value"> - <div class="left"> - <div class="cbi-value-title"><%=self.title%></div> - <div class="cbi-value-description"><%=self.description%></div> - </div> + <div class="cbi-value-title left"><%=self.title%></div> + <div class="cbi-value-description right"><%=self.description%></div> <div class="cbi-value-field"> <% if self.widget == "select" then %> <select name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self.size then %> size="<%=self.size%>"<% end %>> <%for i, key in pairs(self.keylist) do%> - <option<% if self:ucivalue(section) == key then %> selected="selected"<% end %> value="<%=key%>"><%=self.vallist[i]%></option> + <option<% if self:cfgvalue(section) == key then %> selected="selected"<% end %> value="<%=key%>"><%=self.vallist[i]%></option> <% end %> </select> <% elseif self.widget == "radio" then local c = 0; for i, key in pairs(self.keylist) do c = c + 1%> - <%=self.vallist[i]%><input type="radio" name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self:ucivalue(section) == key then %> checked="checked"<% end %> value="<%=key%>" /> + <%=self.vallist[i]%><input type="radio" name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self:cfgvalue(section) == key then %> checked="checked"<% end %> value="<%=key%>" /> <% if c == self.size then c = 0 %><br /> <% end end %> <% end %> diff --git a/src/ffluci/view/cbi/nsection.htm b/src/ffluci/view/cbi/nsection.htm index 80dcefc07c..7615104ad7 100644 --- a/src/ffluci/view/cbi/nsection.htm +++ b/src/ffluci/view/cbi/nsection.htm @@ -1,17 +1,17 @@ -<% if self:ucivalue(self.section) then %> +<% if self:cfgvalue(self.section) then %> <div class="cbi-section" id="cbi-<%=self.config%>-<%=self.section%>"> <h2><%=self.title%></h2> <div class="cbi-section-descr"><%=self.description%></div> <fieldset class="cbi-section-node"> <% self:render_children(self.section) %> - <% if #self.optionals > 0 or self.dynamic then %> + <% if #self.optionals[self.section] > 0 or self.dynamic then %> <div class="cbi-optionals"> <% if self.dynamic then %> <input type="text" name="cbi.opt.<%=self.config%>.<%=self.section%>" /> <% else %> <select name="cbi.opt.<%=self.config%>.<%=self.section%>"> - <option><%:cbi_selopt *** Zusätzliche Felder ***%></option> - <% for key, val in pairs(self.optionals) do %> + <option><%:cbi_selopt *** Zusätzliche Parameter ***%></option> + <% for key, val in pairs(self.optionals[self.section]) do %> <option value="<%=val.option%>"><%=val.title%></option> <% end %> </select> diff --git a/src/ffluci/view/cbi/tsection.htm b/src/ffluci/view/cbi/tsection.htm index 26f8b198e8..9205095313 100644 --- a/src/ffluci/view/cbi/tsection.htm +++ b/src/ffluci/view/cbi/tsection.htm @@ -1,18 +1,18 @@ <div class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>"> <h2><%=self.title%></h2> <div class="cbi-section-descr"><%=self.description%></div> -<% for k, v in pairs(self:ucisections()) do%> +<% for k, v in pairs(self:cfgsections()) do%> <fieldset class="cbi-section-node" id="cbi-<%=self.config%>-<%=k%>"> - <% if not self.anonymous then %><legend><%=k%></legend><% end %> + <% if not self.anonymous then %><h3><%=k%></h3><% end %> <% self:render_children(k) %> - <% if #self.optionals > 0 or self.dynamic then %> + <% if #self.optionals[k] > 0 or self.dynamic then %> <div class="cbi-optionals"> <% if self.dynamic then %> <input type="text" name="cbi.opt.<%=self.config%>.<%=k%>" /> <% else %> <select name="cbi.opt.<%=self.config%>.<%=k%>"> - <option><%:cbi_selopt *** Zusätzliche Felder ***%></option> - <% for key, val in pairs(self.optionals) do %> + <option><%:cbi_selopt *** Zusätzliche Parameter ***%></option> + <% for key, val in pairs(self.optionals[k]) do %> <option value="<%=val.option%>"><%=val.title%></option> <% end %> </select> diff --git a/src/ffluci/view/cbi/value.htm b/src/ffluci/view/cbi/value.htm index 54ca720d90..ae4cd0eb59 100644 --- a/src/ffluci/view/cbi/value.htm +++ b/src/ffluci/view/cbi/value.htm @@ -1,10 +1,8 @@ <div class="cbi-value"> - <div class="left"> - <div class="cbi-value-title"><%=self.title%></div> - <div class="cbi-value-description"><%=self.description%></div> - </div> + <div class="cbi-value-title left"><%=self.title%></div> + <div class="cbi-value-description right"><%=self.description%></div> <div class="cbi-value-field"> - <input type="text" <% if self.size then %>size="<%=self.size%>" <% end %><% if self.maxlength then %>maxlength="<%=self.maxlength%>" <% end %>name="cbid.<%=self.config.."."..section.."."..self.option%>" value="<%=(self:ucivalue(section) or "")%>" /> + <input type="text" <% if self.size then %>size="<%=self.size%>" <% end %><% if self.maxlength then %>maxlength="<%=self.maxlength%>" <% end %>name="cbid.<%=self.config.."."..section.."."..self.option%>" value="<%=(self:cfgvalue(section) or "")%>" /> </div> <div class="clear"></div> <% if self.tag_invalid[section] then %><div class="cbi-error"><%:cbi_invalid Fehler: Ungültige Eingabe%></div><% end %> diff --git a/src/ffluci/view/footer.htm b/src/ffluci/view/footer.htm index c43cbb7e42..8d48c5fac4 100644 --- a/src/ffluci/view/footer.htm +++ b/src/ffluci/view/footer.htm @@ -2,6 +2,6 @@ <div class="clear"></div> </div></div> -<div class="separator magenta bold">FFLuCI 0.1 - Freifunk Lua Configuration Interface</div> +<div class="separator magenta bold">FFLuCI 0.2 - Freifunk Lua Configuration Interface</div> </body> </html>
\ No newline at end of file diff --git a/src/ffluci/view/header.htm b/src/ffluci/view/header.htm index cd2a64b55c..db5570515b 100644 --- a/src/ffluci/view/header.htm +++ b/src/ffluci/view/header.htm @@ -11,7 +11,6 @@ require("ffluci.http").htmlheader() <head> <link rel="stylesheet" type="text/css" href="<%=media%>/cascade.css" /> <link rel="stylesheet" type="text/css" href="<%=media%>/css/<%=req.category%>_<%=req.module%>.css" /> - <link rel="stylesheet" type="text/css" href="<%=media%>/css/<%=req.category%>_<%=req.module%>/<%=req.action%>.css" /> <title>FFLuCI</title> </head> <body> @@ -49,12 +48,29 @@ require("ffluci.http").htmlheader() <div class="sidebar right"> <div><%:webif Weboberfläche%> <ul> - <li<% if "public" == req.category then %> class="yellowtext"<% end %>><a href="<%=controller%>/public"><%:public Public%></a></li> - <li<% if "admin" == req.category then %> class="yellowtext"<% end %>><a href="<%=controller%>/admin"><%:admin Admin%></a></li> + <li<% if "public" == req.category then %> class="yellowtext"<% end %>><a href="<%=controller%>/public"><%:public Öffentlich%></a></li> + <li<% if "admin" == req.category then %> class="yellowtext"<% end %>><a href="<%=controller%>/admin"><%:admin Verwaltung%></a></li> + </ul> + </div> + <% + if "admin" == req.category then + require("ffluci.model.uci") + local ucic = ffluci.model.uci.changes() + if ucic then + ucic = #ffluci.util.split(ucic) + end + %> + <div><%:config Konfiguration%> + <ul> + <% if ucic then %> + <li><a href="<%=controller%>/admin/uci/changes"><%:changes Änderungen:%> <%=ucic%></a></li> + <li><a href="<%=controller%>/admin/uci/apply"><%:apply Anwenden%></a></li> + <li><a href="<%=controller%>/admin/uci/revert"><%:revert Verwerfen%></a></li> + <% else %> + <li><%:changes Änderungen: %> 0</li> + <% end %> </ul> </div> - <% if "admin" == req.category then %> - <div>Konfiguration<ul><li>x Änderungen</li><li>Anwenden</li><li>Zurücksetzen</li></ul></div> <% end %> </div> <div id="content">
\ No newline at end of file diff --git a/src/ffluci/view/public_index/contact.htm b/src/ffluci/view/public_index/contact.htm new file mode 100644 index 0000000000..ded0a94af0 --- /dev/null +++ b/src/ffluci/view/public_index/contact.htm @@ -0,0 +1,12 @@ +<%+header%> +<h1><%:contact Kontakt%></h1> +<table class="contact"> + <tr><th><%:nickname Pseudonym%>:</th><td><%~luci.contact.nickname%></td></tr> + <tr><th><%:name Name%>:</th><td><%~luci.contact.name%></td></tr> + <tr><th><%:mail E-Mail%>:</th><td><%~luci.contact.mail%></td></tr> + <tr><th><%:phone Telefon%>:</th><td><%~luci.contact.phone%></td></tr> + <tr><th><%:location Standort%>:</th><td><%~luci.contact.location%></td></tr> + <tr><th><%:geocoord Geokoordinaten%>:</th><td><%~luci.contact.geo%></td></tr> + <tr><th><%:note Notiz%>:</th><td><%~luci.contact.note%></td></tr> +</table> +<%+footer%>
\ No newline at end of file |