local k, node
for k, node in ipairs(self.children) do
node.last_child = (k == #self.children)
+ node.index = k
node:render(...)
end
end
Node.parse(self, ...)
- self:_run_hooks("on_save", "on_before_save")
- for i, config in ipairs(self.parsechain) do
- self.uci:save(config)
- end
- self:_run_hooks("on_after_save")
- if (not self.proceed and self.flow.autoapply) or luci.http.formvalue("cbi.apply") then
- self:_run_hooks("on_before_commit")
+ if self.save then
+ self:_run_hooks("on_save", "on_before_save")
+ local i, config
for i, config in ipairs(self.parsechain) do
- self.uci:commit(config)
+ self.uci:save(config)
+ end
+ self:_run_hooks("on_after_save")
+ if (not self.proceed and self.flow.autoapply) or luci.http.formvalue("cbi.apply") then
+ self:_run_hooks("on_before_commit")
+ if self.apply_on_parse == false then
+ for i, config in ipairs(self.parsechain) do
+ self.uci:commit(config)
+ end
+ end
+ self:_run_hooks("on_commit", "on_after_commit", "on_before_apply")
+ if self.apply_on_parse == true or self.apply_on_parse == false then
+ self.uci:apply(self.apply_on_parse)
+ self:_run_hooks("on_apply", "on_after_apply")
+ else
+ -- This is evaluated by the dispatcher and delegated to the
+ -- template which in turn fires XHR to perform the actual
+ -- apply actions.
+ self.apply_needed = true
+ end
- -- Refresh data because commit changes section names
- self.uci:load(config)
+ -- Reparse sections
+ Node.parse(self, true)
end
- self:_run_hooks("on_commit", "on_after_commit", "on_before_apply")
- if self.apply_on_parse then
- self.uci:apply(self.parsechain)
- self:_run_hooks("on_apply", "on_after_apply")
- else
- -- This is evaluated by the dispatcher and delegated to the
- -- template which in turn fires XHR to perform the actual
- -- apply actions.
- self.apply_needed = true
+ for i, config in ipairs(self.parsechain) do
+ self.uci:unload(config)
+ end
+ if type(self.commit_handler) == "function" then
+ self:commit_handler(self:submitstate())
end
-
- -- Reparse sections
- Node.parse(self, true)
- end
- for i, config in ipairs(self.parsechain) do
- self.uci:unload(config)
- end
- if type(self.commit_handler) == "function" then
- self:commit_handler(self:submitstate())
end
- if self.proceed then
+ if not self.save then
+ self.state = FORM_INVALID
+ elseif self.proceed then
self.state = FORM_PROCEED
elseif self.changed then
self.state = FORM_CHANGED
local k, node
for k, node in ipairs(self.tabs[tab].childs) do
node.last_child = (k == #self.tabs[tab].childs)
+ node.index = k
node:render(...)
end
end
if name then
-- Ignore if it already exists
if self:cfgvalue(name) then
- name = nil;
- end
-
- name = self:checkscope(name)
-
- if not name then
+ name = nil
self.err_invalid = true
- end
+ else
+ name = self:checkscope(name)
- if name and #name > 0 then
- created = self:create(name, origin) and name
- if not created then
- self.invalid_cts = true
+ if not name then
+ self.err_invalid = true
+ end
+
+ if name and #name > 0 then
+ created = self:create(name, origin) and name
+ if not created then
+ self.invalid_cts = true
+ end
end
end
end
local stval = RESORT_PREFIX .. self.config .. "." .. self.sectiontype
local order = self.map:formvalue(stval)
if order and #order > 0 then
- local sid
- local num = 0
+ local sids, sid = { }, nil
for sid in util.imatch(order) do
- self.map.uci:reorder(self.config, sid, num)
- num = num + 1
+ sids[#sids+1] = sid
+ end
+ if #sids > 0 then
+ self.map.uci:reorder(self.config, sids)
+ self.changed = true
end
- self.changed = (num > 0)
end
end
self.tag_reqerror = {}
self.tag_error = {}
self.deps = {}
- self.subdeps = {}
--self.cast = "string"
self.track_missing = false
deps = field
end
- table.insert(self.deps, {deps=deps, add=""})
+ table.insert(self.deps, deps)
+end
+
+-- Serialize dependencies
+function AbstractValue.deplist2json(self, section, deplist)
+ local deps, i, d = { }
+
+ if type(self.deps) == "table" then
+ for i, d in ipairs(deplist or self.deps) do
+ local a, k, v = { }
+ for k, v in pairs(d) do
+ if k:find("!", 1, true) then
+ a[k] = v
+ elseif k:find(".", 1, true) then
+ a['cbid.%s' % k] = v
+ else
+ a['cbid.%s.%s.%s' %{ self.config, section, k }] = v
+ end
+ end
+ deps[#deps+1] = a
+ end
+ end
+
+ return util.serialize_json(deps)
+end
+
+-- Serialize choices
+function AbstractValue.choices(self)
+ if type(self.keylist) == "table" and #self.keylist > 0 then
+ local i, k, v = nil, nil, {}
+ for i, k in ipairs(self.keylist) do
+ v[k] = self.vallist[i] or k
+ end
+ return v
+ end
+ return nil
end
-- Generates the unique CBID
self:add_error(section, "invalid", val_err)
end
+ if self.alias then
+ self.section.aliased = self.section.aliased or {}
+ self.section.aliased[section] = self.section.aliased[section] or {}
+ self.section.aliased[section][self.alias] = true
+ end
+
if fvalue and (self.forcewrite or not (fvalue == cvalue)) then
if self:write(section, fvalue) then
-- Push events
end
else -- Unset the UCI or error
if self.rmempty or self.optional then
- if self:remove(section) then
- -- Push events
- self.section.changed = true
- --luci.util.append(self.map.events, self.events)
+ if not self.alias or
+ not self.section.aliased or
+ not self.section.aliased[section] or
+ not self.section.aliased[section][self.alias]
+ then
+ if self:remove(section) then
+ -- Push events
+ self.section.changed = true
+ --luci.util.append(self.map.events, self.events)
+ end
end
elseif cvalue ~= fvalue and not novld then
-- trigger validator with nil value to get custom user error msg.
if self.tag_error[section] then
value = self:formvalue(section)
else
- value = self.map:get(section, self.option)
+ value = self.map:get(section, self.alias or self.option)
end
if not value then
-- Write to UCI
function AbstractValue.write(self, section, value)
- return self.map:set(section, self.option, value)
+ return self.map:set(section, self.alias or self.option, value)
end
-- Remove from UCI
function AbstractValue.remove(self, section)
- return self.map:del(section, self.option)
+ return self.map:del(section, self.alias or self.option)
end
AbstractValue.__init__(self, ...)
self.template = "cbi/lvalue"
- self.keylist = {}
- self.vallist = {}
self.size = 1
self.widget = "select"
+
+ self:reset_values()
end
function ListValue.reset_values(self)
self.keylist = {}
self.vallist = {}
+ self.deplist = {}
end
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
- self.subdeps[#self.subdeps + 1] = {add = "-"..key, deps=deps}
- end
+ table.insert(self.deplist, {...})
end
function ListValue.validate(self, val)
AbstractValue.__init__(self, ...)
self.template = "cbi/mvalue"
- self.keylist = {}
- self.vallist = {}
-
self.widget = "checkbox"
self.delimiter = " "
+
+ self:reset_values()
end
function MultiValue.render(self, ...)
function MultiValue.reset_values(self)
self.keylist = {}
self.vallist = {}
+ self.deplist = {}
end
function MultiValue.value(self, key, val)
AbstractValue.__init__(self, ...)
self.template = "cbi/dynlist"
self.cast = "table"
- self.keylist = {}
- self.vallist = {}
+ self:reset_values()
end
function DynamicList.reset_values(self)
end
+DropDown = class(MultiValue)
+
+function DropDown.__init__(self, ...)
+ ListValue.__init__(self, ...)
+ self.template = "cbi/dropdown"
+ self.delimiter = " "
+end
+
+
--[[
TextValue - A multi-line value
rows: Rows