From 4c7ef96974bce862599a3ea4845fd8762c7d2bbb Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Mon, 26 Jul 2021 13:35:45 +0000 Subject: [PATCH] [REF] web: refactor debug menu to use context in env instead of service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes the debug menu more natural to use, and makes the difference between the "in-dialog" and "out-of-dialog" debug contexts explicit. closes odoo/odoo#74346 Related: odoo/enterprise#19967 Signed-off-by: Géry Debongnie (ged) --- .../static/tests/tools/debug_manager_tests.js | 3 - .../static/src/js/debug_manager.js | 2 +- .../static/src/core/debug/debug_context.js | 81 +++++++++++++++++ .../web/static/src/core/debug/debug_menu.js | 88 ++----------------- .../web/static/src/core/debug/debug_menu.xml | 21 ++--- .../static/src/core/debug/debug_menu_items.js | 7 +- .../static/src/core/debug/debug_service.js | 74 ---------------- .../core/debug/profiling/profiling_service.js | 1 + .../web/static/src/legacy/action_adapters.js | 13 +-- addons/web/static/src/legacy/debug_manager.js | 21 ++++- .../src/webclient/actions/action_dialog.js | 2 + .../src/webclient/clickbot/clickbot_loader.js | 2 +- addons/web/static/src/webclient/webclient.js | 13 +++ .../tests/core/debug/debug_manager_tests.js | 66 +++++++------- .../tests/webclient/actions/legacy_tests.js | 6 +- .../webclient/actions/window_action_tests.js | 2 - .../static/src/debug/debug_manager.js | 1 + .../static/tests/debug_manager_tests.js | 8 +- 18 files changed, 179 insertions(+), 232 deletions(-) create mode 100644 addons/web/static/src/core/debug/debug_context.js delete mode 100644 addons/web/static/src/core/debug/debug_service.js diff --git a/addons/mail/static/tests/tools/debug_manager_tests.js b/addons/mail/static/tests/tools/debug_manager_tests.js index d3bde2e0550..0a50e4cd123 100644 --- a/addons/mail/static/tests/tools/debug_manager_tests.js +++ b/addons/mail/static/tests/tools/debug_manager_tests.js @@ -3,7 +3,6 @@ import { manageMessages } from "@mail/js/tools/debug_manager"; import { click, legacyExtraNextTick, patchWithCleanup } from "@web/../tests/helpers/utils"; import { createWebClient, doAction, getActionManagerServerData } from "@web/../tests/webclient/helpers"; -import { debugService } from "@web/core/debug/debug_service"; import { registry } from "@web/core/registry"; QUnit.module("DebugMenu"); @@ -25,8 +24,6 @@ QUnit.test("Manage Messages", async function (assert) { "mail.message,false,search": ``, }); - // Activate debug service with "Manage Message" item - registry.category("services").add("debug", debugService); registry.category("debug").category("form").add("manageMessages", manageMessages); async function mockRPC(route, args) { diff --git a/addons/point_of_sale/static/src/js/debug_manager.js b/addons/point_of_sale/static/src/js/debug_manager.js index b1a185e8417..12cf87d1279 100644 --- a/addons/point_of_sale/static/src/js/debug_manager.js +++ b/addons/point_of_sale/static/src/js/debug_manager.js @@ -18,4 +18,4 @@ function runPoSJSTests({ env }) { }; } -registry.category("debug").add("point_of_sale.runPoSJSTests", runPoSJSTests); +registry.category("debug").category("default").add("point_of_sale.runPoSJSTests", runPoSJSTests); diff --git a/addons/web/static/src/core/debug/debug_context.js b/addons/web/static/src/core/debug/debug_context.js new file mode 100644 index 00000000000..a972f76da4a --- /dev/null +++ b/addons/web/static/src/core/debug/debug_context.js @@ -0,0 +1,81 @@ +/** @odoo-module **/ +import { registry } from "../registry"; +import { memoize } from "../utils/functions"; +import { useEffect } from "../effect_hook"; + +const { useEnv, useSubEnv } = owl.hooks; +const debugRegistry = registry.category("debug"); + +const getAccessRights = memoize(async function getAccessRights(orm) { + const rightsToCheck = { + "ir.ui.view": "write", + "ir.rule": "read", + "ir.model.access": "read", + }; + const proms = Object.entries(rightsToCheck).map(([model, operation]) => { + return orm.call(model, "check_access_rights", [], { + operation, + raise_exception: false, + }); + }); + const [canEditView, canSeeRecordRules, canSeeModelAccess] = await Promise.all(proms); + const accessRights = { canEditView, canSeeRecordRules, canSeeModelAccess }; + return accessRights; +}); + +class DebugContext { + constructor(env, defaultCategories) { + this.orm = env.services.orm; + this.categories = new Map(defaultCategories.map((cat) => [cat, [{}]])); + } + + activateCategory(category, context) { + const contexts = this.categories.get(category) || new Set(); + contexts.add(context); + this.categories.set(category, contexts); + + return () => { + contexts.delete(context); + if (contexts.size === 0) { + this.categories.delete(category); + } + }; + } + + async getItems(env) { + const accessRights = await getAccessRights(this.orm); + return [...this.categories.entries()].flatMap(([category, contexts]) => { + return debugRegistry + .category(category) + .getAll() + .map((factory) => factory(Object.assign({ env, accessRights }, ...contexts))) + .filter(Boolean) + .sort((x, y) => { + const xSeq = x.sequence || 1000; + const ySeq = y.sequence || 1000; + return xSeq - ySeq; + }); + }); + } +} + +const debugContextSymbol = Symbol("debugContext"); +export function useOwnDebugContext({ categories = [] } = {}) { + useSubEnv({ [debugContextSymbol]: new DebugContext(useEnv(), categories) }); +} + +export function useCurrentDebugContext() { + const debugContext = useEnv()[debugContextSymbol]; + if (!debugContext) { + throw new Error("There is no debug context available in the current environment."); + } + return debugContext; +} + +export function useDebugCategory(category, context = {}) { + const debugContext = useCurrentDebugContext(); + useEffect( + () => debugContext.activateCategory(category, context), + () => [] + ); +} diff --git a/addons/web/static/src/core/debug/debug_menu.js b/addons/web/static/src/core/debug/debug_menu.js index e103475e9ed..78b61a8e83c 100644 --- a/addons/web/static/src/core/debug/debug_menu.js +++ b/addons/web/static/src/core/debug/debug_menu.js @@ -1,92 +1,14 @@ /** @odoo-module **/ - -import { useService } from "../service_hook"; -import { useEffect } from "../effect_hook"; -import { registry } from "../registry"; - -const debugRegistry = registry.category("debug"); - +import { useCurrentDebugContext } from "./debug_context"; const { Component } = owl; -let debugElementsId = 1; export class DebugMenu extends Component { setup() { - const globalContext = { env: this.env }; - this.activeCategories = new Set(); - this.contexts = new Map([["global", globalContext]]); - this.debugService = useService("debug"); - this.hasAccessRights = false; - // Defined as arrow to be passed as prop - // @ts-ignore - this.beforeOpenDropdown = async () => { - if (!this.hasAccessRights) { - this.hasAccessRights = true; - const accessRights = await this.debugService.getAccessRights(); - Object.assign(globalContext, { accessRights }); - } + const debugContext = useCurrentDebugContext(); + // Needs to be bound to this for use in template + this.getElements = async () => { + this.elements = await debugContext.getItems(this.env); }; - this.env.bus.on("DEBUG-MANAGER:ADD-CONTEXT", this, (payload) => { - const { category, context, inDialog, itemId } = payload; - if (this.env.inDialog === inDialog) { - this.contexts.set(itemId, context); - this.activeCategories.add(category); - } - }); - this.env.bus.on("DEBUG-MANAGER:REMOVE-CONTEXT", this, (payload) => { - const { category, inDialog, itemId } = payload; - if (this.env.inDialog === inDialog) { - this.contexts.delete(itemId); - this.activeCategories.delete(category); - } - }); - } - - getElements() { - const factories = []; - const context = Object.assign({}, ...this.contexts.values()); - // If not in dialog => gets root (generic) factories - if (!this.env.inDialog) { - factories.push(...debugRegistry.getAll()); - } - // Retrieves the active categories factories - for (const category of this.activeCategories) { - factories.push(...debugRegistry.category(category).getAll()); - } - // Builds, filters and sorts all items - return factories - .map((factory) => factory(context)) - .filter(Boolean) - .sort((x, y) => { - const xSeq = x.sequence ? x.sequence : 1000; - const ySeq = y.sequence ? y.sequence : 1000; - return xSeq - ySeq; - }); - } - - onDropdownItemSelected(ev) { - // items of type "component" don't necessarily have a payload/callback - if (ev.detail.payload && ev.detail.payload.callback) { - ev.detail.payload.callback(); - } } } - DebugMenu.template = "web.DebugMenu"; - -export function useDebugMenu(category, context = {}) { - const component = Component.current; - const env = component.env; - const payload = { - category, - context, - inDialog: env.inDialog, - itemId: debugElementsId++, - }; - useEffect( - () => { - env.bus.trigger("DEBUG-MANAGER:ADD-CONTEXT", payload); - return () => env.bus.trigger("DEBUG-MANAGER:REMOVE-CONTEXT", payload); - }, - () => [] - ); -} diff --git a/addons/web/static/src/core/debug/debug_menu.xml b/addons/web/static/src/core/debug/debug_menu.xml index 309e61f5910..31910cc3938 100644 --- a/addons/web/static/src/core/debug/debug_menu.xml +++ b/addons/web/static/src/core/debug/debug_menu.xml @@ -3,23 +3,20 @@ - - - - - - - - -