[REF] web: refactor command service API

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) <ged@openerp.com>
This commit is contained in:
Michael Mattiello (mcm)
2021-06-18 21:31:31 +02:00
committed by Aaron Bohy
parent 37a73aaf7a
commit 866f0e8c37
3 changed files with 52 additions and 31 deletions
@@ -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),
() => []
);
}
@@ -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);
};
},
};
},
};
@@ -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