luci-base: form.js: add support for dynamic default values

Many uci options have different implicit defaults, depending on the
values of other related options. A prominent example is the wireless
ieee80211w option which defaults to 2, 1 or 0 depending on whether
the encryption is set to wpa3-sae, wpa2/wpa2 mixed or any other mode
respectively.

Add the ability to specify a dictionary of default values and their
corresponding dependencies in order to be able to express such
configurations.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2019-09-19 15:40:57 +02:00
parent 4dfa657f77
commit 25e0b966c7

View file

@ -393,6 +393,39 @@ var CBIMap = CBINode.extend({
this.checkDepends(ev, (n || 10) + 1);
ui.tabs.updateTabs(ev, this.root);
},
isDependencySatisfied: function(depends, config_name, section_id) {
var def = false;
if (!Array.isArray(depends) || !depends.length)
return true;
for (var i = 0; i < depends.length; i++) {
var istat = true,
reverse = false;
for (var dep in depends[i]) {
if (dep == '!reverse') {
reverse = true;
}
else if (dep == '!default') {
def = true;
istat = false;
}
else {
var res = this.lookupOption(dep, section_id, config_name),
val = (res && res[0].isActive(res[1])) ? res[0].formvalue(res[1]) : null;
istat = (istat && isEqual(val, depends[i][dep]));
}
}
if (istat ^ reverse)
return true;
}
return def;
}
});
@ -675,37 +708,41 @@ var CBIAbstractValue = CBINode.extend({
},
checkDepends: function(section_id) {
var def = false;
var config_name = this.uciconfig || this.section.uciconfig || this.map.config,
active = this.map.isDependencySatisfied(this.deps, config_name, section_id);
if (!Array.isArray(this.deps) || !this.deps.length)
return true;
if (active)
this.updateDefaultValue(section_id);
for (var i = 0; i < this.deps.length; i++) {
var istat = true,
reverse = false;
return active;
},
for (var dep in this.deps[i]) {
if (dep == '!reverse') {
reverse = true;
}
else if (dep == '!default') {
def = true;
istat = false;
}
else {
var conf = this.uciconfig || this.section.uciconfig || this.map.config,
res = this.map.lookupOption(dep, section_id, conf),
val = (res && res[0].isActive(res[1])) ? res[0].formvalue(res[1]) : null;
updateDefaultValue: function(section_id) {
if (!L.isObject(this.defaults))
return;
istat = (istat && isEqual(val, this.deps[i][dep]));
}
var config_name = this.uciconfig || this.section.uciconfig || this.map.config,
default_defval = null, satisified_defval = null;
for (var value in this.defaults) {
if (!this.defaults[value] || this.defaults[value].length == 0) {
default_defval = value;
continue;
}
else if (this.map.isDependencySatisfied(this.defaults[value], config_name, section_id)) {
satisified_defval = value;
break;
}
if (istat ^ reverse)
return true;
}
return def;
if (satisified_defval == null)
satisified_defval = default_defval;
var node = this.map.findElement('id', this.cbid(section_id));
if (node && node.getAttribute('data-changed') != 'true' && satisified_defval != null)
L.dom.callClassMethod(node, 'setValue', satisified_defval);
this.default = satisified_defval;
},
cbid: function(section_id) {