diff --git a/web/static/src/ts/services/ajax.ts b/web/static/src/ts/services/ajax.ts index d2ebe59a..49ddf485 100644 --- a/web/static/src/ts/services/ajax.ts +++ b/web/static/src/ts/services/ajax.ts @@ -1,3 +1,5 @@ +import { EventBus } from "../core/event_bus"; + //------------------------------------------------------------------------------ // Types //------------------------------------------------------------------------------ @@ -17,8 +19,11 @@ export interface RPCControllerQuery { export type RPCQuery = RPCModelQuery | RPCControllerQuery; +type AjaxStatus = "loading" | "notloading"; + export interface IAjax { rpc(rpc: RPCQuery): Promise; + on(event: "rpc_status", owner: any, callback: (status: AjaxStatus) => void); } interface RequestParameters { @@ -32,16 +37,27 @@ export type FetchMethod = (route: string, params: any) => Promise; // Ajax //------------------------------------------------------------------------------ -export class Ajax implements IAjax { +export class Ajax extends EventBus implements IAjax { fetch: FetchMethod; + counter: number = 0; constructor(fetch: FetchMethod) { + super(); this.fetch = fetch; } - rpc(rpc: RPCQuery): Promise { + async rpc(rpc: RPCQuery): Promise { const request = this.prepareRequest(rpc); - return this.fetch(request.route, request.params); + if (this.counter === 0) { + this.trigger("rpc_status", "loading"); + } + this.counter++; + const result = await this.fetch(request.route, request.params); + this.counter--; + if (this.counter === 0) { + this.trigger("rpc_status", "notloading"); + } + return result; } private prepareRequest(query: RPCQuery): RequestParameters { diff --git a/web/static/tests/helpers.ts b/web/static/tests/helpers.ts index 28320517..58667d67 100644 --- a/web/static/tests/helpers.ts +++ b/web/static/tests/helpers.ts @@ -1,14 +1,14 @@ import { readFile } from "fs"; -import { Ajax, RPCQuery } from "../src/ts/services/ajax"; import { WEnv } from "../src/ts/core/component"; import { Callback } from "../src/ts/core/event_bus"; import { NotificationManager } from "../src/ts/core/notifications"; import { QWeb } from "../src/ts/core/qweb_vdom"; -import { actionRegistry } from "../src/ts/registries"; import { IRouter, Query, RouterEvent } from "../src/ts/core/router"; import { idGenerator } from "../src/ts/core/utils"; import { getMenuInfo } from "../src/ts/init"; +import { actionRegistry } from "../src/ts/registries"; import { ActionManager } from "../src/ts/services/action_manager"; +import { Ajax } from "../src/ts/services/ajax"; import { MenuInfo } from "../src/ts/widgets/root"; import { Env } from "../src/ts/widgets/widget"; diff --git a/web/static/tests/services/ajax.test.ts b/web/static/tests/services/ajax.test.ts new file mode 100644 index 00000000..bc4095c1 --- /dev/null +++ b/web/static/tests/services/ajax.test.ts @@ -0,0 +1,37 @@ +import { Ajax } from "../../src/ts/services/ajax"; +import { nextMicroTick } from "../helpers"; + +//------------------------------------------------------------------------------ +// Setup and helpers +//------------------------------------------------------------------------------ + +function mockFetch(route: string, params: any): Promise { + return Promise.resolve(`${route}`); +} + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +describe("parameters conversion", () => { + test("properly translate query in route", async () => { + const ajax = new Ajax(mockFetch); + const result = await ajax.rpc({ model: "test", method: "hey" }); + expect(result).toBe("/web/dataset/call_kw/test/hey"); + }); +}); + +describe("event and status", () => { + test("trigger proper events", async () => { + const ajax = new Ajax(mockFetch); + const events: string[] = []; + ajax.on("rpc_status", null, s => { + events.push(s); + }); + expect(events).toEqual([]); + ajax.rpc({ model: "test", method: "hey" }); + expect(events).toEqual(["loading"]); + await nextMicroTick(); + expect(events).toEqual(["loading", "notloading"]); + }); +});