From 866f0e8c37bf69bd554d4efa4cde5a9e96a618f4 Mon Sep 17 00:00:00 2001 From: "Michael Mattiello (mcm)" Date: Mon, 7 Jun 2021 09:15:32 +0000 Subject: [PATCH] [REF] web: refactor command service API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, service command exported 2 functions: registerCommand and unregisterCommand. Now, it exports only one function "add" which is calls registerCommand and returns a callback which calls unregisterCommand The add function's signature is different from registerCommand: - registerCommand signature: registerCommand(command: Command): number interface Command { name: string; action: () => void; category?: string; hotkey?: string; hotkeyOptions?: any; } - add signature: add( name: string, action: () => void, options?: Options ): () => void interface Options { category?: string; hotkey?: string; hotkeyOptions?: any; } closes odoo-dev/odoo#923 Signed-off-by: Géry Debongnie (ged) --- .../src/webclient/commands/command_hook.js | 16 ++++---- .../src/webclient/commands/command_service.js | 28 ++++++++++++- .../commands/command_service_tests.js | 39 ++++++++----------- 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/addons/web/static/src/webclient/commands/command_hook.js b/addons/web/static/src/webclient/commands/command_hook.js index b4a900477ac..798ffde1608 100644 --- a/addons/web/static/src/webclient/commands/command_hook.js +++ b/addons/web/static/src/webclient/commands/command_hook.js @@ -4,19 +4,21 @@ import { useService } from "../../core/service_hook"; import { useEffect } from "../../core/effect_hook"; /** - * @typedef {import("./command_service").Command} Command + * @typedef {import("./command_service").CommandServiceAddOptions} CommandServiceAddOptions */ /** * This hook will subscribe/unsubscribe the given subscription * when the caller component will mount/unmount. * - * @param {Command} command + * @param {string} name + * @param {() => void} action + * @param {CommandServiceAddOptions} [options] */ -export function useCommand(command) { +export function useCommand(name, action, options = {}) { const commandService = useService("command"); - useEffect(() => { - const token = commandService.registerCommand(command); - return () => commandService.unregisterCommand(token); - }, () => []); + useEffect( + () => commandService.add(name, action, options), + () => [] + ); } diff --git a/addons/web/static/src/webclient/commands/command_service.js b/addons/web/static/src/webclient/commands/command_service.js index 95d391b450b..465205cdcd0 100644 --- a/addons/web/static/src/webclient/commands/command_service.js +++ b/addons/web/static/src/webclient/commands/command_service.js @@ -14,6 +14,14 @@ import { CommandPaletteDialog } from "./command_palette_dialog"; * }} Command */ +/** + * @typedef {{ + * category?: string; + * hotkey?: string; + * hotkeyOptions?: any; + * }} CommandServiceAddOptions + */ + export const commandService = { dependencies: ["dialog", "hotkey", "ui"], start(env, { dialog, hotkey: hotkeyService, ui }) { @@ -118,8 +126,24 @@ export const commandService = { } return { - registerCommand, - unregisterCommand, + /** + * @param {string} name + * @param {() => void} action + * @param {CommandServiceAddOptions} [options] + * @returns {() => void} + */ + add(name, action, options = {}) { + const token = registerCommand({ + name, + action, + category: options.category, + hotkey: options.hotkey, + hotkeyOptions: options.hotkeyOptions, + }); + return () => { + unregisterCommand(token); + }; + }, }; }, }; diff --git a/addons/web/static/tests/webclient/commands/command_service_tests.js b/addons/web/static/tests/webclient/commands/command_service_tests.js index 5caf05f82cd..ffd756fd185 100644 --- a/addons/web/static/tests/webclient/commands/command_service_tests.js +++ b/addons/web/static/tests/webclient/commands/command_service_tests.js @@ -68,22 +68,19 @@ QUnit.test("commands evilness 👹", async (assert) => { function action() {} assert.throws(function () { - command.registerCommand(); - }, /undefined/); - assert.throws(function () { - command.registerCommand(null); - }, /null/); - assert.throws(function () { - command.registerCommand({}); + command.add(); }, /A Command must have a name and an action function/); assert.throws(function () { - command.registerCommand({ name: "" }); + command.add(null); }, /A Command must have a name and an action function/); assert.throws(function () { - command.registerCommand({ action }); + command.add(""); }, /A Command must have a name and an action function/); assert.throws(function () { - command.registerCommand({ name: "", action }); + command.add("", action); + }, /A Command must have a name and an action function/); + assert.throws(function () { + command.add("command", null); }, /A Command must have a name and an action function/); }); @@ -93,12 +90,12 @@ QUnit.test("useCommand hook", async (assert) => { class MyComponent extends TestComponent { setup() { super.setup(); - useCommand({ - name: "Take the throne", - action: () => { + useCommand( + "Take the throne", + () => { assert.step("Hodor"); }, - }); + ); } } testComponent = await mount(MyComponent, { env, target }); @@ -121,9 +118,7 @@ QUnit.test("command with hotkey", async (assert) => { assert.expect(2); const hotkey = "a"; - env.services.command.registerCommand({ - name: "test", - action: () => assert.step(hotkey), + env.services.command.add("test", () => assert.step(hotkey), { hotkey, hotkeyOptions: { altIsOptional: true }, }); @@ -197,7 +192,7 @@ QUnit.test("can be searched", async (assert) => { function action() {} const names = ["Cersei Lannister", "Jaime Lannister", "Tyrion Lannister", "Tywin Lannister"]; for (const name of names) { - env.services.command.registerCommand({ name, action }); + env.services.command.add(name, action); } await nextTick(); @@ -246,10 +241,10 @@ QUnit.test("command categories", async (assert) => { // Register some commands function action() {} - env.services.command.registerCommand({ name: "a", action, category: "custom-nolabel" }); - env.services.command.registerCommand({ name: "b", action, category: "custom" }); - env.services.command.registerCommand({ name: "c", action }); - env.services.command.registerCommand({ name: "d", action, category: "invalid-category" }); + env.services.command.add("a", action, { category: "custom-nolabel" }); + env.services.command.add("b", action, { category: "custom" }); + env.services.command.add("c", action); + env.services.command.add("d", action, { category: "invalid-category" }); await nextTick(); // Open palette