diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-04-16 13:26:27 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-04-16 13:30:48 +0200 |
commit | 3f1d6870ff0b3a0e8e0fc1c63ae2fbee86775261 (patch) | |
tree | dc2ff981334ec7edfd198f8475f88dcb3bb732ca /docs/jsapi/luci.js.html | |
parent | 52486e5862926294fd6ea1b6db48bf1ae515d7a6 (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.html | 475 |
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 <= 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 & 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) && 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 < 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' && req.method == 'access')) + if (!LuCI.prototype.isObject(req) || + (req.object == 'session' && 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 < 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 < arguments.length; i++) + path += '/' + arguments[i]; + + var p = path.replace(/\/+$/, '').replace(/\/+/g, '/').split(/\//), + res = []; + + for (var i = 0; i < 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 && interval <= 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> |