diff options
Diffstat (limited to 'applications')
21 files changed, 996 insertions, 0 deletions
diff --git a/applications/cbi/Makefile b/applications/cbi/Makefile new file mode 100644 index 0000000000..81a96f6a83 --- /dev/null +++ b/applications/cbi/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk
\ No newline at end of file diff --git a/applications/cbi/root/www/resources/cbi.js b/applications/cbi/root/www/resources/cbi.js new file mode 100644 index 0000000000..a3a47aa45b --- /dev/null +++ b/applications/cbi/root/www/resources/cbi.js @@ -0,0 +1,42 @@ +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<cbi_d[target][x].length; i++) { + var y = document.getElementById(cbi_d[target][x][i]) + y.style.display = "none"; + } + } + + var t = document.getElementById(target); + if (t && t.value && cbi_d[target][t.value]) { + for (var i=0; i<cbi_d[target][t.value].length; i++) { + var y = document.getElementById(cbi_d[target][t.value][i]) + if (!y.value) { + y.style.display = "table-row"; + } else { + y.style.display = "block"; + } + } + } +} + +function cbi_d_init() { + for (var x in cbi_d) { + cbi_d_update(x); + } +}
\ No newline at end of file diff --git a/applications/cbi/src/cbi.lua b/applications/cbi/src/cbi.lua new file mode 100644 index 0000000000..b7097b5d95 --- /dev/null +++ b/applications/cbi/src/cbi.lua @@ -0,0 +1,747 @@ +--[[ +LuCI - Configuration Bind Interface + +Description: +Offers an interface for binding confiugration values to certain +data types. Supports value and range validation and basic dependencies. + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth <steven@midlink.org> + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.cbi", package.seeall) + +require("luci.template") +require("luci.util") +require("luci.http") +require("luci.model.uci") + +local class = luci.util.class +local instanceof = luci.util.instanceof + +-- Loads a CBI map from given file, creating an environment and returns it +function load(cbimap) + require("luci.fs") + require("luci.i18n") + require("luci.config") + require("luci.sys") + + local cbidir = luci.sys.libpath() .. "/model/cbi/" + local func, err = loadfile(cbidir..cbimap..".lua") + + if not func then + return nil + end + + luci.i18n.loadc("cbi") + + luci.util.resfenv(func) + luci.util.updfenv(func, luci.cbi) + luci.util.extfenv(func, "translate", luci.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 or "" + self.description = description or "" + self.template = "cbi/node" +end + +-- Append child nodes +function Node.append(self, obj) + table.insert(self.children, obj) +end + +-- Parse this node and its children +function Node.parse(self, ...) + for k, child in ipairs(self.children) do + child:parse(...) + end +end + +-- Render this node +function Node.render(self, scope) + scope = scope or {} + scope.self = self + + luci.template.render(self.template, scope) +end + +-- Render the children +function Node.render_children(self, ...) + for k, node in ipairs(self.children) do + node:render(...) + end +end + + +--[[ +A simple template element +]]-- +Template = class(Node) + +function Template.__init__(self, template) + Node.__init__(self) + self.template = template +end + + +--[[ +Map - A map describing a configuration file +]]-- +Map = class(Node) + +function Map.__init__(self, config, ...) + Node.__init__(self, ...) + self.config = config + self.template = "cbi/map" + self.uci = luci.model.uci.Session() + self.ucidata, self.uciorder = self.uci:sections(self.config) + if not self.ucidata or not self.uciorder then + error("Unable to read UCI data: " .. self.config) + end +end + +-- Use optimized UCI writing +function Map.parse(self, ...) + self.uci:t_load(self.config) + Node.parse(self, ...) + self.uci:t_save(self.config) +end + +-- Creates a child section +function Map.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 + +-- UCI add +function Map.add(self, sectiontype) + local name = self.uci:t_add(self.config, sectiontype) + if name then + self.ucidata[name] = {} + self.ucidata[name][".type"] = sectiontype + table.insert(self.uciorder, name) + end + return name +end + +-- UCI set +function Map.set(self, section, option, value) + local stat = self.uci:t_set(self.config, section, option, value) + if stat then + local val = self.uci:t_get(self.config, section, option) + if option then + self.ucidata[section][option] = val + else + if not self.ucidata[section] then + self.ucidata[section] = {} + end + self.ucidata[section][".type"] = val + table.insert(self.uciorder, section) + end + end + return stat +end + +-- UCI del +function Map.del(self, section, option) + local stat = self.uci:t_del(self.config, section, option) + if stat then + if option then + self.ucidata[section][option] = nil + else + self.ucidata[section] = nil + for i, k in ipairs(self.uciorder) do + if section == k then + table.remove(self.uciorder, i) + end + end + end + end + return stat +end + +-- UCI get (cached) +function Map.get(self, section, option) + if not section then + return self.ucidata, self.uciorder + elseif option and self.ucidata[section] then + return self.ucidata[section][option] + else + return self.ucidata[section] + end +end + + +--[[ +AbstractSection +]]-- +AbstractSection = class(Node) + +function AbstractSection.__init__(self, map, sectiontype, ...) + Node.__init__(self, ...) + self.sectiontype = sectiontype + self.map = map + self.config = map.config + self.optionals = {} + + self.optional = true + self.addremove = false + self.dynamic = false +end + +-- Appends a new option +function AbstractSection.option(self, class, ...) + if instanceof(class, AbstractValue) then + local obj = class(self.map, ...) + self:append(obj) + return obj + else + error("class must be a descendent of AbstractValue") + end +end + +-- Parse optional options +function AbstractSection.parse_optionals(self, section) + if not self.optional then + return + end + + self.optionals[section] = {} + + local field = luci.http.formvalue("cbi.opt."..self.config.."."..section) + for k,v in ipairs(self.children) do + if v.optional and not v:cfgvalue(section) then + if field == v.option then + field = nil + else + table.insert(self.optionals[section], v) + end + end + end + + if field and #field > 0 and self.dynamic then + self:add_dynamic(field) + end +end + +-- Add a dynamic option +function AbstractSection.add_dynamic(self, field, optional) + local o = self:option(Value, field, field) + o.optional = optional +end + +-- Parse all dynamic options +function AbstractSection.parse_dynamic(self, section) + if not self.dynamic then + return + end + + local arr = luci.util.clone(self:cfgvalue(section)) + local form = luci.http.formvaluetable("cbid."..self.config.."."..section) + for k, v in pairs(form) do + arr[k] = v + end + + for key,val in pairs(arr) do + local create = true + + for i,c in ipairs(self.children) do + if c.option == key then + create = false + end + end + + if create and key:sub(1, 1) ~= "." then + self:add_dynamic(key, true) + end + end +end + +-- Returns the section's UCI table +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 + + + +--[[ +NamedSection - A fixed configuration section defined by its name +]]-- +NamedSection = class(AbstractSection) + +function NamedSection.__init__(self, map, section, ...) + AbstractSection.__init__(self, map, ...) + self.template = "cbi/nsection" + + self.section = section + self.addremove = false +end + +function NamedSection.parse(self) + local s = self.section + local active = self:cfgvalue(s) + + + if self.addremove then + local path = self.config.."."..s + if active then -- Remove the section + if luci.http.formvalue("cbi.rns."..path) and self:remove(s) then + return + end + else -- Create and apply default values + if luci.http.formvalue("cbi.cns."..path) and self:create(s) then + for k,v in pairs(self.children) do + v:write(s, v.default) + end + end + end + end + + if active then + AbstractSection.parse_dynamic(self, s) + if luci.http.formvalue("cbi.submit") then + Node.parse(self, s) + end + AbstractSection.parse_optionals(self, s) + end +end + + +--[[ +TypedSection - A (set of) configuration section(s) defined by the type + addremove: Defines whether the user can add/remove sections of this type + anonymous: Allow creating anonymous sections + validate: a validation function returning nil if the section is invalid +]]-- +TypedSection = class(AbstractSection) + +function TypedSection.__init__(self, ...) + AbstractSection.__init__(self, ...) + self.template = "cbi/tsection" + self.deps = {} + self.excludes = {} + + self.anonymous = false +end + +-- Return all matching UCI sections for this TypedSection +function TypedSection.cfgsections(self) + local sections = {} + local map, order = self.map:get() + + for i, k in ipairs(order) do + if map[k][".type"] == self.sectiontype then + if self:checkscope(k) then + table.insert(sections, k) + end + end + end + + return sections +end + +-- Creates a new section of this type with the given name (or anonymous) +function TypedSection.create(self, name) + if name then + self.map:set(name, nil, self.sectiontype) + else + name = self.map:add(self.sectiontype) + end + + for k,v in pairs(self.children) do + if v.default then + self.map:set(name, v.option, v.default) + end + end +end + +-- Limits scope to sections that have certain option => 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 + local crval = "cbi.cts." .. self.config .. "." .. self.sectiontype + local name = luci.http.formvalue(crval) + if self.anonymous then + if name then + self:create() + end + else + if name then + -- 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 + end + end + + -- Remove + crval = "cbi.rts." .. self.config + name = luci.http.formvaluetable(crval) + for k,v in pairs(name) do + if self:cfgvalue(k) and self:checkscope(k) then + self:remove(k) + end + end + end + + for i, k in ipairs(self:cfgsections()) do + AbstractSection.parse_dynamic(self, k) + if luci.http.formvalue("cbi.submit") then + Node.parse(self, k) + end + AbstractSection.parse_optionals(self, k) + end +end + +-- 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 self:validate(section) +end + + +-- Dummy validate function +function TypedSection.validate(self, section) + return section +end + + +--[[ +AbstractValue - An abstract Value Type + null: Value can be empty + valid: A function returning the value if it is valid otherwise nil + depends: A table of option => value pairs of which one must be true + default: The default value + size: The size of the input fields + rmempty: Unset value if empty + optional: This value is optional (see AbstractSection.optionals) +]]-- +AbstractValue = class(Node) + +function AbstractValue.__init__(self, map, option, ...) + Node.__init__(self, ...) + self.option = option + self.map = map + self.config = map.config + self.tag_invalid = {} + self.deps = {} + + 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 (luci.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 + return luci.http.formvalue(key) +end + +function AbstractValue.parse(self, section) + local fvalue = self:formvalue(section) + + 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 + end + if fvalue and not (fvalue == self:cfgvalue(section)) then + self:write(section, fvalue) + end + else -- Unset the UCI or error + if self.rmempty or self.optional then + self:remove(section) + end + end +end + +-- Render if this value exists or if it is mandatory +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 + Node.render(self, scope) + end +end + +-- Return the UCI value of this object +function AbstractValue.cfgvalue(self, section) + return self.map:get(section, self.option) +end + +-- Validate the form value +function AbstractValue.validate(self, value) + return value +end + +-- Write to UCI +function AbstractValue.write(self, section, value) + return self.map:set(section, self.option, value) +end + +-- Remove from UCI +function AbstractValue.remove(self, section) + return self.map:del(section, self.option) +end + + + + +--[[ +Value - A one-line value + maxlength: The maximum length + isnumber: The value must be a valid (floating point) number + isinteger: The value must be a valid integer + ispositive: The value must be positive (and a number) +]]-- +Value = class(AbstractValue) + +function Value.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/value" + + self.maxlength = nil + self.isnumber = false + self.isinteger = false +end + +-- This validation is a bit more complex +function Value.validate(self, val) + if self.maxlength and tostring(val):len() > self.maxlength then + val = nil + end + + return luci.util.validate(val, self.isnumber, self.isinteger) +end + + +-- DummyValue - This does nothing except being there +DummyValue = class(AbstractValue) + +function DummyValue.__init__(self, map, ...) + AbstractValue.__init__(self, map, ...) + self.template = "cbi/dvalue" + self.value = nil +end + +function DummyValue.parse(self) + +end + +function DummyValue.render(self, s) + luci.template.render(self.template, {self=self, section=s}) +end + + +--[[ +Flag - A flag being enabled or disabled +]]-- +Flag = class(AbstractValue) + +function Flag.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/fvalue" + + self.enabled = "1" + self.disabled = "0" +end + +-- A flag can only have two states: set or unset +function Flag.parse(self, section) + local fvalue = self:formvalue(section) + + if fvalue then + fvalue = self.enabled + else + fvalue = self.disabled + end + + if fvalue == self.enabled or (not self.optional and not self.rmempty) then + if not(fvalue == self:cfgvalue(section)) then + self:write(section, fvalue) + end + else + self:remove(section) + end +end + + + +--[[ +ListValue - A one-line value predefined in a list + widget: The widget that will be used (select, radio) +]]-- +ListValue = class(AbstractValue) + +function ListValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/lvalue" + self.keylist = {} + self.vallist = {} + + self.size = 1 + self.widget = "select" +end + +function ListValue.value(self, key, val) + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + +function ListValue.validate(self, val) + if luci.util.contains(self.keylist, val) then + return val + else + return nil + end +end + + + +--[[ +MultiValue - Multiple delimited values + widget: The widget that will be used (select, checkbox) + delimiter: The delimiter that will separate the values (default: " ") +]]-- +MultiValue = class(AbstractValue) + +function MultiValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/mvalue" + self.keylist = {} + self.vallist = {} + + self.widget = "checkbox" + self.delimiter = " " +end + +function MultiValue.value(self, key, val) + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + +function MultiValue.valuelist(self, section) + local val = self:cfgvalue(section) + + if not(type(val) == "string") then + return {} + end + + return luci.util.split(val, self.delimiter) +end + +function MultiValue.validate(self, val) + if not(type(val) == "string") then + return nil + end + + local result = "" + + for value in val:gmatch("[^\n]+") do + if luci.util.contains(self.keylist, value) then + result = result .. self.delimiter .. value + end + end + + if result:len() > 0 then + return result:sub(self.delimiter:len() + 1) + else + return nil + end +end
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/dvalue.htm b/applications/cbi/src/view/cbi/dvalue.htm new file mode 100644 index 0000000000..f54667def6 --- /dev/null +++ b/applications/cbi/src/view/cbi/dvalue.htm @@ -0,0 +1,12 @@ +<%+cbi/valueheader%> +<% if self.value then + if type(self.value) == "function" then %> + <%=self:value(section)%> +<% else %> + <%=self.value%> +<% end +else %> + <%=self:cfgvalue(section)%> +<% end %> + +<%+cbi/valuefooter%> diff --git a/applications/cbi/src/view/cbi/footer.htm b/applications/cbi/src/view/cbi/footer.htm new file mode 100644 index 0000000000..2acf710cdd --- /dev/null +++ b/applications/cbi/src/view/cbi/footer.htm @@ -0,0 +1,7 @@ + <div> + <input type="submit" value="<%:save Speichern%>" /> + <input type="reset" value="<%:reset Zurücksetzen%>" /> + <script type="text/javascript">cbi_d_init();</script> + </div> + </form> +<%+footer%>
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/full_valuefooter.htm b/applications/cbi/src/view/cbi/full_valuefooter.htm new file mode 100644 index 0000000000..6151a3a66a --- /dev/null +++ b/applications/cbi/src/view/cbi/full_valuefooter.htm @@ -0,0 +1,8 @@ + <div class="cbi-value-description"><%=self.description%> </div> + </div> + <% if self.tag_invalid[section] then %><div class="cbi-error"><%:cbi_invalid Fehler: Ungültige Eingabe%></div><% end %> + </div> + <% if #self.deps > 0 then %><script type="text/javascript"> + <% for j, d in ipairs(self.deps) do %>cbi_d_add("cbi-<%=self.config.."-"..section.."-"..self.option%>", "cbid.<%=self.config.."."..section.."."..d.field%>", "<%=d.value%>"); + <% end %> + </script><% end %>
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/full_valueheader.htm b/applications/cbi/src/view/cbi/full_valueheader.htm new file mode 100644 index 0000000000..062efa2ddd --- /dev/null +++ b/applications/cbi/src/view/cbi/full_valueheader.htm @@ -0,0 +1,3 @@ + <div class="cbi-value" id="cbi-<%=self.config.."-"..section.."-"..self.option%>"> + <div class="cbi-value-title"><%=self.title%></div> + <div class="cbi-value-field">
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/fvalue.htm b/applications/cbi/src/view/cbi/fvalue.htm new file mode 100644 index 0000000000..b609f1d4f4 --- /dev/null +++ b/applications/cbi/src/view/cbi/fvalue.htm @@ -0,0 +1,3 @@ +<%+cbi/valueheader%> + <input onchange="cbi_d_update(this.id)" type="checkbox" id="cbid.<%=self.config.."."..section.."."..self.option%>" name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self:cfgvalue(section) == self.enabled then %> checked="checked"<% end %> value="1" /> +<%+cbi/valuefooter%>
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/header.htm b/applications/cbi/src/view/cbi/header.htm new file mode 100644 index 0000000000..4229aaf0df --- /dev/null +++ b/applications/cbi/src/view/cbi/header.htm @@ -0,0 +1,7 @@ +<%+header%> + <form method="post" action="<%=luci.http.env.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 Speichern%>" class="hidden" /> + </div> diff --git a/applications/cbi/src/view/cbi/lvalue.htm b/applications/cbi/src/view/cbi/lvalue.htm new file mode 100644 index 0000000000..f1ae5a0939 --- /dev/null +++ b/applications/cbi/src/view/cbi/lvalue.htm @@ -0,0 +1,16 @@ +<%+cbi/valueheader%> +<% if self.widget == "select" then %> + <select onchange="cbi_d_update(this.id)" id="cbid.<%=self.config.."."..section.."."..self.option%>" 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: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:cfgvalue(section) == key then %> checked="checked"<% end %> value="<%=key%>" /> +<% if c == self.size then c = 0 %><br /> +<% end end %> +<% end %> +<%+cbi/valuefooter%>
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/map.htm b/applications/cbi/src/view/cbi/map.htm new file mode 100644 index 0000000000..835393c1c5 --- /dev/null +++ b/applications/cbi/src/view/cbi/map.htm @@ -0,0 +1,6 @@ + <div class="cbi-map" id="cbi-<%=self.config%>"> + <h1><%=self.title%></h1> + <div class="cbi-map-descr"><%=self.description%></div> +<% self:render_children() %> + <br /> + </div> diff --git a/applications/cbi/src/view/cbi/mvalue.htm b/applications/cbi/src/view/cbi/mvalue.htm new file mode 100644 index 0000000000..bed66e569a --- /dev/null +++ b/applications/cbi/src/view/cbi/mvalue.htm @@ -0,0 +1,19 @@ +<% +local v = self:valuelist(section) +%> +<%+cbi/valueheader%> +<% if self.widget == "select" then %> + <select multiple="multiple" 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 luci.util.contains(v, key) then %> selected="selected"<% end %> value="<%=key%>"><%=self.vallist[i]%></option> +<% end %> + </select> +<% elseif self.widget == "checkbox" then + local c = 0; + for i, key in pairs(self.keylist) do + c = c + 1%> + <%=self.vallist[i]%><input type="checkbox" name="cbid.<%=self.config.."."..section.."."..self.option%>[]"<% if luci.util.contains(v, key) then %> checked="checked"<% end %> value="<%=key%>" /> +<% if c == self.size then c = 0 %><br /> +<% end end %> +<% end %> +<%+cbi/valuefooter%>
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/nsection.htm b/applications/cbi/src/view/cbi/nsection.htm new file mode 100644 index 0000000000..fff597ad06 --- /dev/null +++ b/applications/cbi/src/view/cbi/nsection.htm @@ -0,0 +1,20 @@ +<% if self:cfgvalue(self.section) then +section = self.section %> + <div class="cbi-section" id="cbi-<%=self.config%>-<%=section%>"> + <h2><%=self.title%></h2> + <div class="cbi-section-descr"><%=self.description%></div> + <% if self.addremove then %><div class="cbi-section-remove right"> + <input type="submit" name="cbi.rns.<%=self.config%>.<%=section%>" value="<%:cbi_del Eintrag entfernen%>" /> + </div><% end %> +<div class="cbi-section-node" id="cbi-<%=self.config%>-<%=section%>"> +<%+cbi/ucisection%> +</div> +<br /> + </div> +<% elseif self.addremove then %> + <div class="cbi-section" id="cbi-<%=self.config%>-<%=self.section%>"> + <h2><%=self.title%></h2> + <div class="cbi-section-descr"><%=self.description%></div> + <input type="submit" name="cbi.cns.<%=self.config%>.<%=self.section%>" value="<%:cbi_add Eintrag anlegen%>" /> + </div> +<% end %> diff --git a/applications/cbi/src/view/cbi/tblsection.htm b/applications/cbi/src/view/cbi/tblsection.htm new file mode 100644 index 0000000000..df16efbed0 --- /dev/null +++ b/applications/cbi/src/view/cbi/tblsection.htm @@ -0,0 +1,39 @@ + <div class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>"> + <h2><%=self.title%></h2> + <div class="cbi-section-descr"><%=self.description%></div> + <div class="cbi-section-node"> + <div class="cbi-section-row"> +<% for i, k in pairs(self.children) do %> + <div class="cbi-section-row-head"><%=k.title%></div> +<% end %> + </div> + <div class="cbi-section-row"> +<% for i, k in pairs(self.children) do %> + <div class="cbi-section-row-descr"><%=k.description%></div> +<% end %> + </div> +<% for i, k in ipairs(self:cfgsections()) do%> + <% if not self.anonymous then %><h3 class="table-cell"><%=k%></h3><% end %> +<% +section = k +scope = {valueheader = "cbi/tiny_valueheader", valuefooter = "cbi/tiny_valuefooter"} +%> +<div class="cbi-section-row" id="cbi-<%=self.config%>-<%=section%>"> +<%+cbi/ucisection%> + <% if self.addremove then %><div class="cbi-section-remove table-cell"> + <input type="submit" name="cbi.rts.<%=self.config%>.<%=k%>" value="X" /> + </div><% end %> +</div> +<% end %> +<% if self.addremove then %> + <div class="cbi-section-create"> + <% if self.anonymous then %> + <input type="submit" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>" value="<%:cbi_add Eintrag hinzufügen%>" /> + <% else %> + <input type="text" class="cbi-section-create-name" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>" /> + <input type="submit" value="<%:cbi_add Eintrag hinzufügen%>" /> + <% end %><% if self.err_invalid then %><div class="cbi-error"><%:cbi_invalid Fehler: Ungültige Eingabe%></div><% end %> + </div> + </div> +<% end %> + </div> diff --git a/applications/cbi/src/view/cbi/tiny_valuefooter.htm b/applications/cbi/src/view/cbi/tiny_valuefooter.htm new file mode 100644 index 0000000000..e65ebb6c03 --- /dev/null +++ b/applications/cbi/src/view/cbi/tiny_valuefooter.htm @@ -0,0 +1,6 @@ + <% if self.tag_invalid[section] then %><div class="cbi-error"><%:cbi_invalid Fehler: Ungültige Eingabe%></div><% end %> + </div> + <% if #self.deps > 0 then %><script type="text/javascript"> + <% for j, d in ipairs(self.deps) do %>cbi_d_add("cbi-<%=self.config.."-"..section.."-"..self.option%>", "cbid.<%=self.config.."."..section.."."..d.field%>", "<%=d.value%>"); + <% end %> + </script><% end %>
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/tiny_valueheader.htm b/applications/cbi/src/view/cbi/tiny_valueheader.htm new file mode 100644 index 0000000000..b9b26bd6a2 --- /dev/null +++ b/applications/cbi/src/view/cbi/tiny_valueheader.htm @@ -0,0 +1 @@ + <div class="cbi-value-field" id="cbi-<%=self.config.."-"..section.."-"..self.option%>"> diff --git a/applications/cbi/src/view/cbi/tsection.htm b/applications/cbi/src/view/cbi/tsection.htm new file mode 100644 index 0000000000..37b18b5d42 --- /dev/null +++ b/applications/cbi/src/view/cbi/tsection.htm @@ -0,0 +1,25 @@ + <div class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>"> + <h2><%=self.title%></h2> + <div class="cbi-section-descr"><%=self.description%></div> +<% for i, k in ipairs(self:cfgsections()) do%> + <% if self.addremove then %><div class="cbi-section-remove right"> + <input type="submit" name="cbi.rts.<%=self.config%>.<%=k%>" value="<%:cbi_del Eintrag entfernen%>" /> + </div><% end %> + <% if not self.anonymous then %><h3><%=k%></h3><% end %> +<% section = k %> +<div class="cbi-section-node" id="cbi-<%=self.config%>-<%=section%>"> +<%+cbi/ucisection%> +</div> +<br /> +<% end %> +<% if self.addremove then %> + <div class="cbi-section-create"> + <% if self.anonymous then %> + <input type="submit" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>" value="<%:cbi_add Eintrag hinzufügen%>" /> + <% else %> + <input type="text" class="cbi-section-create-name" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>" /> + <input type="submit" value="<%:cbi_add Eintrag hinzufügen%>" /> + <% end %><% if self.err_invalid then %><div class="cbi-error"><%:cbi_invalid Fehler: Ungültige Eingabe%></div><% end %> + </div> +<% end %> + </div> diff --git a/applications/cbi/src/view/cbi/ucisection.htm b/applications/cbi/src/view/cbi/ucisection.htm new file mode 100644 index 0000000000..0abc37e7c6 --- /dev/null +++ b/applications/cbi/src/view/cbi/ucisection.htm @@ -0,0 +1,20 @@ +<% self:render_children(section, scope or {}) %> + <% if #self.optionals[section] > 0 or self.dynamic then %> + <div class="cbi-optionals"> + <% if self.dynamic then %> + <input type="text" name="cbi.opt.<%=self.config%>.<%=section%>" /> + <% else %> + <select name="cbi.opt.<%=self.config%>.<%=section%>"> + <option><%:cbi_addopt -- Feld --%></option> + <% for key, val in pairs(self.optionals[section]) do %> + <option id="cbi-<%=self.config.."-"..section.."-"..val.option%>" value="<%=val.option%>"><%=val.title%></option> + <% end %> + </select> + <script type="text/javascript"><% for key, val in pairs(self.optionals[section]) do %> + <% if #val.deps > 0 then %><% for j, d in ipairs(val.deps) do %>cbi_d_add("cbi-<%=self.config.."-"..section.."-"..val.option%>", "cbid.<%=self.config.."."..section.."."..d.field%>", "<%=d.value%>"); + <% end %><% end %> + <% end %></script> + <% end %> + <input type="submit" value="<%:add hinzufügen%>" /> + </div> + <% end %>
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/value.htm b/applications/cbi/src/view/cbi/value.htm new file mode 100644 index 0000000000..31bf38f77c --- /dev/null +++ b/applications/cbi/src/view/cbi/value.htm @@ -0,0 +1,3 @@ +<%+cbi/valueheader%> + <input type="text" onchange="cbi_d_update(this.id)" <% if self.size then %>size="<%=self.size%>" <% end %><% if self.maxlength then %>maxlength="<%=self.maxlength%>" <% end %>name="cbid.<%=self.config.."."..section.."."..self.option%>" id="cbid.<%=self.config.."."..section.."."..self.option%>" value="<%=self:cfgvalue(section)%>" /> +<%+cbi/valuefooter%> diff --git a/applications/cbi/src/view/cbi/valuefooter.htm b/applications/cbi/src/view/cbi/valuefooter.htm new file mode 100644 index 0000000000..bc9d1b127a --- /dev/null +++ b/applications/cbi/src/view/cbi/valuefooter.htm @@ -0,0 +1,5 @@ +<% if valuefooter then + include(valuefooter) +else + include("cbi/full_valuefooter") +end %>
\ No newline at end of file diff --git a/applications/cbi/src/view/cbi/valueheader.htm b/applications/cbi/src/view/cbi/valueheader.htm new file mode 100644 index 0000000000..8d9802f57f --- /dev/null +++ b/applications/cbi/src/view/cbi/valueheader.htm @@ -0,0 +1,5 @@ +<% if valueheader then + include(valueheader) +else + include("cbi/full_valueheader") +end %>
\ No newline at end of file |