diff --git a/addons/test_website/static/tests/tours/error_views.js b/addons/test_website/static/tests/tours/error_views.js index de6f69b68f7..b0a7b1422a4 100644 --- a/addons/test_website/static/tests/tours/error_views.js +++ b/addons/test_website/static/tests/tours/error_views.js @@ -49,8 +49,8 @@ tour.register('test_error_website', { trigger: 'a[href="/test_internal_error_json"]', }, { content: "rpc error 500 modal is an ErrorDialog", - extra_trigger: 'div.o_dialog_error.modal-body div.alert.alert-warning', - trigger: 'button.btn.btn-primary[type="button"]', + extra_trigger: 'div.o_dialog_error.modal-content div.alert.alert-warning', + trigger: '.modal-footer button.btn.btn-primary', }, // HTTP ERROR { diff --git a/addons/web/__manifest__.py b/addons/web/__manifest__.py index 3147f685333..0e644190f16 100644 --- a/addons/web/__manifest__.py +++ b/addons/web/__manifest__.py @@ -205,6 +205,7 @@ This module provides the core of the Odoo Web Client. # TODO: split debug files correctly when converting frontend debug # manager so we don't need action-service and stuff ('remove', 'web/static/src/core/debug/**/*'), + 'web/static/src/public/error_notifications.js', 'web/static/src/legacy/scss/base_frontend.scss', 'web/static/src/legacy/scss/lazyloader.scss', @@ -219,6 +220,8 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/js/public/public_root.js', 'web/static/src/legacy/js/public/public_root_instance.js', 'web/static/src/legacy/js/public/public_widget.js', + 'web/static/src/legacy/legacy_promise_error_handler.js', + 'web/static/src/legacy/legacy_rpc_error_handler.js', ('include', 'web.frontend_legacy'), ], diff --git a/addons/web/static/src/core/errors/error_dialogs.js b/addons/web/static/src/core/errors/error_dialogs.js index 5a3fb213b2f..a249335f66b 100644 --- a/addons/web/static/src/core/errors/error_dialogs.js +++ b/addons/web/static/src/core/errors/error_dialogs.js @@ -10,13 +10,19 @@ import { capitalize } from "../utils/strings"; const { hooks } = owl; const { useState } = hooks; -const odooExceptionTitleMap = new Map(); - -odooExceptionTitleMap.set("odoo.exceptions.AccessDenied", _lt("Access Denied")); -odooExceptionTitleMap.set("odoo.exceptions.AccessError", _lt("Access Error")); -odooExceptionTitleMap.set("odoo.exceptions.MissingError", _lt("Missing Record")); -odooExceptionTitleMap.set("odoo.exceptions.UserError", _lt("User Error")); -odooExceptionTitleMap.set("odoo.exceptions.ValidationError", _lt("Validation Error")); +export const odooExceptionTitleMap = new Map( + Object.entries({ + "odoo.addons.base.models.ir_mail_server.MailDeliveryException": _lt( + "MailDeliveryException" + ), + "odoo.exceptions.AccessDenied": _lt("Access Denied"), + "odoo.exceptions.MissingError": _lt("Missing Record"), + "odoo.exceptions.UserError": _lt("User Error"), + "odoo.exceptions.ValidationError": _lt("Validation Error"), + "odoo.exceptions.AccessError": _lt("Access Error"), + "odoo.exceptions.Warning": _lt("Warning") + }) +); // ----------------------------------------------------------------------------- // Generic Error Dialog diff --git a/addons/web/static/src/core/notifications/notification.js b/addons/web/static/src/core/notifications/notification.js index 64cc6919e7c..e5fbd0c24a6 100644 --- a/addons/web/static/src/core/notifications/notification.js +++ b/addons/web/static/src/core/notifications/notification.js @@ -40,13 +40,13 @@ Notification.props = { return ( typeof m === "string" || (typeof m === "object" && typeof m.toString === "function") ); - }, + } }, - title: { type: [String, Boolean], optional: true }, + title: { type: [String, Boolean, { toString: Function }], optional: true }, type: { type: String, optional: true, - validate: (t) => ["warning", "danger", "success", "info"].includes(t), + validate: (t) => ["warning", "danger", "success", "info"].includes(t) }, messageIsHtml: { type: Boolean, optional: true }, className: { type: String, optional: true }, @@ -58,15 +58,15 @@ Notification.props = { name: { type: String }, icon: { type: String, optional: true }, primary: { type: Boolean, optional: true }, - onClick: Function, - }, - }, + onClick: Function + } + } }, - onClose: { type: Function, optional: true }, + onClose: { type: Function, optional: true } }; Notification.defaultProps = { buttons: [], className: "", messageIsHtml: false, - type: "warning", + type: "warning" }; diff --git a/addons/web/static/src/legacy/frontend/public_crash_manager/public_crash_manager.js b/addons/web/static/src/legacy/frontend/public_crash_manager/public_crash_manager.js deleted file mode 100644 index a9942498278..00000000000 --- a/addons/web/static/src/legacy/frontend/public_crash_manager/public_crash_manager.js +++ /dev/null @@ -1,398 +0,0 @@ -odoo.define('web.CrashManager', function (require) { - "use strict"; - - const AbstractService = require('web.AbstractService'); - var ajax = require('web.ajax'); - var core = require('web.core'); - var Dialog = require('web.Dialog'); - var Widget = require('web.Widget'); - var config = require('web.config'); - var { formatTraceback, annotateTraceback } = require("@web/legacy/js/core/error_utils"); - - 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/legacy/frontend/public_crash_manager/public_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.error = error; - this.message = error.message; - this.traceback = error.traceback; - core.bus.off('close_dialogs', this); - }, - - willStart: async function () { - await this._super() - const jsError = this.error.data && this.error.data.jsError; - if (jsError) { - if (config.isDebug('assets')) { - this.traceback = await annotateTraceback(jsError); - } else { - this.traceback = formatTraceback(jsError); - } - } - }, - - start: async function () { - await this._super(); - const message = this.message; - const traceback = this.traceback; - - if (!traceback) { - return; - } - this.$(".o_error_detail").on("shown.bs.collapse", function (e) { - e.target.scrollTop = e.target.scrollHeight; - }); - - const $clipboardBtn = this.$(".o_clipboard_button"); - $clipboardBtn.tooltip({title: _t("Copied !"), trigger: "manual", placement: "left"}); - this.clipboard = new window.ClipboardJS($clipboardBtn[0], { - text: function () { - return (_t("Error") + ":\n" + message + "\n\n" + traceback).trim(); - }, - // Container added because of Bootstrap modal that give the focus to another element. - // We need to give to correct focus to ClipboardJS (see in ClipboardJS doc) - // https://github.com/zenorocha/clipboard.js/issues/155 - container: this.el, - }); - this.clipboard.on("success", function (e) { - _.defer(function () { - $clipboardBtn.tooltip("show"); - _.delay(function () { - $clipboardBtn.tooltip("hide"); - }, 800); - }); - }); - }, - destroy() { - if (this.clipboard) { - this.$(".o_clipboard_button").tooltip('dispose'); - this.clipboard.destroy(); - } - this._super(); - } - }); - - 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._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