From 6558a34411648ca5e104617323504b76d0660110 Mon Sep 17 00:00:00 2001 From: aski97 Date: Fri, 21 Aug 2026 14:25:48 +0200 Subject: [PATCH 01/14] [IMP] awesome_owl: create counter component and add to playground --- awesome_owl/static/src/counter/counter.js | 13 +++++++++++++ awesome_owl/static/src/counter/counter.xml | 11 +++++++++++ awesome_owl/static/src/playground.js | 6 +++++- awesome_owl/static/src/playground.xml | 8 ++++++-- 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 awesome_owl/static/src/counter/counter.js create mode 100644 awesome_owl/static/src/counter/counter.xml diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js new file mode 100644 index 00000000000..516b916c314 --- /dev/null +++ b/awesome_owl/static/src/counter/counter.js @@ -0,0 +1,13 @@ +import { Component, useState } from "@odoo/owl"; + +export class Counter extends Component { + static template = "awesome_owl.counter"; + + setup() { + this.state = useState({ value: 0}); + } + + increment() { + this.state.value++; + } +} diff --git a/awesome_owl/static/src/counter/counter.xml b/awesome_owl/static/src/counter/counter.xml new file mode 100644 index 00000000000..eac5cb5d9cb --- /dev/null +++ b/awesome_owl/static/src/counter/counter.xml @@ -0,0 +1,11 @@ + + + + +
+

Counter:

+ +
+
+ +
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 4ac769b0aa5..853bad89082 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,5 +1,9 @@ -import { Component } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; +import { Counter } from "./counter/counter"; export class Playground extends Component { static template = "awesome_owl.playground"; + + static components = { Counter }; + } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 4fb905d59f9..05b6551be0d 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -2,8 +2,12 @@ -
- hello world +
+
+

hello world

+
+ +
From c27b6fe9e9b25a32702f2128ecf851cf4a4679a4 Mon Sep 17 00:00:00 2001 From: aski97 Date: Fri, 21 Aug 2026 14:54:29 +0200 Subject: [PATCH 02/14] [IMP] awesome_owl: create card component --- awesome_owl/static/src/card/card.js | 6 ++++++ awesome_owl/static/src/card/card.xml | 13 +++++++++++++ awesome_owl/static/src/playground.js | 3 ++- awesome_owl/static/src/playground.xml | 9 +++------ 4 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 awesome_owl/static/src/card/card.js create mode 100644 awesome_owl/static/src/card/card.xml diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js new file mode 100644 index 00000000000..0a507042145 --- /dev/null +++ b/awesome_owl/static/src/card/card.js @@ -0,0 +1,6 @@ +import { Component } from "@odoo/owl"; + +export class Card extends Component { + static template = "awesome_owl.card"; + +} diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml new file mode 100644 index 00000000000..fd55f928e84 --- /dev/null +++ b/awesome_owl/static/src/card/card.xml @@ -0,0 +1,13 @@ + + + + +
+
+
+

+
+
+
+ +
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 853bad89082..97bb0853712 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,9 +1,10 @@ import { Component, useState } from "@odoo/owl"; import { Counter } from "./counter/counter"; +import { Card } from "./card/card"; export class Playground extends Component { static template = "awesome_owl.playground"; - static components = { Counter }; + static components = { Counter, Card}; } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 05b6551be0d..699eef10945 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -2,12 +2,9 @@ -
-
-

hello world

-
- - +
+ +
From 52fbd01554b158a14dd2098465047a163d966594 Mon Sep 17 00:00:00 2001 From: aski97 Date: Mon, 24 Aug 2026 11:30:01 +0200 Subject: [PATCH 03/14] [IMP] awesome_owl: add props validation. --- awesome_owl/static/src/card/card.js | 12 +++++++++++- awesome_owl/static/src/card/card.xml | 6 +++++- awesome_owl/static/src/playground.xml | 4 +++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 0a507042145..e7d775cf701 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -2,5 +2,15 @@ import { Component } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card"; - + static props = { + title: String, + body: { type: String, optional: true }, + slots: { + type: Object, + optional: true, + shape: { + default: { optional: true }, + }, + }, + }; } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index fd55f928e84..5b5d92f7044 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -5,7 +5,11 @@
-

