From 3751379f1e9a4c215fb6eb898b4ccc67659b9ace Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Tue, 10 May 2022 21:51:50 +0700 Subject: initial commit 2 --- addons/web/static/src/js/services/ajax_service.js | 41 ++ addons/web/static/src/js/services/config.js | 122 ++++++ addons/web/static/src/js/services/core.js | 49 +++ addons/web/static/src/js/services/crash_manager.js | 412 +++++++++++++++++++++ .../src/js/services/crash_manager_service.js | 9 + addons/web/static/src/js/services/data_manager.js | 225 +++++++++++ .../src/js/services/local_storage_service.js | 20 + .../static/src/js/services/notification_service.js | 111 ++++++ .../web/static/src/js/services/report_service.js | 35 ++ addons/web/static/src/js/services/session.js | 12 + .../src/js/services/session_storage_service.js | 20 + 11 files changed, 1056 insertions(+) create mode 100644 addons/web/static/src/js/services/ajax_service.js create mode 100644 addons/web/static/src/js/services/config.js create mode 100644 addons/web/static/src/js/services/core.js create mode 100644 addons/web/static/src/js/services/crash_manager.js create mode 100644 addons/web/static/src/js/services/crash_manager_service.js create mode 100644 addons/web/static/src/js/services/data_manager.js create mode 100644 addons/web/static/src/js/services/local_storage_service.js create mode 100644 addons/web/static/src/js/services/notification_service.js create mode 100644 addons/web/static/src/js/services/report_service.js create mode 100644 addons/web/static/src/js/services/session.js create mode 100644 addons/web/static/src/js/services/session_storage_service.js (limited to 'addons/web/static/src/js/services') diff --git a/addons/web/static/src/js/services/ajax_service.js b/addons/web/static/src/js/services/ajax_service.js new file mode 100644 index 00000000..da3d436c --- /dev/null +++ b/addons/web/static/src/js/services/ajax_service.js @@ -0,0 +1,41 @@ +odoo.define('web.AjaxService', function (require) { +"use strict"; + +var AbstractService = require('web.AbstractService'); +var ajax = require('web.ajax'); +var core = require('web.core'); +var session = require('web.session'); + +var AjaxService = AbstractService.extend({ + /** + * @param {Object} libs - @see ajax.loadLibs + * @param {Object} [context] - @see ajax.loadLibs + * @param {Object} [tplRoute] - @see ajax.loadLibs + */ + loadLibs: function (libs, context, tplRoute) { + return ajax.loadLibs(libs, context, tplRoute); + }, + rpc: function (route, args, options, target) { + var rpcPromise; + var promise = new Promise(function (resolve, reject) { + rpcPromise = session.rpc(route, args, options); + rpcPromise.then(function (result) { + if (!target.isDestroyed()) { + resolve(result); + } + }).guardedCatch(function (reason) { + if (!target.isDestroyed()) { + reject(reason); + } + }); + }); + promise.abort = rpcPromise.abort.bind(rpcPromise); + return promise; + }, +}); + +core.serviceRegistry.add('ajax', AjaxService); + +return AjaxService; + +}); diff --git a/addons/web/static/src/js/services/config.js b/addons/web/static/src/js/services/config.js new file mode 100644 index 00000000..6c576c35 --- /dev/null +++ b/addons/web/static/src/js/services/config.js @@ -0,0 +1,122 @@ +odoo.define('web.config', function (require) { +"use strict"; + +const Bus = require('web.Bus'); + +const bus = new Bus(); + +/** + * This module contains all the (mostly) static 'environmental' information. + * This is often necessary to allow the rest of the web client to properly + * render itself. + * + * Note that many information currently stored in session should be moved to + * this file someday. + */ + +var config = { + device: { + /** + * bus to use in order to be able to handle device config related events + * - 'size_changed' : triggered when window size is + * corresponding to a new bootstrap breakpoint. The new size_class + * is provided. + */ + bus: bus, + /** + * touch is a boolean, true if the device supports touch interaction + * + * @type Boolean + */ + touch: 'ontouchstart' in window || 'onmsgesturechange' in window, + /** + * size_class is an integer: 0, 1, 2, 3 or 4, depending on the (current) + * size of the device. This is a dynamic property, updated whenever the + * browser is resized + * + * @type Number + */ + size_class: null, + /** + * A frequent use case is to have a different render in 'mobile' mode, + * meaning when the screen is small. This flag (boolean) is true when + * the size is XS/VSM/SM. It is also updated dynamically. + * + * @type Boolean + */ + isMobile: null, + /** + * Mobile device detection using userAgent. + * This flag doesn't depend on the size/resolution of the screen. + * It targets mobile devices which suggests that there is a virtual keyboard. + * + * @return {boolean} + */ + isMobileDevice: navigator.userAgent.match(/Android/i) || + navigator.userAgent.match(/webOS/i) || + navigator.userAgent.match(/iPhone/i) || + navigator.userAgent.match(/iPad/i) || + navigator.userAgent.match(/iPod/i) || + navigator.userAgent.match(/BlackBerry/i) || + navigator.userAgent.match(/Windows Phone/i), + /** + * Mapping between the numbers 0,1,2,3,4,5,6 and some descriptions + */ + SIZES: { XS: 0, VSM: 1, SM: 2, MD: 3, LG: 4, XL: 5, XXL: 6 }, + }, + /** + * States whether the current environment is in debug or not. + * + * @param debugMode the debug mode to check, empty for simple debug mode + * @returns {boolean} + */ + isDebug: function (debugMode) { + if (debugMode) { + return odoo.debug && odoo.debug.indexOf(debugMode) !== -1; + } + return odoo.debug; + }, +}; + + +var medias = [ + window.matchMedia('(max-width: 474px)'), + window.matchMedia('(min-width: 475px) and (max-width: 575px)'), + window.matchMedia('(min-width: 576px) and (max-width: 767px)'), + window.matchMedia('(min-width: 768px) and (max-width: 991px)'), + window.matchMedia('(min-width: 992px) and (max-width: 1199px)'), + window.matchMedia('(min-width: 1200px) and (max-width: 1533px)'), + window.matchMedia('(min-width: 1534px)'), +]; + +/** + * Return the current size class + * + * @returns {integer} a number between 0 and 5, included + */ +function _getSizeClass() { + for (var i = 0 ; i < medias.length ; i++) { + if (medias[i].matches) { + return i; + } + } +} +/** + * Update the size dependant properties in the config object. This method + * should be called every time the size class changes. + */ +function _updateSizeProps() { + var sc = _getSizeClass(); + if (sc !== config.device.size_class) { + config.device.size_class = sc; + config.device.isMobile = config.device.size_class <= config.device.SIZES.SM; + config.device.bus.trigger('size_changed', config.device.size_class); + } +} + +_.invoke(medias, 'addListener', _updateSizeProps); +_updateSizeProps(); + +return config; + +}); diff --git a/addons/web/static/src/js/services/core.js b/addons/web/static/src/js/services/core.js new file mode 100644 index 00000000..1d4619f6 --- /dev/null +++ b/addons/web/static/src/js/services/core.js @@ -0,0 +1,49 @@ +odoo.define('web.core', function (require) { +"use strict"; + +var Bus = require('web.Bus'); +var config = require('web.config'); +var Class = require('web.Class'); +var QWeb = require('web.QWeb'); +var Registry = require('web.Registry'); +var translation = require('web.translation'); + +/** + * Whether the client is currently in "debug" mode + * + * @type Boolean + */ +var bus = new Bus(); + +_.each('click,dblclick,keydown,keypress,keyup'.split(','), function (evtype) { + $('html').on(evtype, function (ev) { + bus.trigger(evtype, ev); + }); +}); +_.each('resize,scroll'.split(','), function (evtype) { + $(window).on(evtype, function (ev) { + bus.trigger(evtype, ev); + }); +}); + +return { + qweb: new QWeb(config.isDebug()), + + // core classes and functions + Class: Class, + bus: bus, + main_bus: new Bus(), + _t: translation._t, + _lt: translation._lt, + + // registries + action_registry: new Registry(), + crash_registry: new Registry(), + serviceRegistry: new Registry(), + /** + * @type {String} + */ + csrf_token: odoo.csrf_token, +}; + +}); diff --git a/addons/web/static/src/js/services/crash_manager.js b/addons/web/static/src/js/services/crash_manager.js new file mode 100644 index 00000000..abd40e93 --- /dev/null +++ b/addons/web/static/src/js/services/crash_manager.js @@ -0,0 +1,412 @@ +odoo.define('web.ErrorDialogRegistry', function (require) { +"use strict"; + +var Registry = require('web.Registry'); + +return new Registry(); +}); + +odoo.define('web.CrashManager', function (require) { +"use strict"; + +const AbstractService = require('web.AbstractService'); +var ajax = require('web.ajax'); +const BrowserDetection = require('web.BrowserDetection'); +var core = require('web.core'); +var Dialog = require('web.Dialog'); +var ErrorDialogRegistry = require('web.ErrorDialogRegistry'); +var Widget = require('web.Widget'); + +var _t = core._t; +var _lt = core._lt; + +// Register this eventlistener before qunit does. +// Some errors needs to be negated by the crash_manager. +window.addEventListener('unhandledrejection', ev => + core.bus.trigger('crash_manager_unhandledrejection', ev) +); + +let active = true; + +/** + * An extension of Dialog Widget to render the warnings and errors on the website. + * Extend it with your template of choice like ErrorDialog/WarningDialog + */ +var CrashManagerDialog = Dialog.extend({ + xmlDependencies: (Dialog.prototype.xmlDependencies || []).concat( + ['/web/static/src/xml/crash_manager.xml'] + ), + + /** + * @param {Object} error + * @param {string} error.message the message in Warning/Error Dialog + * @param {string} error.traceback the traceback in ErrorDialog + * + * @constructor + */ + init: function (parent, options, error) { + this._super.apply(this, [parent, options]); + this.message = error.message; + this.traceback = error.traceback; + core.bus.off('close_dialogs', this); + }, +}); + +var ErrorDialog = CrashManagerDialog.extend({ + template: 'CrashManager.error', +}); + +var WarningDialog = CrashManagerDialog.extend({ + template: 'CrashManager.warning', + + /** + * Sets size to medium by default. + * + * @override + */ + init: function (parent, options, error) { + this._super(parent, _.extend({ + size: 'medium', + }, options), error); + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Focuses the ok button. + * + * @override + */ + open: function () { + this._super({shouldFocusButtons: true}); + }, +}); + +var CrashManager = AbstractService.extend({ + init: function () { + var self = this; + active = true; + this.isConnected = true; + this.odooExceptionTitleMap = { + 'odoo.addons.base.models.ir_mail_server.MailDeliveryException': _lt("MailDeliveryException"), + 'odoo.exceptions.AccessDenied': _lt("Access Denied"), + 'odoo.exceptions.AccessError': _lt("Access Error"), + 'odoo.exceptions.MissingError': _lt("Missing Record"), + 'odoo.exceptions.UserError': _lt("User Error"), + 'odoo.exceptions.ValidationError': _lt("Validation Error"), + 'odoo.exceptions.Warning': _lt("Warning"), + }; + + this.browserDetection = new BrowserDetection(); + this._super.apply(this, arguments); + + // crash manager integration + core.bus.on('rpc_error', this, this.rpc_error); + window.onerror = function (message, file, line, col, error) { + // Scripts injected in DOM (eg: google API's js files) won't return a clean error on window.onerror. + // The browser will just give you a 'Script error.' as message and nothing else for security issue. + // To enable onerror to work properly with CORS file, you should: + // 1. add crossorigin="anonymous" to your