diff --git a/web/static/src/ts/services/router.ts b/web/static/src/ts/services/router.ts index f321c824..09c598d7 100644 --- a/web/static/src/ts/services/router.ts +++ b/web/static/src/ts/services/router.ts @@ -4,11 +4,7 @@ import { EventBus, Callback } from "../core/event_bus"; // Types and helpers //------------------------------------------------------------------------------ -export type Query = { [key: string]: string }; - -function clearSlashes(s: string): string { - return s.replace(/\/$/, "").replace(/^\//, ""); -} +export type Query = { [key: string]: string | true }; export type RouterEvent = "query_changed"; @@ -23,6 +19,10 @@ export interface IRouter { // Router //------------------------------------------------------------------------------ +function clearSlashes(s: string): string { + return s.replace(/\/$/, "").replace(/^\//, ""); +} + export class Router extends EventBus implements IRouter { currentQuery: Query; @@ -46,7 +46,11 @@ export class Router extends EventBus implements IRouter { formatQuery(query: Query): string { let parts: string[] = []; for (let key in query) { - parts.push(`${key}=${query[key]}`); + if (query[key] === true) { + parts.push(key); + } else { + parts.push(`${key}=${query[key]}`); + } } return parts.join("&"); } diff --git a/web/static/src/ts/store/store.ts b/web/static/src/ts/store/store.ts index 6bfd493e..aa0331e3 100644 --- a/web/static/src/ts/store/store.ts +++ b/web/static/src/ts/store/store.ts @@ -62,6 +62,7 @@ export class BaseStore extends EventBus { menuInfo: MenuInfo; services: Services; actionRegistry: Registry; + currentQuery: Query; constructor( services: Services, @@ -72,6 +73,7 @@ export class BaseStore extends EventBus { this.services = services; this.menuInfo = menuInfo; this.actionRegistry = actionRegistry; + this.currentQuery = {}; } update(nextState: Partial) { @@ -84,6 +86,16 @@ export class BaseStore extends EventBus { return; } this.update({ inHome: !this.state.inHome }); + if (this.state.inHome) { + this.services.router.navigate({ home: true }); + } else { + this.updateQuery(this.currentQuery); + } + } + + updateQuery(query: Query) { + this.currentQuery = query; + this.services.router.navigate(query); } } @@ -101,6 +113,7 @@ export class Store extends actionManagerMixin( this.state.currentApp = app; if (!actionId) { this.state.inHome = true; + this.services.router.navigate({ home: true }); } this.services.router.on("query_changed", this, this.updateAction); @@ -131,8 +144,8 @@ export class Store extends actionManagerMixin( if (app) { this.update({ currentApp: app }); } - this.services.router.navigate(query); - return this.doAction(actionId); + await this.doAction(actionId); + this.updateQuery(query); } else { this.update({ inHome: true, currentApp: newApp }); } @@ -144,14 +157,14 @@ export class Store extends actionManagerMixin( const menuInfo = this.menuInfo; let app: MenuItem | null = null; let actionId: number | null = null; - if ("action_id" in query) { + if (typeof query.action_id === "string") { actionId = parseInt(query.action_id, 10); if (menuInfo.actionMap[actionId]) { const menu = menuInfo.actionMap[actionId]!; app = menu.app; } } - if ("menu_id" in query) { + if (typeof query.menu_id === "string") { const menuId = parseInt(query.menu_id, 10); const menu = menuInfo.menus[menuId]; if (menu) { diff --git a/web/static/tests/store/store.test.ts b/web/static/tests/store/store.test.ts index 41db74c1..490b638d 100644 --- a/web/static/tests/store/store.test.ts +++ b/web/static/tests/store/store.test.ts @@ -107,13 +107,26 @@ describe("state transitions", () => { // should still be in home menu since no app is currently active expect(store.state.inHome).toBe(true); + expect(store.services.router.getQuery()).toEqual({ home: true }); - await store.activateMenuItem(96); + const promise = store.activateMenuItem(96); + expect(store.services.router.getQuery()).toEqual({ home: true }); + + await promise; expect(store.state.inHome).toBe(false); + expect(store.services.router.getQuery()).toEqual({ + action_id: "131", + menu_id: "96" + }); store.toggleHomeMenu(); expect(store.state.inHome).toBe(true); + expect(store.services.router.getQuery()).toEqual({ home: true }); store.toggleHomeMenu(); expect(store.state.inHome).toBe(false); + expect(store.services.router.getQuery()).toEqual({ + action_id: "131", + menu_id: "96" + }); }); }); diff --git a/web/static/tests/widgets/root.test.ts b/web/static/tests/widgets/root.test.ts index 8c862956..eb54055a 100644 --- a/web/static/tests/widgets/root.test.ts +++ b/web/static/tests/widgets/root.test.ts @@ -57,7 +57,7 @@ test("start with no action => clicks on client action => discuss is rendered", a const root = new Root(env, store); await root.mount(fixture); - expect(env.services.router.getQuery()).toEqual({}); + expect(env.services.router.getQuery()).toEqual({ home: true }); // discuss menu item await (document.querySelector('[data-menu="96"]')).click();