From 220c8f54eca04db40be80cdb40e0bc6bcba378ea Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Fri, 24 Apr 2026 17:12:19 +0200 Subject: [PATCH 01/33] [IMP] awesome_owl: add counter on page make a counter that adds 1 every time a button is pressed --- awesome_owl/static/src/playground.js | 10 +++++++++- awesome_owl/static/src/playground.xml | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 4ac769b0aa5..112c4d97b09 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,5 +1,13 @@ -import { Component } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; export class Playground extends Component { static template = "awesome_owl.playground"; + + setup() { + this.state = useState({value: 0}); + } + + increment() { + this.state.value++; + } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 4fb905d59f9..4c3c53784b5 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -4,6 +4,10 @@
hello world +
+ Counter: + +
From ba0852da1de03a437cc322be800c62f31159ff79 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 10:14:46 +0200 Subject: [PATCH 02/33] [MOV] awesome_owl: move counter to own class making sure the counter can be reused --- awesome_owl/static/src/counter/counter.js | 13 +++++++++++++ awesome_owl/static/src/counter/counter.xml | 11 +++++++++++ awesome_owl/static/src/playground.js | 11 +++-------- awesome_owl/static/src/playground.xml | 6 ++---- 4 files changed, 29 insertions(+), 12 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..d19ff85e790 --- /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..454b240519c --- /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 112c4d97b09..44989a0f34f 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,13 +1,8 @@ -import { Component, useState } from "@odoo/owl"; +import { Component } from "@odoo/owl"; +import { Counter } from "./counter/counter"; export class Playground extends Component { static template = "awesome_owl.playground"; + static components = {Counter}; - setup() { - this.state = useState({value: 0}); - } - - increment() { - this.state.value++; - } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 4c3c53784b5..57879b36b88 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -4,10 +4,8 @@
hello world -
- Counter: - -
+ +
From ac3da2c26a802ece4db4544faad38da36f8307ec Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 10:29:07 +0200 Subject: [PATCH 03/33] [IMP] awesome_owl: add card have a view of how properties can be used to customize components --- awesome_owl/static/src/card/card.js | 5 +++++ awesome_owl/static/src/card/card.xml | 15 +++++++++++++++ awesome_owl/static/src/playground.js | 3 ++- awesome_owl/static/src/playground.xml | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) 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..4283a8739b2 --- /dev/null +++ b/awesome_owl/static/src/card/card.js @@ -0,0 +1,5 @@ +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..8494816ab54 --- /dev/null +++ b/awesome_owl/static/src/card/card.xml @@ -0,0 +1,15 @@ + + + + +
+
+
+

+ +

+
+
+
+ +
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 44989a0f34f..e843b59c06e 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,8 +1,9 @@ import { Component } 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 57879b36b88..51a22831d63 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -6,6 +6,8 @@ hello world + + From d201888930e04dd44ebd72915562ee63d2ad1a86 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 10:37:06 +0200 Subject: [PATCH 04/33] [IMP] awesome_owl: markup in display make it possible to use markup in cards --- awesome_owl/static/src/card/card.xml | 4 ++-- awesome_owl/static/src/playground.js | 6 +++++- awesome_owl/static/src/playground.xml | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 8494816ab54..8d21330e9a3 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -4,9 +4,9 @@
-
+

- +

diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index e843b59c06e..f7fb669455e 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,4 +1,4 @@ -import { Component } from "@odoo/owl"; +import { Component, markup } from "@odoo/owl"; import { Counter } from "./counter/counter"; import { Card } from "./card/card"; @@ -6,4 +6,8 @@ export class Playground extends Component { static template = "awesome_owl.playground"; static components = {Counter, Card}; + setup() { + this.content1 = "
some content
" + this.content2 = markup("
some content
") + } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 51a22831d63..3686d077342 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -6,8 +6,8 @@ hello world - - + +
From bb195b5198a05b09ff11d76e1769917fc73fee92 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 10:43:12 +0200 Subject: [PATCH 05/33] [IMP] awesome_owl: add prop validation make sure the correct properties are defined, can be validated in developer mode --- awesome_owl/static/src/card/card.js | 1 + 1 file changed, 1 insertion(+) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 4283a8739b2..86312aa946f 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -2,4 +2,5 @@ import { Component } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card"; + static props = ['title', 'content'] } From e5cf19c4bfdf21e8922615ea9351f355cce1e17a Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 11:12:11 +0200 Subject: [PATCH 06/33] [IMP] awesome_owl: add total of counters make it possible to have the total of different counters together --- awesome_owl/static/src/counter/counter.js | 6 ++++++ awesome_owl/static/src/playground.js | 11 ++++++++--- awesome_owl/static/src/playground.xml | 4 +++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js index d19ff85e790..7db202b644d 100644 --- a/awesome_owl/static/src/counter/counter.js +++ b/awesome_owl/static/src/counter/counter.js @@ -2,6 +2,9 @@ import { Component, useState } from "@odoo/owl"; export class Counter extends Component { static template = "awesome_owl.counter"; + static props = { + "onChange": {type: Function, optional: true} + }; setup() { this.state = useState({value: 0}); @@ -9,5 +12,8 @@ export class Counter extends Component { 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 f7fb669455e..817e4c845db 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,4 +1,4 @@ -import { Component, markup } from "@odoo/owl"; +import { Component, markup, useState } from "@odoo/owl"; import { Counter } from "./counter/counter"; import { Card } from "./card/card"; @@ -7,7 +7,12 @@ export class Playground extends Component { static components = {Counter, Card}; setup() { - this.content1 = "
some content
" - this.content2 = markup("
some content
") + this.content1 = "
some content
"; + this.content2 = markup("
some content
"); + this.state = useState({sum: 0}); + } + + increment_total() { + this.state.sum++; } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 3686d077342..d4a1bcc0f0e 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -4,8 +4,10 @@
hello world + + - + the sum of the first two counters is:
From 0233cdf75d26490f03583e347271fa4cef94a961 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 11:44:41 +0200 Subject: [PATCH 07/33] [IMP] awesome_owl: add visualisation of a todolist bring an option to the user to have a todolist visible --- awesome_owl/static/src/playground.js | 3 ++- awesome_owl/static/src/playground.xml | 21 ++++++++++++++------- awesome_owl/static/src/todo/todo_item.js | 16 ++++++++++++++++ awesome_owl/static/src/todo/todo_item.xml | 11 +++++++++++ awesome_owl/static/src/todo/todo_list.js | 11 +++++++++++ awesome_owl/static/src/todo/todo_list.xml | 12 ++++++++++++ 6 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 awesome_owl/static/src/todo/todo_item.js create mode 100644 awesome_owl/static/src/todo/todo_item.xml create mode 100644 awesome_owl/static/src/todo/todo_list.js create mode 100644 awesome_owl/static/src/todo/todo_list.xml diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 817e4c845db..cfb91378bb6 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,10 +1,11 @@ import { Component, markup, useState } from "@odoo/owl"; import { Counter } from "./counter/counter"; import { Card } from "./card/card"; +import { TodoList } from "./todo/todo_list"; export class Playground extends Component { static template = "awesome_owl.playground"; - static components = {Counter, Card}; + static components = {Counter, Card, TodoList}; setup() { this.content1 = "
some content
"; diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index d4a1bcc0f0e..63f521ddb09 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -3,13 +3,20 @@
- hello world - - - - the sum of the first two counters is: - - +
hello world
+
+ + + + the sum of the first two counters is: +
+
+ + +
+
+ +
diff --git a/awesome_owl/static/src/todo/todo_item.js b/awesome_owl/static/src/todo/todo_item.js new file mode 100644 index 00000000000..c2258459ac9 --- /dev/null +++ b/awesome_owl/static/src/todo/todo_item.js @@ -0,0 +1,16 @@ +import { Component } from "@odoo/owl"; + +export class TodoItem extends Component { + static template = "awesome_owl.todo_item"; + static props = { + "todo": { + type: Object, + shape: { + id: Number, + description: String, + isCompleted: Boolean + } + } + } + +} diff --git a/awesome_owl/static/src/todo/todo_item.xml b/awesome_owl/static/src/todo/todo_item.xml new file mode 100644 index 00000000000..5e9c4944378 --- /dev/null +++ b/awesome_owl/static/src/todo/todo_item.xml @@ -0,0 +1,11 @@ + + + + +
+ . + +
+
+ +
diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js new file mode 100644 index 00000000000..946ae34662c --- /dev/null +++ b/awesome_owl/static/src/todo/todo_list.js @@ -0,0 +1,11 @@ +import { Component, useState } from "@odoo/owl"; +import { TodoItem } from "./todo_item"; + +export class TodoList extends Component { + static template = "awesome_owl.todo_list"; + static components = {TodoItem}; + + setup() { + this.todos = useState([{id: 3, description: "buy milk", isCompleted: false}]); + } +} diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml new file mode 100644 index 00000000000..2607dacc5e9 --- /dev/null +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -0,0 +1,12 @@ + + + + +
+ + + +
+
+ +
From 43be439caa5c6d869a53b84e2ded19445cb73a74 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 12:55:07 +0200 Subject: [PATCH 08/33] [IMP] awesome_owl: mark completed items make it visually clear when is task is completed --- awesome_owl/static/src/todo/todo_item.xml | 2 +- awesome_owl/static/src/todo/todo_list.js | 5 ++++- awesome_owl/static/src/todo/todo_list.xml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/awesome_owl/static/src/todo/todo_item.xml b/awesome_owl/static/src/todo/todo_item.xml index 5e9c4944378..7624f7d3771 100644 --- a/awesome_owl/static/src/todo/todo_item.xml +++ b/awesome_owl/static/src/todo/todo_item.xml @@ -2,7 +2,7 @@ -
+
.
diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js index 946ae34662c..5d0b978620c 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -6,6 +6,9 @@ export class TodoList extends Component { static components = {TodoItem}; setup() { - this.todos = useState([{id: 3, description: "buy milk", isCompleted: false}]); + this.todos = useState([ + {id: 2, description: "write tutorial", isCompleted: true}, + {id: 3, description: "buy milk", isCompleted: false}, + ]); } } diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml index 2607dacc5e9..008ba244f61 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -3,7 +3,7 @@
- +
From 4ccb0fc482463be0d4d3b8f770ab7fc6e939844e Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 13:21:31 +0200 Subject: [PATCH 09/33] [IMP] awesome_owl: make adding todo's possible make the list of todo's interactive by adding the option to add items --- awesome_owl/static/src/todo/todo_list.js | 12 ++++++++---- awesome_owl/static/src/todo/todo_list.xml | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js index 5d0b978620c..cdfd7f23524 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -6,9 +6,13 @@ export class TodoList extends Component { static components = {TodoItem}; setup() { - this.todos = useState([ - {id: 2, description: "write tutorial", isCompleted: true}, - {id: 3, description: "buy milk", isCompleted: false}, - ]); + this.todos = useState([]); + } + + addToDo(event) { + if (event.keyCode === 13 && event.target.value !== "") { + this.todos.push({id: this.todos.length, description: event.target.value, isCompleted: false}); + event.target.value = ""; + } } } diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml index 008ba244f61..3e45724c992 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -3,6 +3,7 @@
+ From b1703e6a7febcbe95c36a7905f886046ace8a33a Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 13:37:16 +0200 Subject: [PATCH 10/33] [IMP] awesome_owl: autofocus input field when loading the page automatically focus the input as this improves the speed of adding a new item when loading the page --- awesome_owl/static/src/todo/todo_list.js | 2 ++ awesome_owl/static/src/todo/todo_list.xml | 2 +- awesome_owl/static/src/utils.js | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 awesome_owl/static/src/utils.js diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js index cdfd7f23524..2526ee506b2 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -1,5 +1,6 @@ import { Component, useState } from "@odoo/owl"; import { TodoItem } from "./todo_item"; +import { useAutofocus } from "../utils"; export class TodoList extends Component { static template = "awesome_owl.todo_list"; @@ -7,6 +8,7 @@ export class TodoList extends Component { setup() { this.todos = useState([]); + useAutofocus("add_todo_input"); } addToDo(event) { diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml index 3e45724c992..fd442e049c8 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -3,7 +3,7 @@
- + diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js new file mode 100644 index 00000000000..d7652f3d82a --- /dev/null +++ b/awesome_owl/static/src/utils.js @@ -0,0 +1,8 @@ +import { onMounted, useRef } from "@odoo/owl"; + +export function useAutofocus(named_ref) { + const ref = useRef(named_ref); + onMounted(() => { + ref.el.focus(); + }); +} From 3bfc874a2497469b44a0e30380114e195ccfa2c7 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 15:41:37 +0200 Subject: [PATCH 11/33] [IMP] awesome_owl: toggeling todos make it possible to toggle a todo to completed --- awesome_owl/static/src/todo/todo_item.js | 6 ++++++ awesome_owl/static/src/todo/todo_item.xml | 1 + awesome_owl/static/src/todo/todo_list.js | 7 +++++++ awesome_owl/static/src/todo/todo_list.xml | 2 +- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/awesome_owl/static/src/todo/todo_item.js b/awesome_owl/static/src/todo/todo_item.js index c2258459ac9..5e236262069 100644 --- a/awesome_owl/static/src/todo/todo_item.js +++ b/awesome_owl/static/src/todo/todo_item.js @@ -10,7 +10,13 @@ export class TodoItem extends Component { description: String, isCompleted: Boolean } + }, + "toggleState": { + type: Function } } + onChange(event) { + this.props.toggleState(this.props.todo.id); + } } diff --git a/awesome_owl/static/src/todo/todo_item.xml b/awesome_owl/static/src/todo/todo_item.xml index 7624f7d3771..500e6a236f1 100644 --- a/awesome_owl/static/src/todo/todo_item.xml +++ b/awesome_owl/static/src/todo/todo_item.xml @@ -3,6 +3,7 @@
+ .
diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js index 2526ee506b2..93704ce792d 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -17,4 +17,11 @@ export class TodoList extends Component { event.target.value = ""; } } + + toggleStateOfTodo(id) { + const todo = this.todos.find((todo) => todo.id === id); + if (todo) { + todo.isCompleted = !todo.isCompleted; + } + } } diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml index fd442e049c8..bdffc3d453f 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -5,7 +5,7 @@
- +
From 752c640d50147e4117f2f8192018907295cd7e2f Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 15:48:41 +0200 Subject: [PATCH 12/33] [CLN] awesome_owl: follow naming convention make code in line with teh current standard --- awesome_owl/static/src/card/card.js | 2 +- awesome_owl/static/src/card/card.xml | 5 +---- awesome_owl/static/src/counter/counter.js | 2 +- awesome_owl/static/src/counter/counter.xml | 5 +---- awesome_owl/static/src/playground.js | 3 ++- awesome_owl/static/src/playground.xml | 5 +---- awesome_owl/static/src/todo/todo_item.js | 2 +- awesome_owl/static/src/todo/todo_item.xml | 5 +---- awesome_owl/static/src/todo/todo_list.js | 3 ++- awesome_owl/static/src/todo/todo_list.xml | 5 +---- 10 files changed, 12 insertions(+), 25 deletions(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 86312aa946f..56cebd14a13 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -1,6 +1,6 @@ import { Component } from "@odoo/owl"; export class Card extends Component { - static template = "awesome_owl.card"; + static template = "awesome_owl.Card"; static props = ['title', 'content'] } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 8d21330e9a3..909f1c01ff6 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -1,7 +1,5 @@ - - - +
@@ -11,5 +9,4 @@
-
diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js index 7db202b644d..e10df9f3be5 100644 --- a/awesome_owl/static/src/counter/counter.js +++ b/awesome_owl/static/src/counter/counter.js @@ -1,7 +1,7 @@ import { Component, useState } from "@odoo/owl"; export class Counter extends Component { - static template = "awesome_owl.counter"; + static template = "awesome_owl.Counter"; static props = { "onChange": {type: Function, optional: true} }; diff --git a/awesome_owl/static/src/counter/counter.xml b/awesome_owl/static/src/counter/counter.xml index 454b240519c..be723fcf7dd 100644 --- a/awesome_owl/static/src/counter/counter.xml +++ b/awesome_owl/static/src/counter/counter.xml @@ -1,11 +1,8 @@ - - - +
Counter:
-
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index cfb91378bb6..a080b864d35 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -4,8 +4,9 @@ import { Card } from "./card/card"; import { TodoList } from "./todo/todo_list"; export class Playground extends Component { - static template = "awesome_owl.playground"; + static template = "awesome_owl.Playground"; static components = {Counter, Card, TodoList}; + static props = []; setup() { this.content1 = "
some content
"; diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 63f521ddb09..53dfac08455 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -1,7 +1,5 @@ - - - +
hello world
@@ -19,5 +17,4 @@
-
diff --git a/awesome_owl/static/src/todo/todo_item.js b/awesome_owl/static/src/todo/todo_item.js index 5e236262069..e06737f6bf7 100644 --- a/awesome_owl/static/src/todo/todo_item.js +++ b/awesome_owl/static/src/todo/todo_item.js @@ -1,7 +1,7 @@ import { Component } from "@odoo/owl"; export class TodoItem extends Component { - static template = "awesome_owl.todo_item"; + static template = "awesome_owl.TodoItem"; static props = { "todo": { type: Object, diff --git a/awesome_owl/static/src/todo/todo_item.xml b/awesome_owl/static/src/todo/todo_item.xml index 500e6a236f1..a581b8943aa 100644 --- a/awesome_owl/static/src/todo/todo_item.xml +++ b/awesome_owl/static/src/todo/todo_item.xml @@ -1,12 +1,9 @@ - - - +
.
-
diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js index 93704ce792d..883de4e5395 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -3,8 +3,9 @@ import { TodoItem } from "./todo_item"; import { useAutofocus } from "../utils"; export class TodoList extends Component { - static template = "awesome_owl.todo_list"; + static template = "awesome_owl.TodoList"; static components = {TodoItem}; + static props = []; setup() { this.todos = useState([]); diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml index bdffc3d453f..5f773f097b0 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -1,7 +1,5 @@ - - - +
@@ -9,5 +7,4 @@
-
From c517440c95bd7a86b01f3f4e2f5d99a5b97899f8 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 16:11:49 +0200 Subject: [PATCH 13/33] [IMP] awesome_owl: make deleting todoitems possible make it possible to delete wrong todo items --- awesome_owl/static/src/todo/todo_item.js | 9 ++++++++- awesome_owl/static/src/todo/todo_item.xml | 1 + awesome_owl/static/src/todo/todo_list.js | 10 +++++++++- awesome_owl/static/src/todo/todo_list.xml | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/awesome_owl/static/src/todo/todo_item.js b/awesome_owl/static/src/todo/todo_item.js index e06737f6bf7..3f10d602805 100644 --- a/awesome_owl/static/src/todo/todo_item.js +++ b/awesome_owl/static/src/todo/todo_item.js @@ -13,10 +13,17 @@ export class TodoItem extends Component { }, "toggleState": { type: Function - } + }, + "removeTodo": { + type: Function + }, } onChange(event) { this.props.toggleState(this.props.todo.id); } + + onClickDelete(event) { + this.props.removeTodo(this.props.todo.id); + } } diff --git a/awesome_owl/static/src/todo/todo_item.xml b/awesome_owl/static/src/todo/todo_item.xml index a581b8943aa..418c365686b 100644 --- a/awesome_owl/static/src/todo/todo_item.xml +++ b/awesome_owl/static/src/todo/todo_item.xml @@ -4,6 +4,7 @@ . +
diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js index 883de4e5395..2b852640c09 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -9,12 +9,13 @@ export class TodoList extends Component { setup() { this.todos = useState([]); + this.nextId = this.todos.length; useAutofocus("add_todo_input"); } addToDo(event) { if (event.keyCode === 13 && event.target.value !== "") { - this.todos.push({id: this.todos.length, description: event.target.value, isCompleted: false}); + this.todos.push({id: this.nextId++, description: event.target.value, isCompleted: false}); event.target.value = ""; } } @@ -25,4 +26,11 @@ export class TodoList extends Component { todo.isCompleted = !todo.isCompleted; } } + + deleteTodo(id) { + const index = this.todos.findIndex((todo) => todo.id === id); + if (index >= 0) { + this.todos.splice(index, 1); + } + } } diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml index 5f773f097b0..ae2267b842b 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -3,7 +3,7 @@
- +
From 09e67bbc2d4236674df1ebfd1dc4244e83a8bbfa Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 16:32:25 +0200 Subject: [PATCH 14/33] [IMP] awesome_owl: introduction to slots make it possible to delete wrong todo items --- awesome_owl/static/src/card/card.js | 5 ++++- awesome_owl/static/src/card/card.xml | 2 +- awesome_owl/static/src/playground.xml | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 56cebd14a13..e52684da415 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -2,5 +2,8 @@ import { Component } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.Card"; - static props = ['title', 'content'] + static props = { + 'title': {type: String}, + 'slots': {type: Object, shape: {default: true}} + }; } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 909f1c01ff6..1fae553fe97 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -4,7 +4,7 @@

- +

diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 53dfac08455..77100743552 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -9,8 +9,8 @@ the sum of the first two counters is:
- - + +
From 206c82ebcb403b7d5ddaa42fb96d5204ac80ad61 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 16:49:52 +0200 Subject: [PATCH 15/33] [IMP] awesome_owl: add option to hide card content add option to hide card content --- awesome_owl/static/src/card/card.js | 12 ++++++++++-- awesome_owl/static/src/card/card.xml | 5 +++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index e52684da415..2f1c5f10730 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -1,9 +1,17 @@ -import { Component } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.Card"; static props = { 'title': {type: String}, - 'slots': {type: Object, shape: {default: true}} + 'slots': {type: Object, shape: {default: true}}, }; + + setup() { + this.state = useState({isOpen: true}); + } + + toggleOpen() { + this.state.isOpen = !this.state.isOpen; + } } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 1fae553fe97..46f6f651c74 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -2,8 +2,9 @@
-
-

+

+
+

From 64a8839e4e7bc9788f7e107d55a3d13428f9d1dd Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 17:51:22 +0200 Subject: [PATCH 16/33] [IMP] awesome_dashboard: a new layout make the app follow the common layout to keep the same look and feel over the complete environment --- awesome_dashboard/static/src/dashboard.js | 6 ++++++ awesome_dashboard/static/src/dashboard.scss | 3 +++ awesome_dashboard/static/src/dashboard.xml | 5 +++-- 3 files changed, 12 insertions(+), 2 deletions(-) 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..c4370447b0d 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,8 +1,14 @@ import { Component } from "@odoo/owl"; import { registry } from "@web/core/registry"; +import { Layout } from "@web/search/layout"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; + static components = {Layout}; + + setup() { + this.action = useService("action"); + } } 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..44d19099628 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard.scss @@ -0,0 +1,3 @@ +.o_dashboard { + background-color: darkgrey; +} diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 1a2ac9a2fed..b97c28c83e0 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -1,8 +1,9 @@ - - hello dashboard + + hello dashboard + From a758675a5f275e58cc73d44db701b16654137731 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Mon, 27 Apr 2026 17:52:23 +0200 Subject: [PATCH 17/33] [IMP] awesome_dashboard: Add some buttons for quick navigation make it easier to navigate between the different parts --- awesome_dashboard/static/src/dashboard.js | 17 +++++++++++++++++ awesome_dashboard/static/src/dashboard.xml | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index c4370447b0d..7f6e100db6c 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,6 +1,7 @@ import { Component } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; +import { useService } from "@web/core/utils/hooks"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -9,6 +10,22 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); } + + openCustomers() { + this.action.doAction("base.action_partner_form"); + } + + openLeads() { + this.action.doAction({ + type: 'ir.actions.act_window', + target: 'current', + 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.xml b/awesome_dashboard/static/src/dashboard.xml index b97c28c83e0..18b79f9aa54 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -2,6 +2,10 @@ + + + + hello dashboard From 73580efae403a9cbd231539a173b315eb61e1d56 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 09:48:32 +0200 Subject: [PATCH 18/33] [IMP] awesome_dashboard: add dashboard items make it possible to see some content on the page --- awesome_dashboard/static/src/dashboard.js | 3 ++- awesome_dashboard/static/src/dashboard.xml | 5 ++++- .../src/dashboard_item/dashboard_item.js | 18 ++++++++++++++++++ .../src/dashboard_item/dashboard_item.xml | 13 +++++++++++++ 4 files changed, 37 insertions(+), 2 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 7f6e100db6c..aadc97f7930 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -2,10 +2,11 @@ import { Component } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; +import { DashboardItem } from "./dashboard_item/dashboard_item"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; - static components = {Layout}; + static components = {Layout, DashboardItem}; setup() { this.action = useService("action"); diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 18b79f9aa54..6223547705c 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -6,7 +6,10 @@ - hello dashboard + + some content + I love milk + 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..ba7597b9389 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js @@ -0,0 +1,18 @@ +import { Component } from "@odoo/owl"; + +export class DashboardItem extends Component { + static template = "awesome_dashboard.DashboardItem"; + static props = { + size: { + type: Number, + optional: true, + }, + slots: { + type: Object, + shape: {default: true}, + } + }; + static defaultProps = { + size: 1, + }; +} 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..4b4e80e5829 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml @@ -0,0 +1,13 @@ + + + +
+
+

+ +

+
+
+
+ +
From f8efc82e47677d55a738921bc0a391c69406397c Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 10:32:14 +0200 Subject: [PATCH 19/33] [IMP] awesome_dashboard: add statistics on dashboard it is better to show requested data over dummy data --- awesome_dashboard/static/src/dashboard.js | 6 +++++- awesome_dashboard/static/src/dashboard.xml | 22 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index aadc97f7930..e1cf6c6cc35 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,8 +1,9 @@ -import { Component } from "@odoo/owl"; +import { Component, onWillStart } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item/dashboard_item"; +import { rpc } from "@web/core/network/rpc"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -10,6 +11,9 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); + onWillStart(async () => { + this.results = await rpc("/awesome_dashboard/statistics"); + }); } openCustomers() { diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 6223547705c..f46929c4884 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -7,8 +7,26 @@ - some content - I love milk + + Average amount of t-shirts by order this month +
+
+ + Average time for an order to go from new to sent or canceled +
+
+ + Number of new orders this month +
+
+ + Number of canceled orders this month +
+
+ + Total amount of orders this month +
+
From 949c551a25bffb2371bf2f2c4fcd91320913acb2 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 10:55:57 +0200 Subject: [PATCH 20/33] [IMP] awesome_dashboard: caching the results by caching results through a service you don't need to call backend every time you want to show the statistics --- awesome_dashboard/static/src/dashboard.js | 4 ++-- awesome_dashboard/static/src/statistics.js | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 awesome_dashboard/static/src/statistics.js diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index e1cf6c6cc35..826c22f86e7 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -3,7 +3,6 @@ import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item/dashboard_item"; -import { rpc } from "@web/core/network/rpc"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -11,8 +10,9 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); + const statistics = useService("awesome_dashboard.statistics"); onWillStart(async () => { - this.results = await rpc("/awesome_dashboard/statistics"); + this.results = await statistics.loadStatistics(); }); } diff --git a/awesome_dashboard/static/src/statistics.js b/awesome_dashboard/static/src/statistics.js new file mode 100644 index 00000000000..70508b8b0c6 --- /dev/null +++ b/awesome_dashboard/static/src/statistics.js @@ -0,0 +1,14 @@ +import { rpc } from "@web/core/network/rpc"; +import { registry } from "@web/core/registry"; +import { memoize } from "@web/core/utils/functions"; + + +export const statisticsService = { + start() { + return { + loadStatistics: memoize(() => rpc("/awesome_dashboard/statistics")), + }; + }, +}; + +registry.category("services").add("awesome_dashboard.statistics", statisticsService); From 2affcf3a652d96bfe326f57113b5383f92161107 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 13:33:42 +0200 Subject: [PATCH 21/33] [IMP] awesome_dashboard: add pie-chart add visualization for the statistic data of sizes --- awesome_dashboard/static/src/dashboard.js | 3 +- awesome_dashboard/static/src/dashboard.xml | 4 ++ .../static/src/pie_chart/pie_chart.js | 41 +++++++++++++++++++ .../static/src/pie_chart/pie_chart.xml | 7 ++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 awesome_dashboard/static/src/pie_chart/pie_chart.js create mode 100644 awesome_dashboard/static/src/pie_chart/pie_chart.xml diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 826c22f86e7..7a41f45dc43 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -3,10 +3,11 @@ import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item/dashboard_item"; +import { PieChart } from "./pie_chart/pie_chart"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; - static components = {Layout, DashboardItem}; + static components = {Layout, DashboardItem, PieChart}; setup() { this.action = useService("action"); diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index f46929c4884..616e0b6911c 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -27,6 +27,10 @@ Total amount of orders this month
+ + Shirt orders by size + + diff --git a/awesome_dashboard/static/src/pie_chart/pie_chart.js b/awesome_dashboard/static/src/pie_chart/pie_chart.js new file mode 100644 index 00000000000..8b53ffa58a2 --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.js @@ -0,0 +1,41 @@ +import { Component, onMounted, onPatched, onWillStart, onWillUnmount, useRef } from "@odoo/owl"; +import { loadJS } from "@web/core/assets"; + +export class PieChart extends Component { + static template = "awesome_dashboard.PieChart"; + static props = { + data: { + type: Object, + } + } + + setup() { + this.canvas = useRef("canvas"); + onWillStart(async () => await loadJS("/web/static/lib/Chart/Chart.js")); + onMounted(() => this.renderChart()); + onPatched(() => { + this.renderChart(); + this.destroyChart(); + }); + onWillUnmount(() => this.destroyChart()); + } + + destroyChart() { + if (this.chart) { + this.chart.destroy(); + } + } + + renderChart() { + this.chart = new Chart(this.canvas.el, { + type: "pie", data: { + labels: Object.keys(this.props.data), + datasets: [ + { + data: Object.values(this.props.data), + }, + ], + } + }); + } +} diff --git a/awesome_dashboard/static/src/pie_chart/pie_chart.xml b/awesome_dashboard/static/src/pie_chart/pie_chart.xml new file mode 100644 index 00000000000..697b3287b6e --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.xml @@ -0,0 +1,7 @@ + + + + + + + From cf78101f15d085b4ae151444c915c26404dcc776 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 13:58:07 +0200 Subject: [PATCH 22/33] [CLN] awesome_owl: code convention camelcase for refs code convention --- awesome_owl/static/src/todo/todo_list.js | 2 +- awesome_owl/static/src/todo/todo_list.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js index 2b852640c09..9acc16e9110 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -10,7 +10,7 @@ export class TodoList extends Component { setup() { this.todos = useState([]); this.nextId = this.todos.length; - useAutofocus("add_todo_input"); + useAutofocus("addTodoInput"); } addToDo(event) { diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml index ae2267b842b..52c34981df6 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -1,7 +1,7 @@
- + From 286bd29bd50e0e0de9764e52245bc12578cee491 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 13:59:07 +0200 Subject: [PATCH 23/33] [CLN] awesome_dashboard: coding convention code convention filename needs to be like element inside --- .../static/src/{statistics.js => statistics_service.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename awesome_dashboard/static/src/{statistics.js => statistics_service.js} (100%) diff --git a/awesome_dashboard/static/src/statistics.js b/awesome_dashboard/static/src/statistics_service.js similarity index 100% rename from awesome_dashboard/static/src/statistics.js rename to awesome_dashboard/static/src/statistics_service.js From 1f1e971894b74913effc7181ee9152234f87a4f2 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 14:37:07 +0200 Subject: [PATCH 24/33] [FIX] awesome_dashboard: piechart need to be destroyed before creating next one the order of first deleting the old canvas and only then adding a new chart is important! --- awesome_dashboard/static/src/pie_chart/pie_chart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awesome_dashboard/static/src/pie_chart/pie_chart.js b/awesome_dashboard/static/src/pie_chart/pie_chart.js index 8b53ffa58a2..c71f490b738 100644 --- a/awesome_dashboard/static/src/pie_chart/pie_chart.js +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.js @@ -14,8 +14,8 @@ export class PieChart extends Component { onWillStart(async () => await loadJS("/web/static/lib/Chart/Chart.js")); onMounted(() => this.renderChart()); onPatched(() => { - this.renderChart(); this.destroyChart(); + this.renderChart(); }); onWillUnmount(() => this.destroyChart()); } From dc7faf024cd59aa508abf5efbf0acb24dfa5566f Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 15:25:03 +0200 Subject: [PATCH 25/33] [IMP] awesome_dashboard: real life update making sure the data is in line with the data from the backend --- awesome_dashboard/static/src/dashboard.js | 7 ++----- awesome_dashboard/static/src/dashboard.xml | 2 +- awesome_dashboard/static/src/statistics_service.js | 13 +++++++++++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 7a41f45dc43..29faa55c6f6 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,4 +1,4 @@ -import { Component, onWillStart } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; @@ -11,10 +11,7 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); - const statistics = useService("awesome_dashboard.statistics"); - onWillStart(async () => { - this.results = await statistics.loadStatistics(); - }); + this.results = useState(useService("awesome_dashboard.statistics").loadStatistics); } openCustomers() { diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 616e0b6911c..5aaed5d1aac 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -6,7 +6,7 @@ - + Average amount of t-shirts by order this month
diff --git a/awesome_dashboard/static/src/statistics_service.js b/awesome_dashboard/static/src/statistics_service.js index 70508b8b0c6..86d481de2fb 100644 --- a/awesome_dashboard/static/src/statistics_service.js +++ b/awesome_dashboard/static/src/statistics_service.js @@ -1,12 +1,21 @@ import { rpc } from "@web/core/network/rpc"; import { registry } from "@web/core/registry"; -import { memoize } from "@web/core/utils/functions"; +import { reactive } from "@odoo/owl"; export const statisticsService = { start() { + const statistics = reactive({isLoaded: false}); + + async function loadStatistics() { + Object.assign(statistics, await rpc("/awesome_dashboard/statistics"), {isLoaded: true}); + } + + setInterval(loadStatistics, 10 * 60 * 1000); + loadStatistics(); + return { - loadStatistics: memoize(() => rpc("/awesome_dashboard/statistics")), + loadStatistics: statistics, }; }, }; From f127f24c45faf27f43646bf33dd69866cda98874 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 16:18:40 +0200 Subject: [PATCH 26/33] [IMP] awesome_dashboard: lazy loading of module only load the dashboards when they need to be shown --- awesome_dashboard/__manifest__.py | 6 +++++- .../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}/pie_chart/pie_chart.js | 0 .../src/{ => dashboard}/pie_chart/pie_chart.xml | 0 .../static/src/{ => dashboard}/statistics_service.js | 0 awesome_dashboard/static/src/dashboard_loader.js | 12 ++++++++++++ 10 files changed, 18 insertions(+), 2 deletions(-) rename awesome_dashboard/static/src/{ => dashboard}/dashboard.js (92%) 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}/pie_chart/pie_chart.js (100%) rename awesome_dashboard/static/src/{ => dashboard}/pie_chart/pie_chart.xml (100%) rename awesome_dashboard/static/src/{ => dashboard}/statistics_service.js (100%) create mode 100644 awesome_dashboard/static/src/dashboard_loader.js diff --git a/awesome_dashboard/__manifest__.py b/awesome_dashboard/__manifest__.py index a1cd72893d7..89481aa5f4a 100644 --- a/awesome_dashboard/__manifest__.py +++ b/awesome_dashboard/__manifest__.py @@ -24,7 +24,11 @@ 'assets': { 'web.assets_backend': [ 'awesome_dashboard/static/src/**/*', + ('remove', 'awesome_dashboard/static/src/dashboard/**/*'), + ], + 'awesome_dashboard.dashboard': [ + 'awesome_dashboard/static/src/dashboard/**/*', ], }, - 'license': 'AGPL-3' + 'license': 'AGPL-3', } diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js similarity index 92% rename from awesome_dashboard/static/src/dashboard.js rename to awesome_dashboard/static/src/dashboard/dashboard.js index 29faa55c6f6..bd7dc85fb4e 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -31,4 +31,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/pie_chart/pie_chart.js b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js similarity index 100% rename from awesome_dashboard/static/src/pie_chart/pie_chart.js rename to awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js diff --git a/awesome_dashboard/static/src/pie_chart/pie_chart.xml b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.xml similarity index 100% rename from awesome_dashboard/static/src/pie_chart/pie_chart.xml rename to awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.xml diff --git a/awesome_dashboard/static/src/statistics_service.js b/awesome_dashboard/static/src/dashboard/statistics_service.js similarity index 100% rename from awesome_dashboard/static/src/statistics_service.js rename to awesome_dashboard/static/src/dashboard/statistics_service.js diff --git a/awesome_dashboard/static/src/dashboard_loader.js b/awesome_dashboard/static/src/dashboard_loader.js new file mode 100644 index 00000000000..f86023a1e17 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_loader.js @@ -0,0 +1,12 @@ +import { registry } from "@web/core/registry"; +import { LazyComponent } from "@web/core/assets"; +import { Component, xml } from "@odoo/owl"; + +export class DashBoardComponentLoader extends Component { + static components = {LazyComponent}; + static template = xml` + + `; +} + +registry.category("actions").add("awesome_dashboard.dashboard", DashBoardComponentLoader); From 416de43a0088e7ea9712bc40be53dc4d09daaf6e Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 17:42:47 +0200 Subject: [PATCH 27/33] [IMP] awesome_dashboard: make dashboard generic change hardcode cards to a list of dashboard_items to make customization possible in a later stage --- .../static/src/dashboard/dashboard.js | 7 +- .../static/src/dashboard/dashboard.xml | 32 ++------- .../static/src/dashboard/dashboard_items.js | 66 +++++++++++++++++++ .../src/dashboard/number_card/number_card.js | 13 ++++ .../src/dashboard/number_card/number_card.xml | 6 ++ .../pie_chart_card/pie_chart_card.js | 15 +++++ .../pie_chart_card/pie_chart_card.xml | 6 ++ 7 files changed, 117 insertions(+), 28 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard/dashboard_items.js create mode 100644 awesome_dashboard/static/src/dashboard/number_card/number_card.js create mode 100644 awesome_dashboard/static/src/dashboard/number_card/number_card.xml create mode 100644 awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.js create mode 100644 awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.xml diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index bd7dc85fb4e..54147c31e65 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -3,15 +3,16 @@ import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item/dashboard_item"; -import { PieChart } from "./pie_chart/pie_chart"; +import { items } from "./dashboard_items"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; - static components = {Layout, DashboardItem, PieChart}; + static components = {Layout, DashboardItem}; setup() { this.action = useService("action"); - this.results = useState(useService("awesome_dashboard.statistics").loadStatistics); + this.statistics = useState(useService("awesome_dashboard.statistics").loadStatistics); + this.items = items; } openCustomers() { diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index 5aaed5d1aac..0a613553142 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -6,31 +6,13 @@
- - - Average amount of t-shirts by order this month -
-
- - Average time for an order to go from new to sent or canceled -
-
- - Number of new orders this month -
-
- - Number of canceled orders this month -
-
- - Total amount of orders this month -
-
- - Shirt orders by size - - + + + + + + +
diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items.js b/awesome_dashboard/static/src/dashboard/dashboard_items.js new file mode 100644 index 00000000000..cf99a817d88 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -0,0 +1,66 @@ +import { NumberCard } from "./number_card/number_card"; +import { PieChartCard } from "./pie_chart_card/pie_chart_card"; + +export let items = [ + { + id: "average_quantity", + description: "Average amount of t-shirt", + Component: NumberCard, + // size and props are optionals + size: 3, + props: (data) => ({ + title: "Average amount of t-shirt by order this month", + value: data.average_quantity + }), + }, + { + id: "average_time", + description: "Average time for an order", + Component: NumberCard, + // size and props are optionals + props: (data) => ({ + title: "Average time for an order to go from new to sent or canceled", + value: data.average_time + }), + }, + { + id: "nb_new_orders", + description: "New orders this month", + Component: NumberCard, + // size and props are optionals + props: (data) => ({ + title: "Number of new orders this month", + value: data.nb_new_orders + }), + }, { + id: "nb_cancelled_orders", + description: "Canceled orders this month", + Component: NumberCard, + // size and props are optionals + props: (data) => ({ + title: "Number of canceled orders this month", + value: data.nb_cancelled_orders + }), + }, + { + id: "total_amount", + description: "Smount of orders this month", + Component: NumberCard, + // size and props are optionals + props: (data) => ({ + title: "Total amount of orders this month", + value: data.total_amount + }), + }, + { + id: "orders_by_size", + description: "Shirt orders by size", + Component: PieChartCard, + // size and props are optionals + props: (data) => ({ + title: "Shirt orders by size", + values: data.orders_by_size + }), + }, + +]; diff --git a/awesome_dashboard/static/src/dashboard/number_card/number_card.js b/awesome_dashboard/static/src/dashboard/number_card/number_card.js new file mode 100644 index 00000000000..66305675c9d --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/number_card/number_card.js @@ -0,0 +1,13 @@ +import { Component } from "@odoo/owl"; + +export class NumberCard extends Component { + static template = "awesome_dashboard.NumberCard"; + static props = { + title: { + type: String, + }, + value: { + type: Number, + } + }; +} diff --git a/awesome_dashboard/static/src/dashboard/number_card/number_card.xml b/awesome_dashboard/static/src/dashboard/number_card/number_card.xml new file mode 100644 index 00000000000..b69ba44ad0a --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/number_card/number_card.xml @@ -0,0 +1,6 @@ + + + +
+
+
diff --git a/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.js b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.js new file mode 100644 index 00000000000..9af0398ac38 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.js @@ -0,0 +1,15 @@ +import { Component } from "@odoo/owl"; +import { PieChart } from "../pie_chart/pie_chart"; + +export class PieChartCard extends Component { + static template = "awesome_dashboard.PieChartCard"; + static components = {PieChart}; + static props = { + title: { + type: String, + }, + values: { + type: Object, + } + }; +} diff --git a/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.xml b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.xml new file mode 100644 index 00000000000..01d3b5f0da3 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.xml @@ -0,0 +1,6 @@ + + + + + + From 0ede26b8e86667b57a230b2923396b3c98c5a26a Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 28 Apr 2026 17:47:35 +0200 Subject: [PATCH 28/33] [CLN] awesome_dashboard: improve readability of pie_chart help with readability of code --- .../static/src/dashboard/pie_chart/pie_chart.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js index c71f490b738..d45d981738a 100644 --- a/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js +++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js @@ -21,14 +21,13 @@ export class PieChart extends Component { } destroyChart() { - if (this.chart) { - this.chart.destroy(); - } + this.chart?.destroy(); } renderChart() { this.chart = new Chart(this.canvas.el, { - type: "pie", data: { + type: "pie", + data: { labels: Object.keys(this.props.data), datasets: [ { From 8b8558a876999857486aef83a6a306149dd23856 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Wed, 29 Apr 2026 09:53:06 +0200 Subject: [PATCH 29/33] [IMP] awesome_dashboard: use a registry for the dashboard items dashboard items are shown from a registry making it possible for other addons to add more items to show --- awesome_dashboard/static/src/dashboard/dashboard.js | 3 +-- awesome_dashboard/static/src/dashboard/dashboard_items.js | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index 54147c31e65..233d31743fd 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -3,7 +3,6 @@ import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item/dashboard_item"; -import { items } from "./dashboard_items"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -12,7 +11,7 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); this.statistics = useState(useService("awesome_dashboard.statistics").loadStatistics); - this.items = items; + this.items = registry.category("awesome_dashboard").getAll(); } openCustomers() { diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items.js b/awesome_dashboard/static/src/dashboard/dashboard_items.js index cf99a817d88..b46c44d404e 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_items.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -1,5 +1,6 @@ import { NumberCard } from "./number_card/number_card"; import { PieChartCard } from "./pie_chart_card/pie_chart_card"; +import { registry } from "@web/core/registry"; export let items = [ { @@ -64,3 +65,5 @@ export let items = [ }, ]; + +items.forEach(item => registry.category("awesome_dashboard").add(item.id, item)); From 6dfb3d45f93f7af688c244505411420348d6dd96 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Wed, 29 Apr 2026 14:32:14 +0200 Subject: [PATCH 30/33] [IMP] awesome_dashboard: make dashboard items hideable make it possible to hide dashboarditems through a dialog --- .../static/src/dashboard/dashboard.js | 50 ++++++++++++++++--- .../static/src/dashboard/dashboard.xml | 17 ++++++- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index 233d31743fd..4347b4e2d34 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -1,8 +1,10 @@ -import { Component, useState } from "@odoo/owl"; +import { Component, useRef, useState } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item/dashboard_item"; +import { Dialog } from "@web/core/dialog/dialog"; +import { CheckBox } from "@web/core/checkbox/checkbox"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -11,7 +13,11 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); this.statistics = useState(useService("awesome_dashboard.statistics").loadStatistics); + this.dialogService = useService("dialog"); this.items = registry.category("awesome_dashboard").getAll(); + this.state = useState({ + disabled: localStorage.getItem("awesome_dashboard_disabled")?.split(',') || [] + }); } openCustomers() { @@ -20,15 +26,43 @@ class AwesomeDashboard extends Component { openLeads() { this.action.doAction({ - type: 'ir.actions.act_window', - target: 'current', - res_model: 'crm.lead', - views: [ - [false, "list"], - [false, 'form'], - ], + type: 'ir.actions.act_window', target: 'current', res_model: 'crm.lead', views: [[false, "list"], [false, 'form'],], }); } + + updateDashboard(disabled) { + this.state.disabled = disabled; + } + + openDialog() { + this.dialog = this.dialogService.add( + DashboardConfiguration, + {items: this.items, disabled: this.state.disabled, doneUpdating: this.updateDashboard.bind(this)}, + {}); + } +} + +class DashboardConfiguration extends Component { + static template = "awesome_dashboard.DashboardConfiguration"; + static components = {Dialog, CheckBox}; + static props = ["close", "items", "disabled", "doneUpdating"]; + + + setup() { + this.options = useRef("options"); + this.items = useState(this.props.items.map(item => ({...item, disabled: this.props.disabled.includes(item.id)}))); + } + + updateDisabled(item, checked) { + item.disabled = !checked; + } + + apply() { + const disabled = this.items.filter(item => item.disabled).map(item => item.id); + localStorage.setItem("awesome_dashboard_disabled", disabled); + this.props.doneUpdating(disabled); + this.props.close(); + } } registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard); diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index 0a613553142..a906c87a9ca 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -6,9 +6,12 @@
+ + + - + @@ -16,5 +19,17 @@ + + +
+ + + +
+ + + +
+
From 61531ba0509b6789de7b690215f7516802121578 Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Wed, 29 Apr 2026 15:04:11 +0200 Subject: [PATCH 31/33] [IMP] awesome_dashboard: add dutch translations make sure that every item is correctly translatable --- awesome_dashboard/i18n/nl.po | 117 ++++++++++++++++++ .../static/src/dashboard/dashboard.js | 4 +- .../static/src/dashboard/dashboard.xml | 2 +- .../static/src/dashboard/dashboard_items.js | 25 ++-- 4 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 awesome_dashboard/i18n/nl.po diff --git a/awesome_dashboard/i18n/nl.po b/awesome_dashboard/i18n/nl.po new file mode 100644 index 00000000000..4c0b01847a0 --- /dev/null +++ b/awesome_dashboard/i18n/nl.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * awesome_dashboard +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 19.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2026-04-29 12:41+0000\n" +"PO-Revision-Date: 2026-04-29 12:41+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Amount of orders this month" +msgstr "Aantal orders per maand" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard.xml:0 +msgid "Apply" +msgstr "Opslaan" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Average amount of t-shirt" +msgstr "Gemiddeld aantal t-shirt" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Average amount of t-shirt by order this month" +msgstr "Gemiddeld aantal t-shirts per bestelling deze maand" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Average time for an order" +msgstr "Gemiddelde tijd voor een order" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Average time for an order to go from new to sent or canceled" +msgstr "Gemiddelde tijd voor een bestelling om van nieuw naar verzonden of geannuleerd te gaan" + +#. module: awesome_dashboard +#: model:ir.ui.menu,name:awesome_dashboard.menu_root +msgid "Awesome Dashboard" +msgstr "Magisch overzicht" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Canceled orders this month" +msgstr "Geannulleerde orders deze maand" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard.xml:0 +msgid "Customers" +msgstr "Klanten" + +#. module: awesome_dashboard +#: model:ir.actions.client,name:awesome_dashboard.dashboard +#: model:ir.ui.menu,name:awesome_dashboard.dashboard_menu +msgid "Dashboard" +msgstr "Overzicht" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard.js:0 +msgid "Dashboard items configuration" +msgstr "Dashboard items configureren" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard.xml:0 +msgid "Leads" +msgstr "Prospecten" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "New orders this month" +msgstr "Nieuwe bestellingen deze maand" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Number of canceled orders this month" +msgstr "Aantal geannuleerde bestellingen deze maand" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Number of new orders this month" +msgstr "Aantal nieuwe orders deze maand" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Shirt orders by size" +msgstr "Shirt bestellingen per maat" + +#. module: awesome_dashboard +#. odoo-javascript +#: code:addons/awesome_dashboard/static/src/dashboard/dashboard_items.js:0 +msgid "Total amount of orders this month" +msgstr "Totaal aantal bestellingen deze maand" diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index 4347b4e2d34..0526eeeff8e 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -5,6 +5,7 @@ import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item/dashboard_item"; import { Dialog } from "@web/core/dialog/dialog"; import { CheckBox } from "@web/core/checkbox/checkbox"; +import { _t } from "@web/core/l10n/translation"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -44,13 +45,14 @@ class AwesomeDashboard extends Component { class DashboardConfiguration extends Component { static template = "awesome_dashboard.DashboardConfiguration"; - static components = {Dialog, CheckBox}; + static components = {Dialog, CheckBox, _t}; static props = ["close", "items", "disabled", "doneUpdating"]; setup() { this.options = useRef("options"); this.items = useState(this.props.items.map(item => ({...item, disabled: this.props.disabled.includes(item.id)}))); + this.title = _t('Dashboard items configuration'); } updateDisabled(item, checked) { diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index a906c87a9ca..61ca49dd1c0 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -20,7 +20,7 @@ - +
diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items.js b/awesome_dashboard/static/src/dashboard/dashboard_items.js index b46c44d404e..640b24a0f84 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_items.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -1,65 +1,66 @@ import { NumberCard } from "./number_card/number_card"; import { PieChartCard } from "./pie_chart_card/pie_chart_card"; import { registry } from "@web/core/registry"; +import { _t } from "@web/core/l10n/translation"; export let items = [ { id: "average_quantity", - description: "Average amount of t-shirt", + description: _t("Average amount of t-shirt"), Component: NumberCard, // size and props are optionals size: 3, props: (data) => ({ - title: "Average amount of t-shirt by order this month", + title: _t("Average amount of t-shirt by order this month"), value: data.average_quantity }), }, { id: "average_time", - description: "Average time for an order", + description: _t("Average time for an order"), Component: NumberCard, // size and props are optionals props: (data) => ({ - title: "Average time for an order to go from new to sent or canceled", + title: _t("Average time for an order to go from new to sent or canceled"), value: data.average_time }), }, { id: "nb_new_orders", - description: "New orders this month", + description: _t("New orders this month"), Component: NumberCard, // size and props are optionals props: (data) => ({ - title: "Number of new orders this month", + title: _t("Number of new orders this month"), value: data.nb_new_orders }), }, { id: "nb_cancelled_orders", - description: "Canceled orders this month", + description: _t("Canceled orders this month"), Component: NumberCard, // size and props are optionals props: (data) => ({ - title: "Number of canceled orders this month", + title: _t("Number of canceled orders this month"), value: data.nb_cancelled_orders }), }, { id: "total_amount", - description: "Smount of orders this month", + description: _t("Amount of orders this month"), Component: NumberCard, // size and props are optionals props: (data) => ({ - title: "Total amount of orders this month", + title: _t("Total amount of orders this month"), value: data.total_amount }), }, { id: "orders_by_size", - description: "Shirt orders by size", + description: _t("Shirt orders by size"), Component: PieChartCard, // size and props are optionals props: (data) => ({ - title: "Shirt orders by size", + title: _t("Shirt orders by size"), values: data.orders_by_size }), }, From 0dc5636ab0cd5085b63a73dc7ebb8be14267670d Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 5 May 2026 09:20:03 +0200 Subject: [PATCH 32/33] [CLN] estate: add a webcontroller make a clearer distinction between a disabled item and the list of disabled items --- .../static/src/dashboard/dashboard.js | 18 +++++++++--------- .../static/src/dashboard/dashboard.xml | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index 0526eeeff8e..dfccff6708e 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -17,7 +17,7 @@ class AwesomeDashboard extends Component { this.dialogService = useService("dialog"); this.items = registry.category("awesome_dashboard").getAll(); this.state = useState({ - disabled: localStorage.getItem("awesome_dashboard_disabled")?.split(',') || [] + disabledItems: localStorage.getItem("awesome_dashboard_disabled")?.split(',') || [] }); } @@ -31,14 +31,14 @@ class AwesomeDashboard extends Component { }); } - updateDashboard(disabled) { - this.state.disabled = disabled; + updateDashboard(disabledItems) { + this.state.disabledItems = disabledItems; } openDialog() { this.dialog = this.dialogService.add( DashboardConfiguration, - {items: this.items, disabled: this.state.disabled, doneUpdating: this.updateDashboard.bind(this)}, + {items: this.items, disabledItems: this.state.disabledItems, doneUpdating: this.updateDashboard.bind(this)}, {}); } } @@ -46,12 +46,12 @@ class AwesomeDashboard extends Component { class DashboardConfiguration extends Component { static template = "awesome_dashboard.DashboardConfiguration"; static components = {Dialog, CheckBox, _t}; - static props = ["close", "items", "disabled", "doneUpdating"]; + static props = ["close", "items", "disabledItems", "doneUpdating"]; setup() { this.options = useRef("options"); - this.items = useState(this.props.items.map(item => ({...item, disabled: this.props.disabled.includes(item.id)}))); + this.items = useState(this.props.items.map(item => ({...item, disabled: this.props.disabledItems.includes(item.id)}))); this.title = _t('Dashboard items configuration'); } @@ -60,9 +60,9 @@ class DashboardConfiguration extends Component { } apply() { - const disabled = this.items.filter(item => item.disabled).map(item => item.id); - localStorage.setItem("awesome_dashboard_disabled", disabled); - this.props.doneUpdating(disabled); + const disabledItems = this.items.filter(item => item.disabled).map(item => item.id); + localStorage.setItem("awesome_dashboard_disabled", disabledItems); + this.props.doneUpdating(disabledItems); this.props.close(); } } diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index 61ca49dd1c0..5820e960d17 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -11,7 +11,7 @@ - + From 483de3060abf6711df7c62d898de693764ee159f Mon Sep 17 00:00:00 2001 From: joemo-odoo Date: Tue, 5 May 2026 09:26:15 +0200 Subject: [PATCH 33/33] [MOV] estate: dashboard in its own file having separate responsibilities in separate files improves readability of the different components --- .../static/src/dashboard/dashboard.js | 30 ++----------------- .../static/src/dashboard/dashboard.xml | 12 -------- .../dashboard_configuration.js | 28 +++++++++++++++++ .../dashboard_configuration.xml | 14 +++++++++ 4 files changed, 44 insertions(+), 40 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard/dashboard_configuration/dashboard_configuration.js create mode 100644 awesome_dashboard/static/src/dashboard/dashboard_configuration/dashboard_configuration.xml diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index dfccff6708e..72325add281 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -1,11 +1,9 @@ -import { Component, useRef, useState } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item/dashboard_item"; -import { Dialog } from "@web/core/dialog/dialog"; -import { CheckBox } from "@web/core/checkbox/checkbox"; -import { _t } from "@web/core/l10n/translation"; +import { DashboardConfiguration } from "./dashboard_configuration/dashboard_configuration"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -43,28 +41,4 @@ class AwesomeDashboard extends Component { } } -class DashboardConfiguration extends Component { - static template = "awesome_dashboard.DashboardConfiguration"; - static components = {Dialog, CheckBox, _t}; - static props = ["close", "items", "disabledItems", "doneUpdating"]; - - - setup() { - this.options = useRef("options"); - this.items = useState(this.props.items.map(item => ({...item, disabled: this.props.disabledItems.includes(item.id)}))); - this.title = _t('Dashboard items configuration'); - } - - updateDisabled(item, checked) { - item.disabled = !checked; - } - - apply() { - const disabledItems = this.items.filter(item => item.disabled).map(item => item.id); - localStorage.setItem("awesome_dashboard_disabled", disabledItems); - this.props.doneUpdating(disabledItems); - this.props.close(); - } -} - registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard); diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index 5820e960d17..b6d922e1b1e 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -19,17 +19,5 @@ - - - - - - - - - - - -
diff --git a/awesome_dashboard/static/src/dashboard/dashboard_configuration/dashboard_configuration.js b/awesome_dashboard/static/src/dashboard/dashboard_configuration/dashboard_configuration.js new file mode 100644 index 00000000000..b94aa3d56e3 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard_configuration/dashboard_configuration.js @@ -0,0 +1,28 @@ +import { Component, useRef, useState } from "@odoo/owl"; +import { Dialog } from "@web/core/dialog/dialog"; +import { CheckBox } from "@web/core/checkbox/checkbox"; +import { _t } from "@web/core/l10n/translation"; + +export class DashboardConfiguration extends Component { + static template = "awesome_dashboard.DashboardConfiguration"; + static components = {Dialog, CheckBox, _t}; + static props = ["close", "items", "disabledItems", "doneUpdating"]; + + + setup() { + this.options = useRef("options"); + this.items = useState(this.props.items.map(item => ({...item, disabled: this.props.disabledItems.includes(item.id)}))); + this.title = _t('Dashboard items configuration'); + } + + updateDisabled(item, checked) { + item.disabled = !checked; + } + + apply() { + const disabledItems = this.items.filter(item => item.disabled).map(item => item.id); + localStorage.setItem("awesome_dashboard_disabled", disabledItems); + this.props.doneUpdating(disabledItems); + this.props.close(); + } +} diff --git a/awesome_dashboard/static/src/dashboard/dashboard_configuration/dashboard_configuration.xml b/awesome_dashboard/static/src/dashboard/dashboard_configuration/dashboard_configuration.xml new file mode 100644 index 00000000000..d583bdd05ed --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard_configuration/dashboard_configuration.xml @@ -0,0 +1,14 @@ + + + +
+ + + +
+ + + +
+
+