work on action manager

This commit is contained in:
Géry Debongnie
2019-03-06 14:59:17 +01:00
parent 4145a5ebac
commit c0ea764481
5 changed files with 54 additions and 65 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
import { Registry } from "./core/registry";
import { ActionWidget } from "./store/store";
import { ControllerWidget } from "./store/store";
import { Discuss } from "./discuss/discuss";
export const actionRegistry: Registry<ActionWidget> = new Registry();
export const actionRegistry: Registry<ControllerWidget> = new Registry();
actionRegistry.add("mail.discuss", Discuss);
+38 -49
View File
@@ -7,28 +7,12 @@ import { View } from "../views/view";
// Types
//------------------------------------------------------------------------------
export type Context = { [key: string]: any };
export interface CommonActionInfo {
id: number;
context: Context;
title: string;
target: "current" | "new";
Widget: ActionWidget;
}
// Miscellaneous
export type ActionRequest = number;
export type ActionWidget = Type<Widget<{}, {}>>;
export interface ClientActionInfo extends CommonActionInfo {
type: "client";
}
export interface ActWindowInfo extends CommonActionInfo {
type: "act_window";
}
export type ControllerWidget = Type<Widget<{}, {}>>;
// Action Description
interface BaseActionDescription {
id: number;
target: "current";
@@ -52,13 +36,13 @@ export type ActionDescription =
| ClientActionDescription
| ActWindowActionDescription;
export type ActionInfo = ClientActionInfo | ActWindowInfo;
export interface Action {
// Controller
export interface Controller {
id: number;
actionId: number;
widget?: Widget<any, any>;
executor(parent: Widget<any, any>): Promise<Widget<any, any> | null>;
activate(): void;
create(parent: Widget<any, any>): Promise<Widget<any, any> | null>;
title: string;
}
//------------------------------------------------------------------------------
@@ -70,8 +54,8 @@ export function actionManagerMixin<T extends ReturnType<typeof rpcMixin>>(
) {
return class extends Base {
actionCache: { [key: number]: Promise<ActionDescription> } = {};
currentAction?: Action;
lastAction?: Action;
currentController?: Controller;
lastController?: Controller;
async doAction(request: ActionRequest) {
const self = this;
@@ -87,28 +71,21 @@ export function actionManagerMixin<T extends ReturnType<typeof rpcMixin>>(
default:
throw new Error("unhandled action");
}
if (executor) {
const action: Action = {
id: this.generateID(),
executor,
activate() {
if (self.currentAction && self.currentAction.widget) {
self.currentAction.widget.destroy();
}
self.currentAction = action;
self.update({
inHome: false
});
document.title = descr.name + " - Odoo";
}
};
self.lastAction = action;
this.trigger("update_action", action);
}
const action: Controller = {
id: this.generateID(),
actionId: descr.id,
create: executor,
title: descr.name
};
self.lastController = action;
this.trigger("update_action", action);
}
doActWindowAction(descr: ActWindowActionDescription) {
return async function executor(this: Action, parent: Widget<any, any>) {
return async function executor(
this: Controller,
parent: Widget<any, any>
) {
const widget = new View(parent, { info: descr.views[0][1] });
const div = document.createElement("div");
await widget.mount(div);
@@ -117,9 +94,7 @@ export function actionManagerMixin<T extends ReturnType<typeof rpcMixin>>(
};
}
doClientAction(
descr: ClientActionDescription
): Action["executor"] | undefined {
doClientAction(descr: ClientActionDescription): Controller["create"] {
let key = descr.tag;
let ActionWidget = this.actionRegistry.get(key);
if (!ActionWidget) {
@@ -130,7 +105,10 @@ export function actionManagerMixin<T extends ReturnType<typeof rpcMixin>>(
});
ActionWidget = Widget;
}
return async function executor(this: Action, parent: Widget<any, any>) {
return async function executor(
this: Controller,
parent: Widget<any, any>
) {
const widget = new ActionWidget!(parent, {});
const div = document.createElement("div");
await widget.mount(div);
@@ -150,5 +128,16 @@ export function actionManagerMixin<T extends ReturnType<typeof rpcMixin>>(
}
}));
}
activateController(controller: Controller) {
if (this.currentController && this.currentController.widget) {
this.currentController.widget.destroy();
}
this.currentController = controller;
this.update({
inHome: false
});
document.title = controller.title + " - Odoo";
}
};
}
+5 -5
View File
@@ -3,7 +3,7 @@ import { Registry } from "../core/registry";
import { idGenerator } from "../core/utils";
import { RPC } from "../services/ajax";
import { IRouter, Query } from "../services/router";
import { actionManagerMixin, ActionWidget } from "./action_manager_mixin";
import { actionManagerMixin, ControllerWidget } from "./action_manager_mixin";
import { rpcMixin } from "./rpc_mixin";
import { MenuItem } from "./store";
@@ -11,7 +11,7 @@ import { MenuItem } from "./store";
// Types
//------------------------------------------------------------------------------
export { ActionWidget } from "./action_manager_mixin";
export { ControllerWidget } from "./action_manager_mixin";
export { RPC } from "./rpc_mixin";
export interface MenuItem {
@@ -64,14 +64,14 @@ export class BaseStore extends EventBus {
};
menuInfo: MenuInfo;
services: Services;
actionRegistry: Registry<ActionWidget>;
actionRegistry: Registry<ControllerWidget>;
currentQuery: Query;
generateID = idGenerator();
constructor(
services: Services,
menuInfo: MenuInfo,
actionRegistry: Registry<ActionWidget>
actionRegistry: Registry<ControllerWidget>
) {
super();
this.services = services;
@@ -129,7 +129,7 @@ export class Store extends actionManagerMixin(rpcMixin(BaseStore)) {
constructor(
services: Services,
menuInfo: MenuInfo,
actionRegistry: Registry<ActionWidget>
actionRegistry: Registry<ControllerWidget>
) {
super(services, menuInfo, actionRegistry);
const query = this.services.router.getQuery();
+7 -7
View File
@@ -5,7 +5,7 @@ import { HomeMenu } from "./home_menu";
import { Navbar } from "./navbar";
import { Notification } from "./notification";
import { Widget } from "../widget";
import { Action } from "../store/action_manager_mixin";
import { Controller } from "../store/action_manager_mixin";
//------------------------------------------------------------------------------
// Root Widget
@@ -26,9 +26,9 @@ export class Root extends Widget<Store, State> {
mounted() {
this.store.on("state_updated", this, this.updateState);
this.store.on("rpc_status", this, this.toggleLoadingIndicator);
this.store.on("update_action", this, this.applyAction);
if (this.store.lastAction) {
this.applyAction(this.store.lastAction);
this.store.on("update_action", this, this.applyController);
if (this.store.lastController) {
this.applyController(this.store.lastController);
}
// adding reactiveness to mobile/non mobile
@@ -50,13 +50,13 @@ export class Root extends Widget<Store, State> {
(<any>this.refs.loading_indicator).classList[method]("d-none");
}
async applyAction(action: Action) {
const widget = await action.executor(this);
async applyController(controller: Controller) {
const widget = await controller.create(this);
if (widget) {
// to do: call some public method of widget instead...
(<HTMLElement>this.refs.content).appendChild(widget.el!);
widget.__mount();
action.activate();
this.store.activateController(controller);
}
}
}
+2 -2
View File
@@ -101,7 +101,7 @@ describe("state transitions", () => {
expect(store.services.router.getQuery()).toEqual({ home: true });
await promise;
store.lastAction!.activate();
store.activateController(store.lastController!);
expect(store.state.inHome).toBe(false);
expect(store.services.router.getQuery()).toEqual({
action_id: "131",
@@ -128,7 +128,7 @@ describe("state transitions", () => {
const promise = store.activateMenuItem(96);
expect(document.title).toBe("Odoo");
await promise;
store.lastAction!.activate();
store.activateController(store.lastController!);
expect(document.title).toBe("Discuss - Odoo");