diff --git a/web/static/src/ts/core/Widget.ts b/web/static/src/ts/core/Widget.ts index 1cc986be..7aa71c99 100644 --- a/web/static/src/ts/core/Widget.ts +++ b/web/static/src/ts/core/Widget.ts @@ -23,8 +23,8 @@ interface Meta { isStarted: boolean; isMounted: boolean; isDestroyed: boolean; - parent: Widget | null; - children: { [key: number]: Widget }; + parent: Widget | null; + children: { [key: number]: Widget }; // children mapping: from templateID to widgetID // should it be a map number => Widget? cmap: { [key: number]: number }; @@ -35,7 +35,7 @@ const patch = init([sdListeners, sdAttrs]); //------------------------------------------------------------------------------ // Widget //------------------------------------------------------------------------------ -export class Widget { +export class Widget { __widget__: Meta; name: string = "widget"; template: string = "
"; @@ -46,18 +46,18 @@ export class Widget { env: T; state: Object = {}; - props: any; - refs: { [key: string]: Widget | HTMLElement | undefined } = {}; + props: Props | undefined; + refs: { [key: string]: Widget | HTMLElement | undefined } = {}; //-------------------------------------------------------------------------- // Lifecycle //-------------------------------------------------------------------------- - constructor(parent: Widget | T, props?: any) { + constructor(parent: Widget | T, props?: Props) { wl.push(this); this.props = props; let id: number; - let p: Widget | null = null; + let p: Widget | null = null; if (parent instanceof Widget) { p = parent; this.env = parent.env; @@ -83,7 +83,7 @@ export class Widget { mounted() {} - shouldUpdate(nextProps: any): boolean { + shouldUpdate(nextProps: Props): boolean { return true; } @@ -147,7 +147,7 @@ export class Widget { } } - updateProps(nextProps?: any): Promise { + updateProps(nextProps: Props): Promise { const shouldUpdate = this.shouldUpdate(nextProps); this.props = nextProps; return shouldUpdate ? this.render() : Promise.resolve(); @@ -205,7 +205,7 @@ export class Widget { } } - private visitSubTree(callback: (w: Widget) => void) { + private visitSubTree(callback: (w: Widget) => void) { callback(this); const children = this.__widget__.children; for (let id in children) { diff --git a/web/static/src/ts/registry.ts b/web/static/src/ts/registry.ts index 75e7ca71..8fa771e7 100644 --- a/web/static/src/ts/registry.ts +++ b/web/static/src/ts/registry.ts @@ -6,7 +6,7 @@ import { Type } from "./types"; // Types //------------------------------------------------------------------------------ -type ActionWidget = Type>; +type ActionWidget = Type>; //------------------------------------------------------------------------------ // Registry code diff --git a/web/static/src/ts/services/action_manager.ts b/web/static/src/ts/services/action_manager.ts index 5a099ed0..6fa5595f 100644 --- a/web/static/src/ts/services/action_manager.ts +++ b/web/static/src/ts/services/action_manager.ts @@ -33,7 +33,7 @@ export type Action = ClientAction | ActWindowAction; export interface ActionWidget { id: number; - Widget: Type>; + Widget: Type>; props: any; } diff --git a/web/static/src/ts/widgets/CRM.ts b/web/static/src/ts/widgets/CRM.ts index a9299a74..0bdc27d0 100644 --- a/web/static/src/ts/widgets/CRM.ts +++ b/web/static/src/ts/widgets/CRM.ts @@ -7,7 +7,7 @@ const template = ` `; -export class CRM extends Widget { +export class CRM extends Widget { name = "crm"; template = template; } diff --git a/web/static/src/ts/widgets/Counter.ts b/web/static/src/ts/widgets/Counter.ts index c8c5de0b..e4e2cc9c 100644 --- a/web/static/src/ts/widgets/Counter.ts +++ b/web/static/src/ts/widgets/Counter.ts @@ -9,15 +9,19 @@ const template = ` `; -export class Counter extends Widget { +interface Props { + initialState?: number; +} + +export class Counter extends Widget { name = "counter"; template = template; state = { counter: 0 }; - constructor(parent: Widget, props: { initialState?: number }) { - super(parent); + constructor(parent: Widget, props: Props) { + super(parent, props); this.state.counter = props.initialState || 0; } diff --git a/web/static/src/ts/widgets/Discuss.ts b/web/static/src/ts/widgets/Discuss.ts index 9796f4cf..cd5fae28 100644 --- a/web/static/src/ts/widgets/Discuss.ts +++ b/web/static/src/ts/widgets/Discuss.ts @@ -23,7 +23,7 @@ const template = ` `; -export class Discuss extends Widget { +export class Discuss extends Widget { name = "discuss"; template = template; widgets = { Clock, Counter, ColorWidget }; @@ -54,7 +54,7 @@ export class Discuss extends Widget { } } -class ColorWidget extends Widget { +class ColorWidget extends Widget { name = "colorwidget"; template = `
Current Color:
`; } diff --git a/web/static/src/ts/widgets/Navbar.ts b/web/static/src/ts/widgets/Navbar.ts index 081f5b03..ba408d00 100644 --- a/web/static/src/ts/widgets/Navbar.ts +++ b/web/static/src/ts/widgets/Navbar.ts @@ -14,7 +14,7 @@ const template = ` `; -export class Navbar extends Widget { +export class Navbar extends Widget { name = "navbar"; template = template; diff --git a/web/static/src/ts/widgets/clock.ts b/web/static/src/ts/widgets/clock.ts index 0496777a..a0211a60 100644 --- a/web/static/src/ts/widgets/clock.ts +++ b/web/static/src/ts/widgets/clock.ts @@ -3,7 +3,7 @@ import { Env } from "../env"; const template = `
`; -export class Clock extends Widget { +export class Clock extends Widget { name = "clock"; template = template; interval: any | undefined; diff --git a/web/static/src/ts/widgets/root_widget.ts b/web/static/src/ts/widgets/root_widget.ts index 714600a1..90d95b48 100644 --- a/web/static/src/ts/widgets/root_widget.ts +++ b/web/static/src/ts/widgets/root_widget.ts @@ -11,11 +11,11 @@ const template = ` `; -export class RootWidget extends Widget { +export class RootWidget extends Widget { name = "root"; template = template; widgets = { Navbar }; - content: Widget | null = null; + content: Widget | null = null; mounted() { this.env.actionManager.on("action_ready", this, this.setContentWidget); diff --git a/web/static/tests/core/widget.test.ts b/web/static/tests/core/widget.test.ts index 66708366..6d71908c 100644 --- a/web/static/tests/core/widget.test.ts +++ b/web/static/tests/core/widget.test.ts @@ -31,13 +31,13 @@ function nextTick(): Promise { return Promise.resolve(); } -function children(w: Widget): Widget[] { +function children(w: Widget): Widget[] { const childrenMap = w.__widget__.children; return Object.keys(childrenMap).map(id => childrenMap[id]); } // Test widgets -class Counter extends Widget { +class Counter extends Widget { name = "counter"; template = `
`; state = { @@ -49,13 +49,13 @@ class Counter extends Widget { } } -class WidgetA extends Widget { +class WidgetA extends Widget { name = "a"; template = `
Hello
`; widgets = { b: WidgetB }; } -class WidgetB extends Widget { +class WidgetB extends Widget { template = `
world
`; } @@ -87,7 +87,7 @@ describe("basic widget properties", () => { }); test("widget style and classname", async () => { - class StyledWidget extends Widget { + class StyledWidget extends Widget { template = `
world
`; } const widget = new StyledWidget(env); @@ -99,7 +99,7 @@ describe("basic widget properties", () => { test("updateState before first render does not trigger a render", async () => { let renderCalls = 0; - class TestW extends Widget { + class TestW extends Widget { async willStart() { this.updateState({}); } @@ -132,7 +132,7 @@ describe("basic widget properties", () => { describe("lifecycle hooks", () => { test("willStart hook is called", async () => { let willstart = false; - class HookWidget extends Widget { + class HookWidget extends Widget { async willStart() { willstart = true; } @@ -144,7 +144,7 @@ describe("lifecycle hooks", () => { test("mounted hook is not called if not in DOM", async () => { let mounted = false; - class HookWidget extends Widget { + class HookWidget extends Widget { async mounted() { mounted = true; } @@ -157,7 +157,7 @@ describe("lifecycle hooks", () => { test("mounted hook is called if mounted in DOM", async () => { let mounted = false; - class HookWidget extends Widget { + class HookWidget extends Widget { async mounted() { mounted = true; } @@ -169,12 +169,12 @@ describe("lifecycle hooks", () => { test("willStart hook is called on subwidget", async () => { let ok = false; - class ParentWidget extends Widget { + class ParentWidget extends Widget { name = "a"; template = `
`; widgets = { child: ChildWidget }; } - class ChildWidget extends Widget { + class ChildWidget extends Widget { async willStart() { ok = true; } @@ -188,7 +188,7 @@ describe("lifecycle hooks", () => { expect.assertions(4); let parentMounted = false; let childMounted = false; - class ParentWidget extends Widget { + class ParentWidget extends Widget { name = "a"; template = `
`; widgets = { child: ChildWidget }; @@ -197,7 +197,7 @@ describe("lifecycle hooks", () => { parentMounted = true; } } - class ChildWidget extends Widget { + class ChildWidget extends Widget { mounted() { expect(document.body.contains(this.el)).toBe(true); expect(parentMounted).toBe(true); @@ -212,7 +212,7 @@ describe("lifecycle hooks", () => { test("willStart, mounted on subwidget rendered after main is mounted in some other position", async () => { expect.assertions(3); let hookCounter = 0; - class ParentWidget extends Widget { + class ParentWidget extends Widget { name = "a"; state = { ok: false }; template = ` @@ -228,7 +228,7 @@ describe("lifecycle hooks", () => { // patching algorithm widgets = { child: ChildWidget }; } - class ChildWidget extends Widget { + class ChildWidget extends Widget { async willStart() { hookCounter++; } @@ -253,14 +253,14 @@ describe("lifecycle hooks", () => { expect.assertions(1); const target = document.createElement("div"); document.body.appendChild(target); - class ParentWidget extends Widget { + class ParentWidget extends Widget { name = "a"; mounted() { const child = new ChildWidget(this); child.mount(this.el!); } } - class ChildWidget extends Widget { + class ChildWidget extends Widget { mounted() { expect(this.el).toBeTruthy(); done(); @@ -272,7 +272,7 @@ describe("lifecycle hooks", () => { test("widgets are unmounted and destroyed if no longer in DOM", async () => { let steps: string[] = []; - class ParentWidget extends Widget { + class ParentWidget extends Widget { name = "a"; state = { ok: true }; template = ` @@ -282,7 +282,7 @@ describe("lifecycle hooks", () => { widgets = { child: ChildWidget }; } - class ChildWidget extends Widget { + class ChildWidget extends Widget { constructor(parent) { super(parent); steps.push("init"); @@ -315,7 +315,7 @@ describe("lifecycle hooks", () => { test("hooks are called in proper order in widget creation/destruction", async () => { let steps: string[] = []; - class ParentWidget extends Widget { + class ParentWidget extends Widget { name = "a"; template = `
`; @@ -338,7 +338,7 @@ describe("lifecycle hooks", () => { } } - class ChildWidget extends Widget { + class ChildWidget extends Widget { constructor(parent) { super(parent); steps.push("c init"); @@ -375,7 +375,7 @@ describe("lifecycle hooks", () => { test("shouldUpdate hook prevent rerendering", async () => { let shouldUpdate = false; - class TestWidget extends Widget { + class TestWidget extends Widget { name = "a"; template = `
`; shouldUpdate() { @@ -406,7 +406,7 @@ describe("destroy method", () => { test("destroying a widget twice only call destroyed once", async () => { let count = 0; - class TestWidget extends Widget { + class TestWidget extends Widget { destroyed() { count++; } @@ -448,7 +448,7 @@ describe("destroy method", () => { let p: Promise = new Promise(function(r) { resolve = r; }); - class DelayedWidget extends Widget { + class DelayedWidget extends Widget { willStart() { return p; } @@ -488,7 +488,7 @@ describe("composition", () => { }); test("t-refs on widget are widgets", async () => { - class WidgetC extends Widget { + class WidgetC extends Widget { name = "a"; template = `
Hello
`; widgets = { b: WidgetB }; @@ -499,7 +499,7 @@ describe("composition", () => { }); test("modifying a sub widget", async () => { - class ParentWidget extends Widget { + class ParentWidget extends Widget { template = `
`; widgets = { Counter }; } @@ -537,7 +537,7 @@ describe("composition", () => { }); test("rerendering a widget with a sub widget", async () => { - class ParentWidget extends Widget { + class ParentWidget extends Widget { template = `
`; widgets = { Counter }; } @@ -556,7 +556,7 @@ describe("composition", () => { }); test("sub widgets are destroyed if no longer in dom, then recreated", async () => { - class ParentWidget extends Widget { + class ParentWidget extends Widget { name = "a"; state = { ok: true }; template = ` @@ -582,14 +582,14 @@ describe("composition", () => { describe("props evaluation (with t-props directive)", () => { test("explicit object prop", async () => { - class Parent extends Widget { + class Parent extends Widget { name = "a"; template = `
`; widgets = { child: Child }; state = { val: 42 }; } - class Child extends Widget { + class Child extends Widget { template = ``; state: { someval: number }; constructor(parent: Parent, props: { value: number }) { @@ -604,14 +604,14 @@ describe("props evaluation (with t-props directive)", () => { }); test("object prop value", async () => { - class Parent extends Widget { + class Parent extends Widget { name = "a"; template = `
`; widgets = { child: Child }; state = { val: 42 }; } - class Child extends Widget { + class Child extends Widget { template = ``; state: { someval: number }; constructor(parent: Parent, props: { val: number }) {