+
+ + + +
diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 699eef10945..6fcac8dfce4 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -4,7 +4,9 @@
- + +
Content 2
+
From a0dc999750e3e4f0e518d6739e5dea75742bc9df Mon Sep 17 00:00:00 2001 From: aski97 Date: Mon, 24 Aug 2026 13:43:00 +0200 Subject: [PATCH 04/14] [IMP] awesome_owl: add dynamic compute of the sum of one or multiple counters (controlled by the parent) --- awesome_owl/static/src/counter/counter.js | 16 +++++++++++++++- awesome_owl/static/src/playground.js | 22 ++++++++++++++++++++++ awesome_owl/static/src/playground.xml | 14 +++++++++----- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js index 516b916c314..61599aa9584 100644 --- a/awesome_owl/static/src/counter/counter.js +++ b/awesome_owl/static/src/counter/counter.js @@ -3,11 +3,25 @@ import { Component, useState } from "@odoo/owl"; export class Counter extends Component { static template = "awesome_owl.counter"; + static props = { + initialValue: { type: Number, optional: true}, + onChange: { type: Function, optional: true }, + onRegister: { type: Function, optional: true }, + }; + setup() { - this.state = useState({ value: 0}); + this.state = useState({ value: this.props.initialValue ?? 0}); + + if (this.props.onRegister) { + this.props.onRegister(this) + } } increment() { this.state.value++; + + if (this.props.onChange) { + this.props.onChange(); + } } } diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 97bb0853712..2140b732d0f 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -7,4 +7,26 @@ export class Playground extends Component { static components = { Counter, Card}; + setup() { + /* + I define the counters here so I can show them as much as I want + */ + this.state = useState({ + counters_num: 2, + counters_ref: [] + }); + } + + // It registry the reference of the child here + registerCounter(id, counterInstance) { + this.state.counters_ref[id] = counterInstance; + } + + get sum() { + return this.state.counters_ref.reduce( + (acc, counter) => acc + (counter?.state?.value || 0), + 0 + ) + } + } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 6fcac8dfce4..e00e108dc75 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -2,12 +2,16 @@ -
- - -
Content 2
-
+
+
+ + + +
+ +
The sum is:
+ From a728417ef48335065298a81ff64c8e6e3eadcf1a Mon Sep 17 00:00:00 2001 From: aski97 Date: Mon, 24 Aug 2026 15:46:12 +0200 Subject: [PATCH 05/14] [IMP] awesome_owl: add dynamic todo component in the playground --- awesome_owl/static/src/playground.js | 3 +- awesome_owl/static/src/playground.xml | 6 ++++ awesome_owl/static/src/todo_list/TodoItem.js | 19 +++++++++++ awesome_owl/static/src/todo_list/TodoList.js | 33 +++++++++++++++++++ .../static/src/todo_list/todo_item.xml | 8 +++++ .../static/src/todo_list/todo_list.xml | 13 ++++++++ 6 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 awesome_owl/static/src/todo_list/TodoItem.js create mode 100644 awesome_owl/static/src/todo_list/TodoList.js create mode 100644 awesome_owl/static/src/todo_list/todo_item.xml create mode 100644 awesome_owl/static/src/todo_list/todo_list.xml diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 2140b732d0f..0642f24b6c7 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,11 +1,12 @@ import { Component, useState } from "@odoo/owl"; import { Counter } from "./counter/counter"; import { Card } from "./card/card"; +import { TodoList } from "./todo_list/TodoList"; export class Playground extends Component { static template = "awesome_owl.playground"; - static components = { Counter, Card}; + static components = { Counter, Card, TodoList}; setup() { /* diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index e00e108dc75..2ec727f901e 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -12,6 +12,12 @@
The sum is:
+
+
+ +
+
+
diff --git a/awesome_owl/static/src/todo_list/TodoItem.js b/awesome_owl/static/src/todo_list/TodoItem.js new file mode 100644 index 00000000000..c0554e6e33d --- /dev/null +++ b/awesome_owl/static/src/todo_list/TodoItem.js @@ -0,0 +1,19 @@ +import { Component, useState} from "@odoo/owl"; + +export class TodoItem extends Component { + static template = "awesome_owl.todo_item"; + + static props = { + id: Number, + description: String, + isCompleted: Boolean, + }; + + setup() { + this.state = useState({ + id: this.props.id, + description: this.props.description, + isCompleted: this.props.isCompleted + }) + } +} diff --git a/awesome_owl/static/src/todo_list/TodoList.js b/awesome_owl/static/src/todo_list/TodoList.js new file mode 100644 index 00000000000..bbfb902a25b --- /dev/null +++ b/awesome_owl/static/src/todo_list/TodoList.js @@ -0,0 +1,33 @@ +import { Component, useState} from "@odoo/owl"; +import { TodoItem } from "./TodoItem"; + +export class TodoList extends Component { + static template = "awesome_owl.todo_list"; + + static components = { TodoItem }; + + setup() { + this.todos = useState([ ]); + this.state = useState({ + next_id: 1, + }) + } + + onInputKeyup(ev) { + if (ev.key === "Enter") { + const value = ev.target.value.trim(); + if (value) { + const next_id = this.state.next_id++; + this.todos.push( + { + id: next_id, + description: value, + isCompleted: false + } + ) + ev.target.value = ""; + } + } + } + +} diff --git a/awesome_owl/static/src/todo_list/todo_item.xml b/awesome_owl/static/src/todo_list/todo_item.xml new file mode 100644 index 00000000000..669b2035a02 --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_item.xml @@ -0,0 +1,8 @@ + + + + +

.

+
+ +
diff --git a/awesome_owl/static/src/todo_list/todo_list.xml b/awesome_owl/static/src/todo_list/todo_list.xml new file mode 100644 index 00000000000..0af17aeef05 --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_list.xml @@ -0,0 +1,13 @@ + + + + + +
    + +
  • +
    +
+
+ +
From fc3252d493672c62e1aca61cdf4386f50b415471 Mon Sep 17 00:00:00 2001 From: aski97 Date: Tue, 25 Aug 2026 14:22:28 +0200 Subject: [PATCH 06/14] [IMP] awesome_owl: add the focus on todo input, the toggle and the delete feature. --- awesome_owl/static/src/todo_list/TodoItem.js | 18 ++++++++----- awesome_owl/static/src/todo_list/TodoList.js | 26 +++++++++++++++++-- .../static/src/todo_list/todo_item.xml | 8 +++++- .../static/src/todo_list/todo_list.xml | 4 +-- awesome_owl/static/src/utils.js | 9 +++++++ 5 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 awesome_owl/static/src/utils.js diff --git a/awesome_owl/static/src/todo_list/TodoItem.js b/awesome_owl/static/src/todo_list/TodoItem.js index c0554e6e33d..6610c4af1c4 100644 --- a/awesome_owl/static/src/todo_list/TodoItem.js +++ b/awesome_owl/static/src/todo_list/TodoItem.js @@ -7,13 +7,19 @@ export class TodoItem extends Component { id: Number, description: String, isCompleted: Boolean, + toggleState: Function, + onRemove: Function }; - setup() { - this.state = useState({ - id: this.props.id, - description: this.props.description, - isCompleted: this.props.isCompleted - }) + toggleTodo() { + if (this.props.toggleState) { + this.props.toggleState(this.props.id) + } + } + + removeTodo() { + if (this.props.onRemove) { + this.props.onRemove(this.props.id) + } } } diff --git a/awesome_owl/static/src/todo_list/TodoList.js b/awesome_owl/static/src/todo_list/TodoList.js index bbfb902a25b..6c0a80ae087 100644 --- a/awesome_owl/static/src/todo_list/TodoList.js +++ b/awesome_owl/static/src/todo_list/TodoList.js @@ -1,5 +1,6 @@ -import { Component, useState} from "@odoo/owl"; +import { Component, useState, useRef, onMounted } from "@odoo/owl"; import { TodoItem } from "./TodoItem"; +import { useAutofocus} from "./../utils" export class TodoList extends Component { static template = "awesome_owl.todo_list"; @@ -10,7 +11,9 @@ export class TodoList extends Component { this.todos = useState([ ]); this.state = useState({ next_id: 1, - }) + }); + useAutofocus("input_todo"); + } onInputKeyup(ev) { @@ -30,4 +33,23 @@ export class TodoList extends Component { } } + toogleTodoState(id) { + if (!id) { + return; + } + const todo = this.todos.find(item => item.id === id); + + if (!todo) { + return; + } + todo.isCompleted = !todo.isCompleted + } + + removeTodo(id) { + const index = this.todos.findIndex((elem) => elem.id === id); + if (index >= 0) { + this.todos.splice(index, 1); + } + } + } diff --git a/awesome_owl/static/src/todo_list/todo_item.xml b/awesome_owl/static/src/todo_list/todo_item.xml index 669b2035a02..e967ed34e58 100644 --- a/awesome_owl/static/src/todo_list/todo_item.xml +++ b/awesome_owl/static/src/todo_list/todo_item.xml @@ -2,7 +2,13 @@ -

.

+
+ + + +
diff --git a/awesome_owl/static/src/todo_list/todo_list.xml b/awesome_owl/static/src/todo_list/todo_list.xml index 0af17aeef05..6c0a81dab9e 100644 --- a/awesome_owl/static/src/todo_list/todo_list.xml +++ b/awesome_owl/static/src/todo_list/todo_list.xml @@ -2,10 +2,10 @@ - +
    -
  • +
diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js new file mode 100644 index 00000000000..21689fd51e8 --- /dev/null +++ b/awesome_owl/static/src/utils.js @@ -0,0 +1,9 @@ +import { useRef, useEffect } from "@odoo/owl"; + +export function useAutofocus(name) { + let ref = useRef(name); + useEffect( + (el) => el && el.focus(), + () => [ref.el] + ); +} From 4778518576b3b4c41ace4128db1ff00f054bc75c Mon Sep 17 00:00:00 2001 From: aski97 Date: Tue, 25 Aug 2026 15:23:49 +0200 Subject: [PATCH 07/14] [IMP] awesome_owl: add the toggle card content --- awesome_owl/static/src/card/card.js | 17 ++++++++++++++++- awesome_owl/static/src/card/card.xml | 13 ++++++++++--- awesome_owl/static/src/playground.xml | 9 +++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index e7d775cf701..0cf2d816f61 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -1,4 +1,4 @@ -import { Component } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card"; @@ -12,5 +12,20 @@ export class Card extends Component { default: { optional: true }, }, }, + toggleMode: { + type: Boolean, + } }; + + setup() { + this.state = useState({ + isToggleOn: false + }); + } + + toggle() { + if (this.props.toggleMode) { + this.state.isToggleOn = !this.state.isToggleOn; + } + } } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 5b5d92f7044..c3f56a84535 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -4,11 +4,18 @@
-
+
+ + + + +
- - + +
+ +
diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 2ec727f901e..78e07121357 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -18,6 +18,15 @@
+
+ + + + + + + +
From c4ad164c7812deae8f555cb72996861d0e43fe3a Mon Sep 17 00:00:00 2001 From: aski97 Date: Tue, 25 Aug 2026 17:26:50 +0200 Subject: [PATCH 08/14] [IMP] awesome_dashboard: add basic layout to the dashboard with two buttons. --- awesome_dashboard/static/src/dashboard.js | 32 +++++++++++++++++++++ awesome_dashboard/static/src/dashboard.scss | 3 ++ awesome_dashboard/static/src/dashboard.xml | 13 ++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 awesome_dashboard/static/src/dashboard.scss diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index c4fb245621b..1d9a89a9a9d 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,8 +1,40 @@ import { Component } from "@odoo/owl"; +import { _t } from "@web/core/l10n/translation"; +import { useService } from "@web/core/utils/hooks"; +import { Layout } from "@web/search/layout"; import { registry } from "@web/core/registry"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; + static components = { + Layout + }; + + setup() { + this.display = { + controlPanel: {}, + }; + this.action = useService("action"); + } + + openCustomers() { + this.action.doAction("base.action_partner_form", { + viewType: "kanban" + }); + } + + openLeads() { + this.action.doAction({ + type: 'ir.actions.act_window', + name: _t('Leads'), + target: 'new', + res_model: "crm.lead", + views: [ + [false, "list"], + [false, "form"] + ], + }); + } } registry.category("actions").add("awesome_dashboard.dashboard", AwesomeDashboard); diff --git a/awesome_dashboard/static/src/dashboard.scss b/awesome_dashboard/static/src/dashboard.scss new file mode 100644 index 00000000000..94f7569d0b2 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard.scss @@ -0,0 +1,3 @@ +.o_dashboard { + background-color: #5f5e5e; +} diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 1a2ac9a2fed..845600c13e4 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -2,7 +2,18 @@ - hello dashboard +
+ + + + + + +
+

Dashboard Content

+
+
+
From e931f1d9da672e986b82e94d711285f410cadea6 Mon Sep 17 00:00:00 2001 From: aski97 Date: Wed, 26 Aug 2026 13:28:47 +0200 Subject: [PATCH 09/14] [IMP] awesome_dashboard: add dashboard item --- awesome_dashboard/static/src/dashboard.js | 7 ++--- awesome_dashboard/static/src/dashboard.xml | 10 ++++++- .../src/dashboard_item/dashboard_item.js | 28 +++++++++++++++++++ .../src/dashboard_item/dashboard_item.xml | 14 ++++++++++ 4 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard_item/dashboard_item.js create mode 100644 awesome_dashboard/static/src/dashboard_item/dashboard_item.xml diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 1d9a89a9a9d..6e1e1a232fc 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -3,12 +3,11 @@ import { _t } from "@web/core/l10n/translation"; import { useService } from "@web/core/utils/hooks"; import { Layout } from "@web/search/layout"; import { registry } from "@web/core/registry"; +import { DashboardItem } from "./dashboard_item/dashboard_item" class AwesomeDashboard extends Component { - static template = "awesome_dashboard.AwesomeDashboard"; - static components = { - Layout - }; + static template = "awesome_dashboard.AwesomeDashboard"; + static components = { Layout, DashboardItem }; setup() { this.display = { diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 845600c13e4..1da02f9d8b1 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -10,7 +10,15 @@
-

Dashboard Content

+ + some content + + + some content + + + some content +
diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.js b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js new file mode 100644 index 00000000000..956e87370f9 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js @@ -0,0 +1,28 @@ +import { Component, useState } from "@odoo/owl"; + +export class DashboardItem extends Component { + static template = "awesome_owl.dashboard_item"; + static props = { + title: String, + size: { type: Number, optional: true }, + slots: { + type: Object, + optional: true, + shape: { + default: { optional: true }, + }, + }, + }; + + static defaultProps = { + size: 1 + } + + setup() { + } + + get cardWidth() { + return 18 * this.props.size; + } + +} diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml new file mode 100644 index 00000000000..ae4f1278e11 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml @@ -0,0 +1,14 @@ + + + + +
+
+
+ +
+
+
+
+ +
From 8f1651e03ce6bc10241f6bcfc17500b675d278aa Mon Sep 17 00:00:00 2001 From: aski97 Date: Wed, 26 Aug 2026 15:21:16 +0200 Subject: [PATCH 10/14] [IMP] awesome_dashboard: add cache to dashboard statistics --- awesome_dashboard/static/src/dashboard.js | 19 +++++++++++++------ awesome_dashboard/static/src/dashboard.xml | 17 ++++++++++++++--- .../src/dashboard_item/dashboard_item.js | 4 +++- .../src/dashboard_item/dashboard_item.xml | 4 ++++ .../static/src/dashboard_stats_service.js | 18 ++++++++++++++++++ 5 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard_stats_service.js diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 6e1e1a232fc..a2029afa2f2 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,9 +1,9 @@ -import { Component } from "@odoo/owl"; -import { _t } from "@web/core/l10n/translation"; -import { useService } from "@web/core/utils/hooks"; -import { Layout } from "@web/search/layout"; -import { registry } from "@web/core/registry"; -import { DashboardItem } from "./dashboard_item/dashboard_item" +import {Component, onWillStart, useState} from "@odoo/owl"; +import {_t} from "@web/core/l10n/translation"; +import {useService} from "@web/core/utils/hooks"; +import {Layout} from "@web/search/layout"; +import {registry} from "@web/core/registry"; +import {DashboardItem} from "./dashboard_item/dashboard_item" class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -14,6 +14,13 @@ class AwesomeDashboard extends Component { controlPanel: {}, }; this.action = useService("action"); + + this.dashStatsService = useService("awesome_dashboard.statistics"); + + onWillStart(async () => { + this.stats = await this.dashStatsService.loadStatistics(); + }) + } openCustomers() { diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 1da02f9d8b1..db78b74b8ff 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -11,13 +11,24 @@
- some content + Number of new orders this month + + + + Total amount of new orders this month + - some content + Average amount of t-shirt by order this month + - some content + Number of cancelled orders this month + + + + Average time for an order to go from ‘new’ to ‘sent’ or ‘cancelled’ +
diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.js b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js index 956e87370f9..b2e33d9635e 100644 --- a/awesome_dashboard/static/src/dashboard_item/dashboard_item.js +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js @@ -1,4 +1,4 @@ -import { Component, useState } from "@odoo/owl"; +import { Component } from "@odoo/owl"; export class DashboardItem extends Component { static template = "awesome_owl.dashboard_item"; @@ -10,6 +10,8 @@ export class DashboardItem extends Component { optional: true, shape: { default: { optional: true }, + title: String, + value: String }, }, }; diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml index ae4f1278e11..0441809f2c0 100644 --- a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml @@ -4,7 +4,11 @@
+
+ +
+

diff --git a/awesome_dashboard/static/src/dashboard_stats_service.js b/awesome_dashboard/static/src/dashboard_stats_service.js new file mode 100644 index 00000000000..593c5cc79aa --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_stats_service.js @@ -0,0 +1,18 @@ +import { registry } from "@web/core/registry"; +import { rpc } from "@web/core/network/rpc"; +import { memoize } from "@web/core/utils/functions"; + +export async function loadStatistics() { + return rpc("/awesome_dashboard/statistics"); +} + +export const dashboardStatsService = { + dependencies: [], + start() { + return { + loadStatistics: memoize(loadStatistics) + }; + }, +}; + +registry.category("services").add("awesome_dashboard.statistics", dashboardStatsService); From 8c569fd568d75d9f44ce643c3cb7390d6022dca3 Mon Sep 17 00:00:00 2001 From: aski97 Date: Wed, 26 Aug 2026 16:45:13 +0200 Subject: [PATCH 11/14] [IMP] awesome_dashboard: display a pie chart. --- .../static/src/chart/pie_chart/pie_chart.js | 54 +++++++++++++++++++ .../static/src/chart/pie_chart/pie_chart.xml | 8 +++ awesome_dashboard/static/src/dashboard.js | 3 +- awesome_dashboard/static/src/dashboard.xml | 4 ++ .../src/dashboard_item/dashboard_item.xml | 2 +- 5 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 awesome_dashboard/static/src/chart/pie_chart/pie_chart.js create mode 100644 awesome_dashboard/static/src/chart/pie_chart/pie_chart.xml diff --git a/awesome_dashboard/static/src/chart/pie_chart/pie_chart.js b/awesome_dashboard/static/src/chart/pie_chart/pie_chart.js new file mode 100644 index 00000000000..29405774d4a --- /dev/null +++ b/awesome_dashboard/static/src/chart/pie_chart/pie_chart.js @@ -0,0 +1,54 @@ +import {Component, onWillStart, onWillUnmount, useEffect, useRef} from "@odoo/owl"; +import { loadJS } from "@web/core/assets"; + +export class PieChart extends Component { + static template = "awesome_owl.pie_chart"; + static props = { + dataset: { + type: Object + }, + }; + + setup() { + this.chart = null; + this.canvasRef = useRef("canvas"); + onWillStart(() => loadJS("/web/static/lib/Chart/Chart.js")); + useEffect(() => this.renderChart()); + onWillUnmount(this.onWillUnmount); + } + + destroyChart() { + if (this.chart) { + this.chart.destroy(); + } + } + + onWillUnmount() { + this.destroyChart(); + } + + renderChart() { + this.destroyChart(); + const config = this.getChartConfig(); + this.chart = new Chart(this.canvasRef.el, config); + } + + getChartConfig() { + const labels = Object.keys(this.props.dataset); + + const data = Object.values(this.props.dataset); + + return { + type: 'pie', + data: { + labels: labels, + datasets: [ + { + data: data, + } + ], + } + }; + } + +} diff --git a/awesome_dashboard/static/src/chart/pie_chart/pie_chart.xml b/awesome_dashboard/static/src/chart/pie_chart/pie_chart.xml new file mode 100644 index 00000000000..48161459cbf --- /dev/null +++ b/awesome_dashboard/static/src/chart/pie_chart/pie_chart.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index a2029afa2f2..bdcc10e861d 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -4,10 +4,11 @@ import {useService} from "@web/core/utils/hooks"; import {Layout} from "@web/search/layout"; import {registry} from "@web/core/registry"; import {DashboardItem} from "./dashboard_item/dashboard_item" +import {PieChart} from "./chart/pie_chart/pie_chart" class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; - static components = { Layout, DashboardItem }; + static components = { Layout, DashboardItem, PieChart }; setup() { this.display = { diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index db78b74b8ff..c2f7513ca97 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -30,6 +30,10 @@ Average time for an order to go from ‘new’ to ‘sent’ or ‘cancelled’ + + Shirt orders by size + +
diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml index 0441809f2c0..e2e35093453 100644 --- a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml @@ -2,7 +2,7 @@ -
+
From 430c99c3f9e8b531e31b82291c914cc9abe8d2f2 Mon Sep 17 00:00:00 2001 From: aski97 Date: Thu, 27 Aug 2026 11:39:33 +0200 Subject: [PATCH 12/14] [IMP] awesome_dashboard: update the statistics data every 10m keeping the cache for that time frame --- awesome_dashboard/static/src/dashboard.js | 51 ++++++++++++------- awesome_dashboard/static/src/dashboard.xml | 12 ++--- .../static/src/dashboard_stats_service.js | 7 ++- 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index bdcc10e861d..d0937e8cb38 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,4 +1,4 @@ -import {Component, onWillStart, useState} from "@odoo/owl"; +import {Component, onWillStart, useState, onWillUnmount } from "@odoo/owl"; import {_t} from "@web/core/l10n/translation"; import {useService} from "@web/core/utils/hooks"; import {Layout} from "@web/search/layout"; @@ -11,18 +11,31 @@ class AwesomeDashboard extends Component { static components = { Layout, DashboardItem, PieChart }; setup() { - this.display = { - controlPanel: {}, - }; - this.action = useService("action"); + this.display = { + controlPanel: {}, + }; + this.action = useService("action"); - this.dashStatsService = useService("awesome_dashboard.statistics"); + this.dashStatsService = useService("awesome_dashboard.statistics"); - onWillStart(async () => { - this.stats = await this.dashStatsService.loadStatistics(); - }) + this.state = useState({ + stats: {}, + }); - } + onWillStart(async () => { + this.state.stats = await this.dashStatsService.loadStatistics(); + }) + + const intervalId = setInterval(async () => { + const newStats = await this.dashStatsService.loadStatistics(); + // Update the stats state keeping the reference + Object.assign(this.state.stats, newStats); + }, 1000*60*10); + + onWillUnmount(() => { + clearInterval(intervalId); + }); + } openCustomers() { this.action.doAction("base.action_partner_form", { @@ -32,15 +45,15 @@ class AwesomeDashboard extends Component { openLeads() { this.action.doAction({ - type: 'ir.actions.act_window', - name: _t('Leads'), - target: 'new', - res_model: "crm.lead", - views: [ - [false, "list"], - [false, "form"] - ], - }); + type: 'ir.actions.act_window', + name: _t('Leads'), + target: 'new', + res_model: "crm.lead", + views: [ + [false, "list"], + [false, "form"] + ], + }); } } diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index c2f7513ca97..4ca0b262d27 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -12,27 +12,27 @@
Number of new orders this month - + Total amount of new orders this month - + Average amount of t-shirt by order this month - + Number of cancelled orders this month - + Average time for an order to go from ‘new’ to ‘sent’ or ‘cancelled’ - + Shirt orders by size - +
diff --git a/awesome_dashboard/static/src/dashboard_stats_service.js b/awesome_dashboard/static/src/dashboard_stats_service.js index 593c5cc79aa..8f65fed26f3 100644 --- a/awesome_dashboard/static/src/dashboard_stats_service.js +++ b/awesome_dashboard/static/src/dashboard_stats_service.js @@ -9,8 +9,13 @@ export async function loadStatistics() { export const dashboardStatsService = { dependencies: [], start() { + const memoizedLoad = memoize(loadStatistics); + + // Time key integer changing every 10m in order to miss the cache of memoize + const getTimeKey = () => Math.floor(Date.now() / 1000*60*10); + return { - loadStatistics: memoize(loadStatistics) + loadStatistics: () => memoizedLoad(getTimeKey()) }; }, }; From 969b9756503f938931aae50e22cd2f58d8f21a63 Mon Sep 17 00:00:00 2001 From: aski97 Date: Thu, 27 Aug 2026 11:44:25 +0200 Subject: [PATCH 13/14] [FIX] awesome_dashboard: correct math operation order in the time key function using parenthesis --- awesome_dashboard/static/src/dashboard_stats_service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awesome_dashboard/static/src/dashboard_stats_service.js b/awesome_dashboard/static/src/dashboard_stats_service.js index 8f65fed26f3..5898bcc43ef 100644 --- a/awesome_dashboard/static/src/dashboard_stats_service.js +++ b/awesome_dashboard/static/src/dashboard_stats_service.js @@ -12,7 +12,7 @@ export const dashboardStatsService = { const memoizedLoad = memoize(loadStatistics); // Time key integer changing every 10m in order to miss the cache of memoize - const getTimeKey = () => Math.floor(Date.now() / 1000*60*10); + const getTimeKey = () => Math.floor(Date.now() / (1000 * 60 * 10)); return { loadStatistics: () => memoizedLoad(getTimeKey()) From 0a9977e1b224faa2fcbc2525152e41a089dabb72 Mon Sep 17 00:00:00 2001 From: aski97 Date: Thu, 27 Aug 2026 14:51:33 +0200 Subject: [PATCH 14/14] [IMP] awesome_dashboard: add lazy loading component. --- awesome_dashboard/__manifest__.py | 5 ++++- .../src/{ => dashboard}/chart/pie_chart/pie_chart.js | 0 .../{ => dashboard}/chart/pie_chart/pie_chart.xml | 0 .../static/src/{ => dashboard}/dashboard.js | 2 +- .../static/src/{ => dashboard}/dashboard.scss | 0 .../static/src/{ => dashboard}/dashboard.xml | 0 .../{ => dashboard}/dashboard_item/dashboard_item.js | 0 .../dashboard_item/dashboard_item.xml | 0 .../src/{ => dashboard}/dashboard_stats_service.js | 0 awesome_dashboard/static/src/dashboard_action.js | 12 ++++++++++++ 10 files changed, 17 insertions(+), 2 deletions(-) rename awesome_dashboard/static/src/{ => dashboard}/chart/pie_chart/pie_chart.js (100%) rename awesome_dashboard/static/src/{ => dashboard}/chart/pie_chart/pie_chart.xml (100%) rename awesome_dashboard/static/src/{ => dashboard}/dashboard.js (95%) rename awesome_dashboard/static/src/{ => dashboard}/dashboard.scss (100%) rename awesome_dashboard/static/src/{ => dashboard}/dashboard.xml (100%) rename awesome_dashboard/static/src/{ => dashboard}/dashboard_item/dashboard_item.js (100%) rename awesome_dashboard/static/src/{ => dashboard}/dashboard_item/dashboard_item.xml (100%) rename awesome_dashboard/static/src/{ => dashboard}/dashboard_stats_service.js (100%) create mode 100644 awesome_dashboard/static/src/dashboard_action.js diff --git a/awesome_dashboard/__manifest__.py b/awesome_dashboard/__manifest__.py index a1cd72893d7..95d84598ce6 100644 --- a/awesome_dashboard/__manifest__.py +++ b/awesome_dashboard/__manifest__.py @@ -22,8 +22,11 @@ 'views/views.xml', ], 'assets': { + 'awesome_dashboard.dashboard': [ + 'awesome_dashboard/static/src/dashboard/**/*', + ], 'web.assets_backend': [ - 'awesome_dashboard/static/src/**/*', + 'awesome_dashboard/static/src/dashboard_action.js', ], }, 'license': 'AGPL-3' diff --git a/awesome_dashboard/static/src/chart/pie_chart/pie_chart.js b/awesome_dashboard/static/src/dashboard/chart/pie_chart/pie_chart.js similarity index 100% rename from awesome_dashboard/static/src/chart/pie_chart/pie_chart.js rename to awesome_dashboard/static/src/dashboard/chart/pie_chart/pie_chart.js diff --git a/awesome_dashboard/static/src/chart/pie_chart/pie_chart.xml b/awesome_dashboard/static/src/dashboard/chart/pie_chart/pie_chart.xml similarity index 100% rename from awesome_dashboard/static/src/chart/pie_chart/pie_chart.xml rename to awesome_dashboard/static/src/dashboard/chart/pie_chart/pie_chart.xml diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js similarity index 95% rename from awesome_dashboard/static/src/dashboard.js rename to awesome_dashboard/static/src/dashboard/dashboard.js index d0937e8cb38..435126ade7d 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -57,4 +57,4 @@ class AwesomeDashboard extends Component { } } -registry.category("actions").add("awesome_dashboard.dashboard", AwesomeDashboard); +registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard); diff --git a/awesome_dashboard/static/src/dashboard.scss b/awesome_dashboard/static/src/dashboard/dashboard.scss similarity index 100% rename from awesome_dashboard/static/src/dashboard.scss rename to awesome_dashboard/static/src/dashboard/dashboard.scss diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml similarity index 100% rename from awesome_dashboard/static/src/dashboard.xml rename to awesome_dashboard/static/src/dashboard/dashboard.xml diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.js b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.js similarity index 100% rename from awesome_dashboard/static/src/dashboard_item/dashboard_item.js rename to awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.js diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml similarity index 100% rename from awesome_dashboard/static/src/dashboard_item/dashboard_item.xml rename to awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml diff --git a/awesome_dashboard/static/src/dashboard_stats_service.js b/awesome_dashboard/static/src/dashboard/dashboard_stats_service.js similarity index 100% rename from awesome_dashboard/static/src/dashboard_stats_service.js rename to awesome_dashboard/static/src/dashboard/dashboard_stats_service.js diff --git a/awesome_dashboard/static/src/dashboard_action.js b/awesome_dashboard/static/src/dashboard_action.js new file mode 100644 index 00000000000..12296b17cd6 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_action.js @@ -0,0 +1,12 @@ +import { Component, xml } from "@odoo/owl"; +import { registry } from "@web/core/registry"; +import { LazyComponent } from "@web/core/assets"; + +export class AwesomeDashboardLoader extends Component { + static components = { LazyComponent }; + static template = xml` + + `; +} + +registry.category("actions").add("awesome_dashboard.dashboard", AwesomeDashboardLoader);