diff options
Diffstat (limited to 'addons/bus/static/src/js/web_client_bus.js')
| -rw-r--r-- | addons/bus/static/src/js/web_client_bus.js | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/addons/bus/static/src/js/web_client_bus.js b/addons/bus/static/src/js/web_client_bus.js new file mode 100644 index 00000000..6683b565 --- /dev/null +++ b/addons/bus/static/src/js/web_client_bus.js @@ -0,0 +1,109 @@ +odoo.define('bus.WebClient', function (require) { + "use strict"; + + const core = require('web.core'); + const WebClient = require('web.WebClient'); + + const _t = core._t; + + WebClient.include({ + + //---------------------------------------------------------------------- + // Public + //---------------------------------------------------------------------- + + /** + * Detects the presence of assets in DOM's HEAD + * + * @override + */ + async start() { + this._assetsChangedNotificationId = null; + this._assets = {}; + await this._super(...arguments); + }, + /** + * Assigns handler to bus notification + * + * @override + */ + show_application() { + const shown = this._super(...arguments); + document.querySelectorAll('*[data-asset-xmlid]').forEach(el => { + this._assets[el.getAttribute('data-asset-xmlid')] = el.getAttribute('data-asset-version'); + }); + this.call('bus_service', 'onNotification', this, this._onNotification); + this.call('bus_service', 'addChannel', 'bundle_changed'); + return shown; + }, + + //---------------------------------------------------------------------- + // Private + //---------------------------------------------------------------------- + + /** + * Displays one notification on user's screen when assets have changed + * + * @private + */ + _displayBundleChangedNotification() { + if (!this._assetsChangedNotificationId) { + // Wrap the notification inside a delay. + // The server may be overwhelmed with recomputing assets + // We wait until things settle down + clearTimeout(this._bundleNotifTimerID); + this._bundleNotifTimerID = setTimeout(() => { + this._assetsChangedNotificationId = this.call('notification', 'notify', { + title: _t('Refresh'), + message: _t('The page appears to be out of date.'), + sticky: true, + onClose: () => { + this._assetsChangedNotificationId = null; + }, + buttons: [{ + text: _t('Refresh'), + primary: true, + click: () => { + window.location.reload(true); + } + }], + }); + }, this._getBundleNotificationDelay()); + } + }, + /** + * Computes a random delay to avoid hammering the server + * when bundles change with all the users reloading + * at the same time + * + * @private + * @return {number} delay in milliseconds + */ + _getBundleNotificationDelay() { + return 10000 + Math.floor(Math.random()*50) * 1000; + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Reacts to bus's notification + * + * @private + * @param {Array} notifications: list of received notifications + */ + _onNotification(notifications) { + for (const notif of notifications) { + if (notif[0][1] === 'bundle_changed') { + const bundleXmlId = notif[1][0]; + const bundleVersion = notif[1][1]; + if (bundleXmlId in this._assets && bundleVersion !== this._assets[bundleXmlId]) { + this._displayBundleChangedNotification(); + break; + } + } + } + } + }); +}); |
