summaryrefslogtreecommitdiffhomepage
path: root/docs/jsapi/luci.js.html
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2020-04-16 13:26:27 +0200
committerJo-Philipp Wich <jo@mein.io>2020-04-16 13:30:48 +0200
commit3f1d6870ff0b3a0e8e0fc1c63ae2fbee86775261 (patch)
treedc2ff981334ec7edfd198f8475f88dcb3bb732ca /docs/jsapi/luci.js.html
parent52486e5862926294fd6ea1b6db48bf1ae515d7a6 (diff)
docs: update js api docs
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'docs/jsapi/luci.js.html')
-rw-r--r--docs/jsapi/luci.js.html475
1 files changed, 380 insertions, 95 deletions
diff --git a/docs/jsapi/luci.js.html b/docs/jsapi/luci.js.html
index 33dab5716..4c146ef38 100644
--- a/docs/jsapi/luci.js.html
+++ b/docs/jsapi/luci.js.html
@@ -74,12 +74,16 @@
<li data-name="LuCI#error"><a href="LuCI.html#error">error</a></li>
+ <li data-name="LuCI#fspath"><a href="LuCI.html#fspath">fspath</a></li>
+
<li data-name="LuCI#get"><a href="LuCI.html#get">get</a></li>
<li data-name="LuCI#halt"><a href="LuCI.html#halt">halt</a></li>
<li data-name="LuCI#hasSystemFeature"><a href="LuCI.html#hasSystemFeature">hasSystemFeature</a></li>
+ <li data-name="LuCI#hasViewPermission"><a href="LuCI.html#hasViewPermission">hasViewPermission</a></li>
+
<li data-name="LuCI#isObject"><a href="LuCI.html#isObject">isObject</a></li>
<li data-name="LuCI#location"><a href="LuCI.html#location">location</a></li>
@@ -331,6 +335,8 @@
<li data-name="LuCI.form.AbstractValue##optional"><a href="LuCI.form.AbstractValue.html#optional">optional</a></li>
+ <li data-name="LuCI.form.AbstractValue##readonly"><a href="LuCI.form.AbstractValue.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.AbstractValue##rmempty"><a href="LuCI.form.AbstractValue.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.AbstractValue##uciconfig"><a href="LuCI.form.AbstractValue.html#uciconfig">uciconfig</a></li>
@@ -423,6 +429,8 @@
<li data-name="LuCI.form.ButtonValue#placeholder"><a href="LuCI.form.ButtonValue.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.ButtonValue#readonly"><a href="LuCI.form.ButtonValue.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.ButtonValue#rmempty"><a href="LuCI.form.ButtonValue.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.ButtonValue#uciconfig"><a href="LuCI.form.ButtonValue.html#uciconfig">uciconfig</a></li>
@@ -511,6 +519,8 @@
<li data-name="LuCI.form.DummyValue#placeholder"><a href="LuCI.form.DummyValue.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.DummyValue#readonly"><a href="LuCI.form.DummyValue.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.DummyValue#rmempty"><a href="LuCI.form.DummyValue.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.DummyValue#uciconfig"><a href="LuCI.form.DummyValue.html#uciconfig">uciconfig</a></li>
@@ -595,6 +605,8 @@
<li data-name="LuCI.form.DynamicList#placeholder"><a href="LuCI.form.DynamicList.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.DynamicList#readonly"><a href="LuCI.form.DynamicList.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.DynamicList#rmempty"><a href="LuCI.form.DynamicList.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.DynamicList#uciconfig"><a href="LuCI.form.DynamicList.html#uciconfig">uciconfig</a></li>
@@ -687,6 +699,8 @@
<li data-name="LuCI.form.FileUpload#placeholder"><a href="LuCI.form.FileUpload.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.FileUpload#readonly"><a href="LuCI.form.FileUpload.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.FileUpload#rmempty"><a href="LuCI.form.FileUpload.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.FileUpload#uciconfig"><a href="LuCI.form.FileUpload.html#uciconfig">uciconfig</a></li>
@@ -775,6 +789,8 @@
<li data-name="LuCI.form.FlagValue#placeholder"><a href="LuCI.form.FlagValue.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.FlagValue#readonly"><a href="LuCI.form.FlagValue.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.FlagValue#rmempty"><a href="LuCI.form.FlagValue.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.FlagValue#uciconfig"><a href="LuCI.form.FlagValue.html#uciconfig">uciconfig</a></li>
@@ -929,6 +945,8 @@
<li data-name="LuCI.form.HiddenValue#placeholder"><a href="LuCI.form.HiddenValue.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.HiddenValue#readonly"><a href="LuCI.form.HiddenValue.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.HiddenValue#rmempty"><a href="LuCI.form.HiddenValue.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.HiddenValue#uciconfig"><a href="LuCI.form.HiddenValue.html#uciconfig">uciconfig</a></li>
@@ -997,6 +1015,10 @@
</span>
<ul class="members itemMembers">
+ <span class="subtitle">Members</span>
+
+ <li data-name="LuCI.form.JSONMap#readonly"><a href="LuCI.form.JSONMap.html#readonly">readonly</a></li>
+
</ul>
<ul class="typedefs itemMembers">
@@ -1065,6 +1087,8 @@
<li data-name="LuCI.form.ListValue#placeholder"><a href="LuCI.form.ListValue.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.ListValue#readonly"><a href="LuCI.form.ListValue.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.ListValue#rmempty"><a href="LuCI.form.ListValue.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.ListValue#uciconfig"><a href="LuCI.form.ListValue.html#uciconfig">uciconfig</a></li>
@@ -1133,6 +1157,10 @@
</span>
<ul class="members itemMembers">
+ <span class="subtitle">Members</span>
+
+ <li data-name="LuCI.form.Map##readonly"><a href="LuCI.form.Map.html#readonly">readonly</a></li>
+
</ul>
<ul class="typedefs itemMembers">
@@ -1203,6 +1231,8 @@
<li data-name="LuCI.form.MultiValue#placeholder"><a href="LuCI.form.MultiValue.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.MultiValue#readonly"><a href="LuCI.form.MultiValue.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.MultiValue#rmempty"><a href="LuCI.form.MultiValue.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.MultiValue#uciconfig"><a href="LuCI.form.MultiValue.html#uciconfig">uciconfig</a></li>
@@ -1343,6 +1373,8 @@
<li data-name="LuCI.form.SectionValue#placeholder"><a href="LuCI.form.SectionValue.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.SectionValue#readonly"><a href="LuCI.form.SectionValue.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.SectionValue#rmempty"><a href="LuCI.form.SectionValue.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.SectionValue#uciconfig"><a href="LuCI.form.SectionValue.html#uciconfig">uciconfig</a></li>
@@ -1513,6 +1545,8 @@
<li data-name="LuCI.form.TextValue#placeholder"><a href="LuCI.form.TextValue.html#placeholder">placeholder</a></li>
+ <li data-name="LuCI.form.TextValue#readonly"><a href="LuCI.form.TextValue.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.TextValue#rmempty"><a href="LuCI.form.TextValue.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.TextValue#uciconfig"><a href="LuCI.form.TextValue.html#uciconfig">uciconfig</a></li>
@@ -1655,6 +1689,8 @@
<li data-name="LuCI.form.Value#optional"><a href="LuCI.form.Value.html#optional">optional</a></li>
+ <li data-name="LuCI.form.Value#readonly"><a href="LuCI.form.Value.html#readonly">readonly</a></li>
+
<li data-name="LuCI.form.Value#rmempty"><a href="LuCI.form.Value.html#rmempty">rmempty</a></li>
<li data-name="LuCI.form.Value#uciconfig"><a href="LuCI.form.Value.html#uciconfig">uciconfig</a></li>
@@ -2462,6 +2498,36 @@
</ul>
</li>
+ <li class="item" data-name="LuCI.session">
+ <span class="title">
+ <a href="LuCI.session.html">LuCI.session</a>
+
+ </span>
+ <ul class="members itemMembers">
+
+ </ul>
+ <ul class="typedefs itemMembers">
+
+ </ul>
+ <ul class="typedefs itemMembers">
+
+ </ul>
+ <ul class="methods itemMembers">
+
+ <span class="subtitle">Methods</span>
+
+ <li data-name="LuCI.session#getID"><a href="LuCI.session.html#getID">getID</a></li>
+
+ <li data-name="LuCI.session#getLocalData"><a href="LuCI.session.html#getLocalData">getLocalData</a></li>
+
+ <li data-name="LuCI.session#setLocalData"><a href="LuCI.session.html#setLocalData">setLocalData</a></li>
+
+ </ul>
+ <ul class="events itemMembers">
+
+ </ul>
+ </li>
+
<li class="item" data-name="LuCI.uci">
<span class="title">
<a href="LuCI.uci.html">LuCI.uci</a>
@@ -2974,6 +3040,38 @@
</ul>
</li>
+ <li class="item" data-name="LuCI.ui.menu">
+ <span class="title">
+ <a href="LuCI.ui.menu.html">LuCI.ui.menu</a>
+
+ </span>
+ <ul class="members itemMembers">
+
+ </ul>
+ <ul class="typedefs itemMembers">
+
+ <span class="subtitle">Typedefs</span>
+
+ <li data-name="LuCI.ui.menu.MenuNode"><a href="LuCI.ui.menu.html#.MenuNode">MenuNode</a></li>
+
+ </ul>
+ <ul class="typedefs itemMembers">
+
+ </ul>
+ <ul class="methods itemMembers">
+
+ <span class="subtitle">Methods</span>
+
+ <li data-name="LuCI.ui.menu#getChildren"><a href="LuCI.ui.menu.html#getChildren">getChildren</a></li>
+
+ <li data-name="LuCI.ui.menu#load"><a href="LuCI.ui.menu.html#load">load</a></li>
+
+ </ul>
+ <ul class="events itemMembers">
+
+ </ul>
+ </li>
+
<li class="item" data-name="LuCI.ui.Select">
<span class="title">
<a href="LuCI.ui.Select.html">LuCI.ui.Select</a>
@@ -3230,6 +3328,8 @@
(function(window, document, undefined) {
'use strict';
+ var env = {};
+
/* Object.assign polyfill for IE */
if (typeof Object.assign !== 'function') {
Object.defineProperty(Object, 'assign', {
@@ -4287,7 +4387,7 @@
*/
add: function(fn, interval) {
if (interval == null || interval &lt;= 0)
- interval = window.L ? window.L.env.pollinterval : null;
+ interval = env.pollinterval || null;
if (isNaN(interval) || typeof(fn) != 'function')
throw new TypeError('Invalid argument to LuCI.poll.add()');
@@ -4429,7 +4529,7 @@
* To import the class in views, use `'require dom'`, to import it in
* external JavaScript, use `L.require("dom").then(...)`.
*/
- var DOM = Class.singleton(/* @lends LuCI.dom.prototype */ {
+ var DOM = Class.singleton(/** @lends LuCI.dom.prototype */ {
__name__: 'LuCI.dom',
/**
@@ -4934,7 +5034,7 @@
*/
bindClassInstance: function(node, inst) {
if (!(inst instanceof Class))
- L.error('TypeError', 'Argument must be a class instance');
+ LuCI.prototype.error('TypeError', 'Argument must be a class instance');
return this.data(node, '_class', inst);
},
@@ -5042,6 +5142,101 @@
});
/**
+ * @class session
+ * @memberof LuCI
+ * @hideconstructor
+ * @classdesc
+ *
+ * The `session` class provides various session related functionality.
+ */
+ var Session = Class.singleton(/** @lends LuCI.session.prototype */ {
+ __name__: 'LuCI.session',
+
+ /**
+ * Retrieve the current session ID.
+ *
+ * @returns {string}
+ * Returns the current session ID.
+ */
+ getID: function() {
+ return env.sessionid || '00000000000000000000000000000000';
+ },
+
+ /**
+ * Retrieve data from the local session storage.
+ *
+ * @param {string} [key]
+ * The key to retrieve from the session data store. If omitted, all
+ * session data will be returned.
+ *
+ * @returns {*}
+ * Returns the stored session data or `null` if the given key wasn't
+ * found.
+ */
+ getLocalData: function(key) {
+ try {
+ var sid = this.getID(),
+ item = 'luci-session-store',
+ data = JSON.parse(window.sessionStorage.getItem(item));
+
+ if (!LuCI.prototype.isObject(data) || !data.hasOwnProperty(sid)) {
+ data = {};
+ data[sid] = {};
+ }
+
+ if (key != null)
+ return data[sid].hasOwnProperty(key) ? data[sid][key] : null;
+
+ return data[sid];
+ }
+ catch (e) {
+ return (key != null) ? null : {};
+ }
+ },
+
+ /**
+ * Set data in the local session storage.
+ *
+ * @param {string} key
+ * The key to set in the session data store.
+ *
+ * @param {*} value
+ * The value to store. It will be internally converted to JSON before
+ * being put in the session store.
+ *
+ * @returns {boolean}
+ * Returns `true` if the data could be stored or `false` on error.
+ */
+ setLocalData: function(key, value) {
+ if (key == null)
+ return false;
+
+ try {
+ var sid = this.getID(),
+ item = 'luci-session-store',
+ data = JSON.parse(window.sessionStorage.getItem(item));
+
+ if (!LuCI.prototype.isObject(data) || !data.hasOwnProperty(sid)) {
+ data = {};
+ data[sid] = {};
+ }
+
+ if (value != null)
+ data[sid][key] = value;
+ else
+ delete data[sid][key];
+
+ window.sessionStorage.setItem(item, JSON.stringify(data));
+
+ return true;
+ }
+ catch (e) {
+ return false;
+ }
+ }
+ });
+
+ /**
* @class view
* @memberof LuCI
* @hideconstructor
@@ -5050,7 +5245,7 @@
* The `view` class forms the basis of views and provides a standard
* set of methods to inherit from.
*/
- var View = Class.extend(/* @lends LuCI.view.prototype */ {
+ var View = Class.extend(/** @lends LuCI.view.prototype */ {
__name__: 'LuCI.view',
__init__: function() {
@@ -5059,13 +5254,13 @@
DOM.content(vp, E('div', { 'class': 'spinning' }, _('Loading view…')));
return Promise.resolve(this.load())
- .then(L.bind(this.render, this))
- .then(L.bind(function(nodes) {
+ .then(LuCI.prototype.bind(this.render, this))
+ .then(LuCI.prototype.bind(function(nodes) {
var vp = document.getElementById('view');
DOM.content(vp, nodes);
DOM.append(vp, this.addFooter());
- }, this)).catch(L.error);
+ }, this)).catch(LuCI.prototype.error);
},
/**
@@ -5199,7 +5394,7 @@
*/
handleSaveApply: function(ev, mode) {
return this.handleSave(ev).then(function() {
- L.ui.changes.apply(mode == '0');
+ classes.ui.changes.apply(mode == '0');
});
},
@@ -5269,9 +5464,25 @@
* methods are overwritten with `null`.
*/
addFooter: function() {
- var footer = E([]);
+ var footer = E([]),
+ vp = document.getElementById('view'),
+ hasmap = false,
+ readonly = true;
+
+ vp.querySelectorAll('.cbi-map').forEach(function(map) {
+ var m = DOM.findClassInstance(map);
+ if (m) {
+ hasmap = true;
+
+ if (!m.readonly)
+ readonly = false;
+ }
+ });
+
+ if (!hasmap)
+ readonly = !LuCI.prototype.hasViewPermission();
- var saveApplyBtn = this.handleSaveApply ? new L.ui.ComboButton('0', {
+ var saveApplyBtn = this.handleSaveApply ? new classes.ui.ComboButton('0', {
0: [ _('Save &amp; Apply') ],
1: [ _('Apply unchecked') ]
}, {
@@ -5279,7 +5490,8 @@
0: 'btn cbi-button cbi-button-apply important',
1: 'btn cbi-button cbi-button-negative important'
},
- click: L.ui.createHandlerFn(this, 'handleSaveApply')
+ click: classes.ui.createHandlerFn(this, 'handleSaveApply'),
+ disabled: readonly || null
}).render() : E([]);
if (this.handleSaveApply || this.handleSave || this.handleReset) {
@@ -5287,11 +5499,13 @@
saveApplyBtn, ' ',
this.handleSave ? E('button', {
'class': 'cbi-button cbi-button-save',
- 'click': L.ui.createHandlerFn(this, 'handleSave')
+ 'click': classes.ui.createHandlerFn(this, 'handleSave'),
+ 'disabled': readonly || null
}, [ _('Save') ]) : '', ' ',
this.handleReset ? E('button', {
'class': 'cbi-button cbi-button-reset',
- 'click': L.ui.createHandlerFn(this, 'handleReset')
+ 'click': classes.ui.createHandlerFn(this, 'handleReset'),
+ 'disabled': readonly || null
}, [ _('Reset') ]) : ''
]));
}
@@ -5305,7 +5519,8 @@
domParser = null,
originalCBIInit = null,
rpcBaseURL = null,
- sysFeatures = null;
+ sysFeatures = null,
+ preloadClasses = null;
/* "preload" builtin classes to make the available via require */
var classes = {
@@ -5313,41 +5528,30 @@
dom: DOM,
poll: Poll,
request: Request,
+ session: Session,
view: View
};
var LuCI = Class.extend(/** @lends LuCI.prototype */ {
__name__: 'LuCI',
- __init__: function(env) {
+ __init__: function(setenv) {
document.querySelectorAll('script[src*="/luci.js"]').forEach(function(s) {
- if (env.base_url == null || env.base_url == '') {
+ if (setenv.base_url == null || setenv.base_url == '') {
var m = (s.getAttribute('src') || '').match(/^(.*)\/luci\.js(?:\?v=([^?]+))?$/);
if (m) {
- env.base_url = m[1];
- env.resource_version = m[2];
+ setenv.base_url = m[1];
+ setenv.resource_version = m[2];
}
}
});
- if (env.base_url == null)
+ if (setenv.base_url == null)
this.error('InternalError', 'Cannot find url of luci.js');
- env.cgi_base = env.scriptname.replace(/\/[^\/]+$/, '');
-
- Object.assign(this.env, env);
+ setenv.cgi_base = setenv.scriptname.replace(/\/[^\/]+$/, '');
- document.addEventListener('poll-start', function(ev) {
- document.querySelectorAll('[id^="xhr_poll_status"]').forEach(function(e) {
- e.style.display = (e.id == 'xhr_poll_status_off') ? 'none' : '';
- });
- });
-
- document.addEventListener('poll-stop', function(ev) {
- document.querySelectorAll('[id^="xhr_poll_status"]').forEach(function(e) {
- e.style.display = (e.id == 'xhr_poll_status_on') ? 'none' : '';
- });
- });
+ Object.assign(env, setenv);
var domReady = new Promise(function(resolveFn, rejectFn) {
document.addEventListener('DOMContentLoaded', resolveFn);
@@ -5457,12 +5661,13 @@
*/
error: function(type, fmt /*, ...*/) {
try {
- L.raise.apply(L, Array.prototype.slice.call(arguments));
+ LuCI.prototype.raise.apply(LuCI.prototype,
+ Array.prototype.slice.call(arguments));
}
catch (e) {
if (!e.reported) {
- if (L.ui)
- L.ui.addNotification(e.name || _('Runtime error'),
+ if (classes.ui)
+ classes.ui.addNotification(e.name || _('Runtime error'),
E('pre', {}, e.message), 'danger');
else
DOM.content(document.querySelector('#maincontent'),
@@ -5541,19 +5746,19 @@
if (classes[name] != null) {
/* Circular dependency */
if (from.indexOf(name) != -1)
- L.raise('DependencyError',
+ LuCI.prototype.raise('DependencyError',
'Circular dependency: class "%s" depends on "%s"',
name, from.join('" which depends on "'));
return Promise.resolve(classes[name]);
}
- url = '%s/%s.js%s'.format(L.env.base_url, name.replace(/\./g, '/'), (L.env.resource_version ? '?v=' + L.env.resource_version : ''));
+ url = '%s/%s.js%s'.format(env.base_url, name.replace(/\./g, '/'), (env.resource_version ? '?v=' + env.resource_version : ''));
from = [ name ].concat(from);
var compileClass = function(res) {
if (!res.ok)
- L.raise('NetworkError',
+ LuCI.prototype.raise('NetworkError',
'HTTP error %d while loading class file "%s"', res.status, url);
var source = res.text(),
@@ -5578,7 +5783,7 @@
if (m) {
var dep = m[1], as = m[2] || dep.replace(/[^a-zA-Z0-9_]/g, '_');
- depends.push(L.require(dep, from));
+ depends.push(LuCI.prototype.require(dep, from));
args += ', ' + as;
}
else if (!strictmatch.exec(s)) {
@@ -5604,7 +5809,7 @@
.format(args, source, res.url));
}
catch (error) {
- L.raise('SyntaxError', '%s\n in %s:%s',
+ LuCI.prototype.raise('SyntaxError', '%s\n in %s:%s',
error.message, res.url, error.lineNumber || '?');
}
@@ -5612,7 +5817,7 @@
_class = _factory.apply(_factory, [window, document, L].concat(instances));
if (!Class.isSubclass(_class))
- L.error('TypeError', '"%s" factory yields invalid constructor', name);
+ LuCI.prototype.error('TypeError', '"%s" factory yields invalid constructor', name);
if (_class.displayName == 'AnonymousClass')
_class.displayName = toCamelCase(name + 'Class');
@@ -5641,26 +5846,18 @@
/* DOM setup */
probeRPCBaseURL: function() {
- if (rpcBaseURL == null) {
- try {
- rpcBaseURL = window.sessionStorage.getItem('rpcBaseURL');
- }
- catch (e) { }
- }
+ if (rpcBaseURL == null)
+ rpcBaseURL = Session.getLocalData('rpcBaseURL');
if (rpcBaseURL == null) {
var rpcFallbackURL = this.url('admin/ubus');
- rpcBaseURL = Request.get(this.env.ubuspath).then(function(res) {
- return (rpcBaseURL = (res.status == 400) ? L.env.ubuspath : rpcFallbackURL);
+ rpcBaseURL = Request.get(env.ubuspath).then(function(res) {
+ return (rpcBaseURL = (res.status == 400) ? env.ubuspath : rpcFallbackURL);
}, function() {
return (rpcBaseURL = rpcFallbackURL);
}).then(function(url) {
- try {
- window.sessionStorage.setItem('rpcBaseURL', url);
- }
- catch (e) { }
-
+ Session.setLocalData('rpcBaseURL', url);
return url;
});
}
@@ -5669,17 +5866,8 @@
},
probeSystemFeatures: function() {
- var sessionid = classes.rpc.getSessionID();
-
- if (sysFeatures == null) {
- try {
- var data = JSON.parse(window.sessionStorage.getItem('sysFeatures'));
-
- if (this.isObject(data) &amp;&amp; this.isObject(data[sessionid]))
- sysFeatures = data[sessionid];
- }
- catch (e) {}
- }
+ if (sysFeatures == null)
+ sysFeatures = Session.getLocalData('features');
if (!this.isObject(sysFeatures)) {
sysFeatures = classes.rpc.declare({
@@ -5687,14 +5875,7 @@
method: 'getFeatures',
expect: { '': {} }
})().then(function(features) {
- try {
- var data = {};
- data[sessionid] = features;
-
- window.sessionStorage.setItem('sysFeatures', JSON.stringify(data));
- }
- catch (e) {}
-
+ Session.setLocalData('features', features);
sysFeatures = features;
return features;
@@ -5704,6 +5885,39 @@
return Promise.resolve(sysFeatures);
},
+ probePreloadClasses: function() {
+ if (preloadClasses == null)
+ preloadClasses = Session.getLocalData('preload');
+
+ if (!Array.isArray(preloadClasses)) {
+ preloadClasses = this.resolveDefault(classes.rpc.declare({
+ object: 'file',
+ method: 'list',
+ params: [ 'path' ],
+ expect: { 'entries': [] }
+ })(this.fspath(this.resource('preload'))), []).then(function(entries) {
+ var classes = [];
+
+ for (var i = 0; i &lt; entries.length; i++) {
+ if (entries[i].type != 'file')
+ continue;
+
+ var m = entries[i].name.match(/(.+)\.js$/);
+
+ if (m)
+ classes.push('preload.%s'.format(m[1]));
+ }
+
+ Session.setLocalData('preload', classes);
+ preloadClasses = classes;
+
+ return classes;
+ });
+ }
+
+ return Promise.resolve(preloadClasses);
+ },
+
/**
* Test whether a particular system feature is available, such as
* hostapd SAE support or an installed firewall. The features are
@@ -5742,7 +5956,7 @@
notifySessionExpiry: function() {
Poll.stop();
- L.ui.showModal(_('Session expired'), [
+ classes.ui.showModal(_('Session expired'), [
E('div', { class: 'alert-message warning' },
_('A new login is required since the authentication session expired.')),
E('div', { class: 'right' },
@@ -5755,7 +5969,7 @@
}, _('To login…')))
]);
- L.raise('SessionError', 'Login session is expired');
+ LuCI.prototype.raise('SessionError', 'Login session is expired');
},
/* private */
@@ -5769,10 +5983,13 @@
rpcClass.setBaseURL(rpcBaseURL);
rpcClass.addInterceptor(function(msg, req) {
- if (!L.isObject(msg) || !L.isObject(msg.error) || msg.error.code != -32002)
+ if (!LuCI.prototype.isObject(msg) ||
+ !LuCI.prototype.isObject(msg.error) ||
+ msg.error.code != -32002)
return;
- if (!L.isObject(req) || (req.object == 'session' &amp;&amp; req.method == 'access'))
+ if (!LuCI.prototype.isObject(req) ||
+ (req.object == 'session' &amp;&amp; req.method == 'access'))
return;
return rpcClass.declare({
@@ -5780,7 +5997,7 @@
'method': 'access',
'params': [ 'scope', 'object', 'function' ],
'expect': { access: true }
- })('uci', 'luci', 'read').catch(L.notifySessionExpiry);
+ })('uci', 'luci', 'read').catch(LuCI.prototype.notifySessionExpiry);
});
Request.addInterceptor(function(res) {
@@ -5792,10 +6009,31 @@
if (!isDenied)
return;
- L.notifySessionExpiry();
+ LuCI.prototype.notifySessionExpiry();
+ });
+
+ document.addEventListener('poll-start', function(ev) {
+ uiClass.showIndicator('poll-status', _('Refreshing'), function(ev) {
+ Request.poll.active() ? Request.poll.stop() : Request.poll.start();
+ });
+ });
+
+ document.addEventListener('poll-stop', function(ev) {
+ uiClass.showIndicator('poll-status', _('Paused'), null, 'inactive');
});
- return this.probeSystemFeatures().finally(this.initDOM);
+ return Promise.all([
+ this.probeSystemFeatures(),
+ this.probePreloadClasses()
+ ]).finally(LuCI.prototype.bind(function() {
+ var tasks = [];
+
+ if (Array.isArray(preloadClasses))
+ for (var i = 0; i &lt; preloadClasses.length; i++)
+ tasks.push(this.require(preloadClasses[i]));
+
+ return Promise.all(tasks);
+ }, this)).finally(this.initDOM);
},
/* private */
@@ -5812,7 +6050,38 @@
* @instance
* @memberof LuCI
*/
- env: {},
+ env: env,
+
+ /**
+ * Construct an absolute filesystem path relative to the server
+ * document root.
+ *
+ * @instance
+ * @memberof LuCI
+ *
+ * @param {...string} [parts]
+ * An array of parts to join into a path.
+ *
+ * @return {string}
+ * Return the joined path.
+ */
+ fspath: function(/* ... */) {
+ var path = env.documentroot;
+
+ for (var i = 0; i &lt; arguments.length; i++)
+ path += '/' + arguments[i];
+
+ var p = path.replace(/\/+$/, '').replace(/\/+/g, '/').split(/\//),
+ res = [];
+
+ for (var i = 0; i &lt; p.length; i++)
+ if (p[i] == '..')
+ res.pop();
+ else if (p[i] != '.')
+ res.push(p[i]);
+
+ return res.join('/');
+ },
/**
* Construct a relative URL path from the given prefix and parts.
@@ -5866,7 +6135,7 @@
* Returns the resulting URL path.
*/
url: function() {
- return this.path(this.env.scriptname, arguments);
+ return this.path(env.scriptname, arguments);
},
/**
@@ -5888,7 +6157,7 @@
* Returns the resulting URL path.
*/
resource: function() {
- return this.path(this.env.resource, arguments);
+ return this.path(env.resource, arguments);
},
/**
@@ -5910,7 +6179,7 @@
* Returns the resulting URL path.
*/
media: function() {
- return this.path(this.env.media, arguments);
+ return this.path(env.media, arguments);
},
/**
@@ -5923,7 +6192,7 @@
* Returns the URL path to the current view.
*/
location: function() {
- return this.path(this.env.scriptname, this.env.requestpath);
+ return this.path(env.scriptname, env.requestpath);
},
@@ -6167,9 +6436,9 @@
*/
poll: function(interval, url, args, cb, post) {
if (interval !== null &amp;&amp; interval &lt;= 0)
- interval = this.env.pollinterval;
+ interval = env.pollinterval;
- var data = post ? { token: this.env.token } : null,
+ var data = post ? { token: env.token } : null,
method = post ? 'POST' : 'GET';
if (!/^(?:\/|\S+:\/\/)/.test(url))
@@ -6191,6 +6460,22 @@
},
/**
+ * Check whether a view has sufficient permissions.
+ *
+ * @return {boolean|null}
+ * Returns `null` if the current session has no permission at all to
+ * load resources required by the view. Returns `false` if readonly
+ * permissions are granted or `true` if at least one required ACL
+ * group is granted with write permissions.
+ */
+ hasViewPermission: function() {
+ if (!this.isObject(env.nodespec) || !env.nodespec.satisfied)
+ return null;
+
+ return !env.nodespec.readonly;
+ },
+
+ /**
* Deprecated wrapper around {@link LuCI.poll.remove Poll.remove()}.
*
* @deprecated
@@ -6333,7 +6618,7 @@
*/
get: function(url, data, callback, timeout) {
this.active = true;
- L.get(url, data, this._response.bind(this, callback), timeout);
+ LuCI.prototype.get(url, data, this._response.bind(this, callback), timeout);
},
/**
@@ -6360,7 +6645,7 @@
*/
post: function(url, data, callback, timeout) {
this.active = true;
- L.post(url, data, this._response.bind(this, callback), timeout);
+ LuCI.prototype.post(url, data, this._response.bind(this, callback), timeout);
},
/**
@@ -6414,12 +6699,12 @@
* Throws an `InternalError` with the message `Not implemented`
* when invoked.
*/
- send_form: function() { L.error('InternalError', 'Not implemented') },
+ send_form: function() { LuCI.prototype.error('InternalError', 'Not implemented') },
});
- XHR.get = function() { return window.L.get.apply(window.L, arguments) };
- XHR.post = function() { return window.L.post.apply(window.L, arguments) };
- XHR.poll = function() { return window.L.poll.apply(window.L, arguments) };
+ XHR.get = function() { return LuCI.prototype.get.apply(LuCI.prototype, arguments) };
+ XHR.post = function() { return LuCI.prototype.post.apply(LuCI.prototype, arguments) };
+ XHR.poll = function() { return LuCI.prototype.poll.apply(LuCI.prototype, arguments) };
XHR.stop = Request.poll.remove.bind(Request.poll);
XHR.halt = Request.poll.stop.bind(Request.poll);
XHR.run = Request.poll.start.bind(Request.poll);
@@ -6440,7 +6725,7 @@
<footer>
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Tue Apr 07 2020 16:33:40 GMT+0200 (Central European Summer Time)
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Thu Apr 16 2020 13:30:42 GMT+0200 (Central European Summer Time)
</footer>
</div>
</div>