mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
make widget generic on State
This commit is contained in:
@@ -23,8 +23,8 @@ interface Meta<T extends WEnv> {
|
||||
isStarted: boolean;
|
||||
isMounted: boolean;
|
||||
isDestroyed: boolean;
|
||||
parent: Widget<T, {}> | null;
|
||||
children: { [key: number]: Widget<T, {}> };
|
||||
parent: BaseWidget<T, any, any> | null;
|
||||
children: { [key: number]: BaseWidget<T, any, any> };
|
||||
// children mapping: from templateID to widgetID
|
||||
// should it be a map number => Widget?
|
||||
cmap: { [key: number]: number };
|
||||
@@ -40,7 +40,7 @@ export interface Type<T> extends Function {
|
||||
// Widget
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class Widget<T extends WEnv, Props> extends EventBus {
|
||||
export class BaseWidget<T extends WEnv, Props, State> extends EventBus {
|
||||
__widget__: Meta<WEnv>;
|
||||
template: string = "default";
|
||||
inlineTemplate: string | null = null;
|
||||
@@ -52,13 +52,15 @@ export class Widget<T extends WEnv, Props> extends EventBus {
|
||||
env: T;
|
||||
state: Object = {};
|
||||
props: Props;
|
||||
refs: { [key: string]: Widget<T, {}> | HTMLElement | undefined } = {};
|
||||
refs: {
|
||||
[key: string]: BaseWidget<T, any, any> | HTMLElement | undefined;
|
||||
} = {};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Lifecycle
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
constructor(parent: Widget<T, any> | T, props?: Props) {
|
||||
constructor(parent: BaseWidget<T, any, any> | T, props?: Props) {
|
||||
super();
|
||||
wl.push(this);
|
||||
|
||||
@@ -68,8 +70,8 @@ export class Widget<T extends WEnv, Props> extends EventBus {
|
||||
// Pro: but creating widget (by a template) is always unsafe anyway
|
||||
this.props = <Props>props;
|
||||
let id: number;
|
||||
let p: Widget<T, any> | null = null;
|
||||
if (parent instanceof Widget) {
|
||||
let p: BaseWidget<T, any, any> | null = null;
|
||||
if (parent instanceof BaseWidget) {
|
||||
p = parent;
|
||||
this.env = parent.env;
|
||||
id = this.env.getID();
|
||||
@@ -173,17 +175,11 @@ export class Widget<T extends WEnv, Props> extends EventBus {
|
||||
* - it is ok to call updateState before the widget is started. In that
|
||||
* case, it will simply update the state and will not rerender
|
||||
*/
|
||||
async updateState(nextState: Object) {
|
||||
async updateState(nextState: Partial<State>) {
|
||||
if (Object.keys(nextState).length === 0) {
|
||||
return;
|
||||
}
|
||||
for (let key in nextState) {
|
||||
if (key in this.state) {
|
||||
this.state[key] = nextState[key];
|
||||
} else {
|
||||
throw new Error(`Invalid key: '${key}' does not exist in widget state`);
|
||||
}
|
||||
}
|
||||
Object.assign(this.state, nextState);
|
||||
if (this.__widget__.isStarted) {
|
||||
return this.render();
|
||||
}
|
||||
@@ -259,7 +255,7 @@ export class Widget<T extends WEnv, Props> extends EventBus {
|
||||
}
|
||||
}
|
||||
|
||||
private visitSubTree(callback: (w: Widget<T, any>) => boolean) {
|
||||
private visitSubTree(callback: (w: BaseWidget<T, any, any>) => boolean) {
|
||||
const shouldVisitChildren = callback(this);
|
||||
if (shouldVisitChildren) {
|
||||
const children = this.__widget__.children;
|
||||
@@ -1,18 +1,22 @@
|
||||
import { QWeb } from "./core/qweb_vdom";
|
||||
import { idGenerator, memoize } from "./core/utils";
|
||||
import { WEnv } from "./core/widget";
|
||||
import { ActionManager, IActionManager } from "./services/action_manager";
|
||||
import { Ajax, IAjax } from "./core/ajax";
|
||||
import { WEnv } from "./core/base_widget";
|
||||
import {
|
||||
INotificationManager,
|
||||
NotificationManager
|
||||
} from "./core/notifications";
|
||||
import { actionRegistry } from "./registries";
|
||||
import { QWeb } from "./core/qweb_vdom";
|
||||
import { Registry } from "./core/registry";
|
||||
import { IRouter, Router } from "./core/router";
|
||||
import { idGenerator, memoize } from "./core/utils";
|
||||
import { actionRegistry } from "./registries";
|
||||
import {
|
||||
ActionManager,
|
||||
ActionWidget,
|
||||
IActionManager
|
||||
} from "./services/action_manager";
|
||||
import { CRM } from "./widgets/crm";
|
||||
import { Discuss } from "./widgets/discuss";
|
||||
import { Widget, Type } from "./core/widget";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -30,7 +34,7 @@ export interface Env extends WEnv {
|
||||
router: IRouter;
|
||||
|
||||
// registries
|
||||
actionRegistry: Registry<Type<Widget<Env, any>>>;
|
||||
actionRegistry: Registry<ActionWidget>;
|
||||
|
||||
// data
|
||||
menus: Menu[];
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Registry } from "./core/registry";
|
||||
import { Widget, Type } from "./core/widget";
|
||||
import { Env } from "./env";
|
||||
import { ActionWidget } from "./services/action_manager";
|
||||
|
||||
export const actionRegistry: Registry<Type<Widget<Env, any>>> = new Registry();
|
||||
export const actionRegistry: Registry<ActionWidget> = new Registry();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Type } from "../core/base_widget";
|
||||
import { EventBus } from "../core/event_bus";
|
||||
import { Registry } from "../core/registry";
|
||||
import { Type, Widget } from "../core/widget";
|
||||
import { Env } from "../env";
|
||||
import { Widget } from "../widgets/widget";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
@@ -18,10 +18,12 @@ export interface CommonActionInfo {
|
||||
target: "current" | "new";
|
||||
}
|
||||
|
||||
export type ActionWidget = Type<Widget<{}, {}>>;
|
||||
|
||||
export interface ClientActionInfo extends CommonActionInfo {
|
||||
type: "client";
|
||||
name: string;
|
||||
Widget: Type<Widget<Env, {}>>;
|
||||
Widget: ActionWidget;
|
||||
}
|
||||
|
||||
export interface ActWindowInfo extends CommonActionInfo {
|
||||
@@ -47,10 +49,10 @@ export interface IActionManager {
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class ActionManager extends EventBus implements IActionManager {
|
||||
registry: Registry<Type<Widget<Env, any>>>;
|
||||
registry: Registry<ActionWidget>;
|
||||
stack: ActionStack;
|
||||
|
||||
constructor(registry: Registry<Type<Widget<Env, any>>>) {
|
||||
constructor(registry: Registry<ActionWidget>) {
|
||||
super();
|
||||
this.registry = registry;
|
||||
this.stack = [];
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Widget } from "../core/widget";
|
||||
import { Env } from "../env";
|
||||
import { Widget } from "./widget";
|
||||
|
||||
export class CRM extends Widget<Env, {}> {
|
||||
export class CRM extends Widget<{}, {}> {
|
||||
template = "web.crm";
|
||||
}
|
||||
|
||||
@@ -1,22 +1,34 @@
|
||||
import { Widget } from "../core/widget";
|
||||
import { Env } from "../env";
|
||||
import { Widget } from "./widget";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
interface Props {
|
||||
initialState?: number;
|
||||
}
|
||||
|
||||
export class Counter extends Widget<Env, Props> {
|
||||
interface State {
|
||||
counter: number;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Counter
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class Counter extends Widget<Props, State> {
|
||||
inlineTemplate = `
|
||||
<div t-name="counter">
|
||||
<button t-on-click="increment(-1)">-</button>
|
||||
<span style="font-weight:bold">Value: <t t-esc="state.counter"/></span>
|
||||
<button t-on-click="increment(1)">+</button>
|
||||
</div>`;
|
||||
|
||||
state = {
|
||||
counter: 0
|
||||
};
|
||||
|
||||
constructor(parent: Widget<Env, {}>, props: Props) {
|
||||
constructor(parent: Widget<any, any>, props: Props) {
|
||||
super(parent, props);
|
||||
this.state.counter = props.initialState || 0;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
import { Widget } from "../core/widget";
|
||||
import { Env } from "../env";
|
||||
import { Clock } from "./clock";
|
||||
import { Counter } from "./counter";
|
||||
import { Widget } from "./widget";
|
||||
|
||||
export class Discuss extends Widget<Env, {}> {
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
interface State {
|
||||
validcounter: boolean;
|
||||
color: "red" | "blue";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Discuss
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class Discuss extends Widget<{}, State> {
|
||||
template = "web.discuss";
|
||||
widgets = { Clock, Counter, ColorWidget };
|
||||
state = { validcounter: true, color: "red" };
|
||||
@@ -38,7 +50,7 @@ export class Discuss extends Widget<Env, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
class ColorWidget extends Widget<Env, { color: "red" | "blue" }> {
|
||||
class ColorWidget extends Widget<{ color: "red" | "blue" }, {}> {
|
||||
inlineTemplate = `
|
||||
<div t-name="colorwidget">
|
||||
<span>Current Color: </span>
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import { Widget } from "../core/widget";
|
||||
import { Env, Menu } from "../env";
|
||||
import { Menu } from "../env";
|
||||
import { MenuItem } from "../misc/menu_helpers";
|
||||
import { Widget } from "./widget";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export interface Props {
|
||||
inHome: boolean;
|
||||
app: MenuItem | null;
|
||||
}
|
||||
|
||||
export class Navbar extends Widget<Env, Props> {
|
||||
//------------------------------------------------------------------------------
|
||||
// Navbar
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class Navbar extends Widget<Props, {}> {
|
||||
template = "web.navbar";
|
||||
|
||||
getUrl(menu: Menu) {
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import { Widget } from "../core/widget";
|
||||
import { Env } from "../env";
|
||||
import { ActionStack } from "../services/action_manager";
|
||||
import { Widget } from "./widget";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export interface Props {
|
||||
stack: ActionStack;
|
||||
}
|
||||
|
||||
export class ActionContainer extends Widget<Env, Props> {
|
||||
//------------------------------------------------------------------------------
|
||||
// Action Container
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class ActionContainer extends Widget<Props, {}> {
|
||||
template = "web.action_container";
|
||||
currentWidget: any;
|
||||
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
import { Widget } from "../core/widget";
|
||||
import { Env } from "../env";
|
||||
import { Widget } from "./widget";
|
||||
|
||||
export class Clock extends Widget<Env, {}> {
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
interface State {
|
||||
currentTime: string;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Clock
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class Clock extends Widget<{}, State> {
|
||||
inlineTemplate = `<div class="o_clock"><t t-esc="state.currentTime"/></div>`;
|
||||
timeout: any | undefined;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Widget } from "../core/widget";
|
||||
import { Env } from "../env";
|
||||
import { MenuInfo, MenuItem } from "../misc/menu_helpers";
|
||||
import { Widget } from "./widget";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
@@ -14,7 +13,7 @@ export interface Props {
|
||||
// Home Menu
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class HomeMenu extends Widget<Env, Props> {
|
||||
export class HomeMenu extends Widget<Props, {}> {
|
||||
template = "web.home_menu";
|
||||
|
||||
get apps(): MenuItem[] {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Widget } from "../core/widget";
|
||||
import { Env } from "../env";
|
||||
import { INotification } from "../core/notifications";
|
||||
import { Widget } from "./widget";
|
||||
|
||||
export class Notification extends Widget<Env, INotification> {
|
||||
export class Notification extends Widget<INotification, {}> {
|
||||
template = "web.notification";
|
||||
|
||||
close() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { INotification } from "../core/notifications";
|
||||
import { Widget } from "../core/widget";
|
||||
import { Widget } from "./widget";
|
||||
import { Env } from "../env";
|
||||
import { MenuInfo, MenuItem, getAppAndAction } from "../misc/menu_helpers";
|
||||
import { ActionStack } from "../services/action_manager";
|
||||
@@ -28,7 +28,7 @@ interface Props {
|
||||
// Root Widget
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
export class Root extends Widget<Env, Props> {
|
||||
export class Root extends Widget<Props, State> {
|
||||
template = "web.web_client";
|
||||
widgets = { Navbar, Notification, HomeMenu, ActionContainer };
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import { BaseWidget } from "../core/base_widget";
|
||||
import { Env } from "../env";
|
||||
|
||||
export class Widget<Props, State> extends BaseWidget<Env, Props, State> {}
|
||||
Reference in New Issue
Block a user