make widget generic on State

This commit is contained in:
Géry Debongnie
2019-02-04 21:09:17 +01:00
parent 70b25fc7b8
commit 05e9797f7a
16 changed files with 161 additions and 107 deletions
@@ -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;
+11 -7
View File
@@ -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[];
+2 -3
View File
@@ -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();
+7 -5
View File
@@ -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 = [];
+2 -3
View File
@@ -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";
}
+16 -4
View File
@@ -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;
}
+16 -4
View File
@@ -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>
+11 -3
View File
@@ -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) {
+10 -3
View File
@@ -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;
+14 -3
View File
@@ -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;
+2 -3
View File
@@ -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[] {
+2 -3
View File
@@ -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() {
+2 -2
View File
@@ -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 };
+4
View File
@@ -0,0 +1,4 @@
import { BaseWidget } from "../core/base_widget";
import { Env } from "../env";
export class Widget<Props, State> extends BaseWidget<Env, Props, State> {}
@@ -1,6 +1,5 @@
import { WEnv, Widget } from "../../src/ts/core/widget";
import { makeTestWEnv, makeTestFixture } from "../helpers";
import { normalize } from "../helpers";
import { BaseWidget, WEnv } from "../../src/ts/core/base_widget";
import { makeTestFixture, makeTestWEnv, normalize } from "../helpers";
//------------------------------------------------------------------------------
// Setup and helpers
@@ -34,13 +33,16 @@ function nextTick(): Promise<void> {
return Promise.resolve();
}
function children(w: Widget<WEnv, {}>): Widget<WEnv, {}>[] {
class Widget extends BaseWidget<WEnv, {}, {}> {}
function children(w: Widget): Widget[] {
const childrenMap = w.__widget__.children;
return Object.keys(childrenMap).map(id => childrenMap[id]);
}
// Test widgets
class Counter extends Widget<WEnv, {}> {
class Counter extends Widget {
// class Counter extends Widget<WEnv, {}, {counter: number}> {
template = "counter";
state = {
counter: 0
@@ -51,12 +53,12 @@ class Counter extends Widget<WEnv, {}> {
}
}
class WidgetA extends Widget<WEnv, {}> {
class WidgetA extends Widget {
template = "widgetA";
widgets = { b: WidgetB };
}
class WidgetB extends Widget<WEnv, {}> {
class WidgetB extends Widget {
template = "widgetB";
}
@@ -88,7 +90,7 @@ describe("basic widget properties", () => {
});
test("widget style and classname", async () => {
class StyledWidget extends Widget<WEnv, {}> {
class StyledWidget extends Widget {
inlineTemplate = `<div style="font-weight:bold;" class="some-class">world</div>`;
}
const widget = new StyledWidget(env);
@@ -100,7 +102,7 @@ describe("basic widget properties", () => {
test("updateState before first render does not trigger a render", async () => {
let renderCalls = 0;
class TestW extends Widget<WEnv, {}> {
class TestW extends Widget {
async willStart() {
this.updateState({});
}
@@ -142,7 +144,7 @@ describe("basic widget properties", () => {
describe("lifecycle hooks", () => {
test("willStart hook is called", async () => {
let willstart = false;
class HookWidget extends Widget<WEnv, {}> {
class HookWidget extends Widget {
async willStart() {
willstart = true;
}
@@ -154,7 +156,7 @@ describe("lifecycle hooks", () => {
test("mounted hook is not called if not in DOM", async () => {
let mounted = false;
class HookWidget extends Widget<WEnv, {}> {
class HookWidget extends Widget {
async mounted() {
mounted = true;
}
@@ -167,7 +169,7 @@ describe("lifecycle hooks", () => {
test("mounted hook is called if mounted in DOM", async () => {
let mounted = false;
class HookWidget extends Widget<WEnv, {}> {
class HookWidget extends Widget {
async mounted() {
mounted = true;
}
@@ -179,11 +181,11 @@ describe("lifecycle hooks", () => {
test("willStart hook is called on subwidget", async () => {
let ok = false;
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
inlineTemplate = `<div><t t-widget="child"/></div>`;
widgets = { child: ChildWidget };
}
class ChildWidget extends Widget<WEnv, {}> {
class ChildWidget extends Widget {
async willStart() {
ok = true;
}
@@ -197,7 +199,7 @@ describe("lifecycle hooks", () => {
expect.assertions(4);
let parentMounted = false;
let childMounted = false;
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
inlineTemplate = `<div><t t-widget="child"/></div>`;
widgets = { child: ChildWidget };
mounted() {
@@ -205,7 +207,7 @@ describe("lifecycle hooks", () => {
parentMounted = true;
}
}
class ChildWidget extends Widget<WEnv, {}> {
class ChildWidget extends Widget {
mounted() {
expect(document.body.contains(this.el)).toBe(true);
expect(parentMounted).toBe(true);
@@ -223,7 +225,7 @@ describe("lifecycle hooks", () => {
// the t-else part in the template is important. This is
// necessary to have a situation that could confuse the vdom
// patching algorithm
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
inlineTemplate = `
<div>
<t t-if="state.ok">
@@ -236,7 +238,7 @@ describe("lifecycle hooks", () => {
state = { ok: false };
widgets = { child: ChildWidget };
}
class ChildWidget extends Widget<WEnv, {}> {
class ChildWidget extends Widget {
async willStart() {
hookCounter++;
}
@@ -261,13 +263,13 @@ describe("lifecycle hooks", () => {
expect.assertions(1);
const target = document.createElement("div");
document.body.appendChild(target);
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
mounted() {
const child = new ChildWidget(this);
child.mount(this.el!);
}
}
class ChildWidget extends Widget<WEnv, {}> {
class ChildWidget extends Widget {
mounted() {
expect(this.el).toBeTruthy();
done();
@@ -279,7 +281,7 @@ describe("lifecycle hooks", () => {
test("widgets are unmounted and destroyed if no longer in DOM", async () => {
let steps: string[] = [];
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
state = { ok: true };
inlineTemplate = `<div>
<t t-if="state.ok"><t t-widget="child"/></t>
@@ -287,7 +289,7 @@ describe("lifecycle hooks", () => {
widgets = { child: ChildWidget };
}
class ChildWidget extends Widget<WEnv, {}> {
class ChildWidget extends Widget {
constructor(parent) {
super(parent);
steps.push("init");
@@ -320,7 +322,7 @@ describe("lifecycle hooks", () => {
test("hooks are called in proper order in widget creation/destruction", async () => {
let steps: string[] = [];
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
inlineTemplate = `<div><t t-widget="child"/></div>`;
widgets = { child: ChildWidget };
constructor(parent) {
@@ -341,7 +343,7 @@ describe("lifecycle hooks", () => {
}
}
class ChildWidget extends Widget<WEnv, {}> {
class ChildWidget extends Widget {
constructor(parent) {
super(parent);
steps.push("c init");
@@ -378,7 +380,7 @@ describe("lifecycle hooks", () => {
test("shouldUpdate hook prevent rerendering", async () => {
let shouldUpdate = false;
class TestWidget extends Widget<WEnv, {}> {
class TestWidget extends Widget {
inlineTemplate = `<div><t t-esc="props.val"/></div>`;
shouldUpdate() {
return shouldUpdate;
@@ -408,7 +410,7 @@ describe("destroy method", () => {
test("destroying a widget twice only call destroyed once", async () => {
let count = 0;
class TestWidget extends Widget<WEnv, {}> {
class TestWidget extends Widget {
destroyed() {
count++;
}
@@ -450,7 +452,7 @@ describe("destroy method", () => {
let p: Promise<void> = new Promise(function(r) {
resolve = r;
});
class DelayedWidget extends Widget<WEnv, {}> {
class DelayedWidget extends Widget {
willStart() {
return p;
}
@@ -490,7 +492,7 @@ describe("composition", () => {
});
test("t-refs on widget are widgets", async () => {
class WidgetC extends Widget<WEnv, {}> {
class WidgetC extends Widget {
inlineTemplate = `<div>Hello<t t-ref="mywidgetb" t-widget="b"/></div>`;
widgets = { b: WidgetB };
}
@@ -500,7 +502,7 @@ describe("composition", () => {
});
test("modifying a sub widget", async () => {
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
inlineTemplate = `<div><t t-widget="Counter"/></div>`;
widgets = { Counter };
}
@@ -538,7 +540,7 @@ describe("composition", () => {
});
test("rerendering a widget with a sub widget", async () => {
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
inlineTemplate = `<div><t t-widget="Counter"/></div>`;
widgets = { Counter };
}
@@ -557,7 +559,7 @@ describe("composition", () => {
});
test("sub widgets are destroyed if no longer in dom, then recreated", async () => {
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
state = { ok: true };
inlineTemplate = `<div><t t-if="state.ok"><t t-widget="counter"/></t></div>`;
widgets = { counter: Counter };
@@ -579,7 +581,7 @@ describe("composition", () => {
});
test("sub widgets with t-keep-alive are not destroyed if no longer in dom", async () => {
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
state = { ok: true };
inlineTemplate = `<div><t t-if="state.ok"><t t-widget="counter" t-keep-alive="1"/></t></div>`;
widgets = { counter: Counter };
@@ -605,12 +607,12 @@ describe("composition", () => {
});
test("sub widgets dom state with t-keep-alive is preserved", async () => {
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
state = { ok: true };
inlineTemplate = `<div><t t-if="state.ok"><t t-widget="InputWidget" t-keep-alive="1"/></t></div>`;
widgets = { InputWidget };
}
class InputWidget extends Widget<WEnv, {}> {
class InputWidget extends Widget {
inlineTemplate = "<input/>";
}
const widget = new ParentWidget(env);
@@ -627,11 +629,11 @@ describe("composition", () => {
});
test("sub widgets rendered in a loop", async () => {
class ChildWidget extends Widget<WEnv, { n: number }> {
class ChildWidget extends Widget {
inlineTemplate = `<span><t t-esc="props.n"/></span>`;
}
class Parent extends Widget<WEnv, {}> {
class Parent extends Widget {
inlineTemplate = `
<div>
<t t-foreach="state.numbers" t-as="number">
@@ -658,7 +660,7 @@ describe("composition", () => {
test("sub widgets with some state rendered in a loop", async () => {
let n = 1;
class ChildWidget extends Widget<WEnv, never> {
class ChildWidget extends Widget {
inlineTemplate = `<span><t t-esc="state.n"/></span>`;
constructor(parent) {
super(parent);
@@ -667,7 +669,7 @@ describe("composition", () => {
}
}
class Parent extends Widget<WEnv, {}> {
class Parent extends Widget {
inlineTemplate = `<div>
<t t-foreach="state.numbers" t-as="number">
<t t-widget="ChildWidget" t-key="number"/>
@@ -694,13 +696,13 @@ describe("composition", () => {
describe("props evaluation (with t-props directive)", () => {
test("explicit object prop", async () => {
class Parent extends Widget<WEnv, {}> {
class Parent extends Widget {
inlineTemplate = `<div><t t-widget="child" t-props="{value: state.val}"/></div>`;
widgets = { child: Child };
state = { val: 42 };
}
class Child extends Widget<WEnv, {}> {
class Child extends Widget {
inlineTemplate = `<span><t t-esc="state.someval"/></span>`;
state: { someval: number };
constructor(parent: Parent, props: { value: number }) {
@@ -715,13 +717,13 @@ describe("props evaluation (with t-props directive)", () => {
});
test("object prop value", async () => {
class Parent extends Widget<WEnv, {}> {
class Parent extends Widget {
inlineTemplate = `<div><t t-widget="child" t-props="state"/></div>`;
widgets = { child: Child };
state = { val: 42 };
}
class Child extends Widget<WEnv, {}> {
class Child extends Widget {
inlineTemplate = `<span><t t-esc="state.someval"/></span>`;
state: { someval: number };
constructor(parent: Parent, props: { val: number }) {
@@ -739,7 +741,7 @@ describe("props evaluation (with t-props directive)", () => {
describe("t-on directive on widgets", () => {
test("t-on works as expected", async () => {
let n = 0;
class ParentWidget extends Widget<WEnv, {}> {
class ParentWidget extends Widget {
inlineTemplate = `<div><t t-widget="child" t-on-customevent="someMethod"/></div>`;
widgets = { child: Child };
someMethod(arg) {
@@ -747,7 +749,7 @@ describe("t-on directive on widgets", () => {
n++;
}
}
class Child extends Widget<WEnv, {}> {}
class Child extends Widget {}
const widget = new ParentWidget(env);
await widget.mount(fixture);
let child = children(widget)[0];
@@ -765,7 +767,7 @@ describe("random stuff/miscellaneous", () => {
// this test makes sure that the foreach directive does not pollute sub
// context with the inLoop variable, which is then used in the t-widget
// directive as a key
class Test extends Widget<WEnv, {}> {
class Test extends Widget {
inlineTemplate = `<div><t t-foreach="2">txt</t><t t-widget="widget"/></div>`;
widgets = { widget: Widget };
}
@@ -778,13 +780,13 @@ describe("random stuff/miscellaneous", () => {
// in this situation, we protect against a bug that occurred: because of the
// interplay between widgets and vnodes, a sub widget vnode was patched
// twice.
class Parent extends Widget<WEnv, {}> {
class Parent extends Widget {
inlineTemplate = `<div><t t-widget="child" t-props="state"/></div>`;
widgets = { child: Child };
state = { flag: false };
}
class Child extends Widget<WEnv, {}> {
class Child extends Widget {
inlineTemplate = `<span>abc<t t-if="props.flag">def</t></span>`;
}
+1 -1
View File
@@ -1,6 +1,6 @@
import { QWeb } from "../src/ts/core/qweb_vdom";
import { idGenerator } from "../src/ts/core/utils";
import { WEnv } from "../src/ts/core/widget";
import { WEnv } from "../src/ts/core/base_widget";
import { Env } from "../src/ts/env";
import { IAjax, RPCQuery } from "../src/ts/core/ajax";
import { Registry } from "../src/ts/core/registry";