From 8242913ccc7a98c2cbba5db50e1692249036e414 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Tue, 23 Sep 2025 13:22:54 +0200 Subject: [PATCH 01/21] [ADD] todo: add new todo, card and counter components --- awesome_owl/static/src/card/card.js | 7 +++++++ awesome_owl/static/src/card/card.xml | 16 ++++++++++++++++ awesome_owl/static/src/counter/counter.js | 21 +++++++++++++++++++++ awesome_owl/static/src/counter/counter.xml | 10 ++++++++++ awesome_owl/static/src/playground.js | 22 +++++++++++++++++++++- awesome_owl/static/src/playground.xml | 15 ++++++++++++--- awesome_owl/static/src/todo/todo.js | 10 ++++++++++ awesome_owl/static/src/todo/todo_item.js | 14 ++++++++++++++ awesome_owl/static/src/todo/todo_item.xml | 17 +++++++++++++++++ awesome_owl/static/src/todo/todo_list.js | 22 ++++++++++++++++++++++ awesome_owl/static/src/todo/todo_list.xml | 12 ++++++++++++ 11 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 awesome_owl/static/src/card/card.js create mode 100644 awesome_owl/static/src/card/card.xml create mode 100644 awesome_owl/static/src/counter/counter.js create mode 100644 awesome_owl/static/src/counter/counter.xml create mode 100644 awesome_owl/static/src/todo/todo.js 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/card/card.js b/awesome_owl/static/src/card/card.js new file mode 100644 index 00000000000..cf37f6b5f18 --- /dev/null +++ b/awesome_owl/static/src/card/card.js @@ -0,0 +1,7 @@ +import { Component } from "@odoo/owl"; + +export class Card extends Component { + static template = "awesome_owl.card"; + + static props = ['title', 'body'] +} diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml new file mode 100644 index 00000000000..739dfabd4c1 --- /dev/null +++ b/awesome_owl/static/src/card/card.xml @@ -0,0 +1,16 @@ + + + + +
+
+
+ +
+

+ +

+
+
+
+
diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js new file mode 100644 index 00000000000..a7d3eeba563 --- /dev/null +++ b/awesome_owl/static/src/counter/counter.js @@ -0,0 +1,21 @@ +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: 1 }) + } + + increment() { + this.state.value++; + if(this.props.onChange){ + this.props.onChange(); + } + } +} diff --git a/awesome_owl/static/src/counter/counter.xml b/awesome_owl/static/src/counter/counter.xml new file mode 100644 index 00000000000..3eee18d5610 --- /dev/null +++ b/awesome_owl/static/src/counter/counter.xml @@ -0,0 +1,10 @@ + + + + +
+

Counter:

+ +
+
+
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 657fb8b07bb..ff12d353944 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,7 +1,27 @@ /** @odoo-module **/ -import { Component } from "@odoo/owl"; +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 = { TodoList, Counter, Card } + + setup() { + this.state = useState({sum: 2}) + } + + incrementSum() { + console.log('call') + this.state.sum++ + } + + card_body = markup(` + + content of card 2 + + `); } + diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 4fb905d59f9..7ba797f5bbe 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -2,9 +2,18 @@ -
- hello world +
+
+ Hi + +
+
+ + +
+

Sum:

+ +
- diff --git a/awesome_owl/static/src/todo/todo.js b/awesome_owl/static/src/todo/todo.js new file mode 100644 index 00000000000..7c399383384 --- /dev/null +++ b/awesome_owl/static/src/todo/todo.js @@ -0,0 +1,10 @@ +export class Todo { + id + description + isCompleted + constructor(id, description, isCompleted) { + this.id = id + this.description = description; + this.isCompleted = isCompleted; + } +} 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..2e6263a9759 --- /dev/null +++ b/awesome_owl/static/src/todo/todo_item.js @@ -0,0 +1,14 @@ +import { Component } from "@odoo/owl"; +import { Todo } from "./todo"; +import { Card } from "../card/card"; + +export class TodoItem extends Component { + static template = "awesome_owl.todo_item"; + static components = { Card }; + + static props = { todo: { type: Todo } } + + toggle() { + this.props.todo.isCompleted = !this.props.todo.isCompleted; + } +} 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..2a844e3d2df --- /dev/null +++ b/awesome_owl/static/src/todo/todo_item.xml @@ -0,0 +1,17 @@ + + + + +
+

+ + ✅ + + + 🔄 + +

+
+
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..8badd1fe883 --- /dev/null +++ b/awesome_owl/static/src/todo/todo_list.js @@ -0,0 +1,22 @@ +import { Component, useState } from "@odoo/owl"; +import { TodoItem } from "./todo_item"; +import { Todo } from "./todo"; +import { Card } from "../card/card"; + +export class TodoList extends Component { + static template = "awesome_owl.todo_list"; + static components = { Card, TodoItem }; + + ids = 0 + + setup() { + this.state = useState({ todos: [], input: ''}) + } + + keyup(event) { + if(event.keyCode === 13) { + this.state.todos.push(new Todo(this.ids++, event.srcElement.value, 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..8592412a1ef --- /dev/null +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -0,0 +1,12 @@ + + + +
+
Todos
+ + + + +
+
+
From b57ecf48a7e574531a46f8bc429f518a22dc22bd Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Tue, 23 Sep 2025 13:38:36 +0200 Subject: [PATCH 02/21] [IMP] todo: Focusing the input --- awesome_owl/static/src/todo/todo_list.js | 8 +++++--- awesome_owl/static/src/todo/todo_list.xml | 2 +- awesome_owl/static/src/utils.js | 8 ++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) 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 8badd1fe883..27b96693ca1 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -2,19 +2,21 @@ import { Component, useState } from "@odoo/owl"; import { TodoItem } from "./todo_item"; import { Todo } from "./todo"; import { Card } from "../card/card"; +import { useAutofocus } from "../utils"; export class TodoList extends Component { static template = "awesome_owl.todo_list"; static components = { Card, TodoItem }; ids = 0 - + setup() { - this.state = useState({ todos: [], input: ''}) + this.state = useState({ todos: [], input: '' }) + useAutofocus('todo_input') } keyup(event) { - if(event.keyCode === 13) { + if (event.keyCode === 13) { this.state.todos.push(new Todo(this.ids++, event.srcElement.value, false)) } } diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml index 8592412a1ef..faacad60736 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -3,7 +3,7 @@
Todos
- + diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js new file mode 100644 index 00000000000..5b16a111dda --- /dev/null +++ b/awesome_owl/static/src/utils.js @@ -0,0 +1,8 @@ +import { useRef, onMounted } from "@odoo/owl" + +export function useAutofocus(name) { + let ref = useRef(name) + onMounted(() => { + ref.el.focus() + }) +} From 2d3beffc47eadfc96b96f5b3ccb94cc9840e10a1 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Tue, 23 Sep 2025 13:56:38 +0200 Subject: [PATCH 03/21] [IMP] todo: deleting todos --- awesome_owl/static/src/todo/todo_item.js | 6 +++++- awesome_owl/static/src/todo/todo_item.xml | 6 ++++-- awesome_owl/static/src/todo/todo_list.js | 7 +++++++ awesome_owl/static/src/todo/todo_list.xml | 10 +++++----- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/awesome_owl/static/src/todo/todo_item.js b/awesome_owl/static/src/todo/todo_item.js index 2e6263a9759..bb94a6f3efc 100644 --- a/awesome_owl/static/src/todo/todo_item.js +++ b/awesome_owl/static/src/todo/todo_item.js @@ -6,9 +6,13 @@ export class TodoItem extends Component { static template = "awesome_owl.todo_item"; static components = { Card }; - static props = { todo: { type: Todo } } + static props = { todo: { type: Todo }, onRemove: { type: Function } } toggle() { this.props.todo.isCompleted = !this.props.todo.isCompleted; } + + remove() { + this.props.onRemove(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 2a844e3d2df..a9b8a1234d6 100644 --- a/awesome_owl/static/src/todo/todo_item.xml +++ b/awesome_owl/static/src/todo/todo_item.xml @@ -4,14 +4,16 @@

- + - + 🔄 +

diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js index 27b96693ca1..54c16a87647 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -20,5 +20,12 @@ export class TodoList extends Component { this.state.todos.push(new Todo(this.ids++, event.srcElement.value, false)) } } + + remove(id) { + const index = this.state.todos.findIndex((elem) => elem.id === id) + if (index >= 0) { + this.state.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 faacad60736..5c739261e6a 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -2,11 +2,11 @@
-
Todos
- - - - +
Todos
+ + + +
From 0c74508f5a7bf020a1a5d90fd49b0fb643b218a7 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Tue, 23 Sep 2025 14:03:57 +0200 Subject: [PATCH 04/21] [IMP] awesome_owl: generic card with slots --- awesome_owl/static/src/card/card.js | 2 +- awesome_owl/static/src/card/card.xml | 5 ++--- awesome_owl/static/src/playground.xml | 14 +++++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index cf37f6b5f18..d91bb8598c7 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -3,5 +3,5 @@ import { Component } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card"; - static props = ['title', 'body'] + static props = ['title', 'slots'] } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 739dfabd4c1..8dc6d53dbc0 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -7,9 +7,8 @@
-

- -

+ +
diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 7ba797f5bbe..161cd3dce47 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -9,11 +9,19 @@
- - + +

Content of card 1

+
+ + + content of card 2 + +

Sum:

- + + +
From 9cc166ec6f7a4b5f5965dbd1b118a114eab8fde9 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Tue, 23 Sep 2025 14:08:56 +0200 Subject: [PATCH 05/21] [IMP] awesome_owl: minimizing card content --- awesome_owl/static/src/card/card.js | 10 +++++++++- awesome_owl/static/src/card/card.xml | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index d91bb8598c7..a26e5851357 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -1,7 +1,15 @@ -import { Component } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card"; static props = ['title', 'slots'] + + setup() { + this.state = useState({ hidden: false }) + } + + hide() { + this.state.hidden = !this.state.hidden + } } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 8dc6d53dbc0..7dab6e4543c 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -4,10 +4,11 @@
-
+
+
- +
From 8ae564023f5653076c08e823344e6aa94e821de2 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Tue, 23 Sep 2025 15:16:42 +0200 Subject: [PATCH 06/21] [IMP] awesome_dashboard: add some buttons for quick navigation --- awesome_dashboard/static/src/dashboard.js | 21 +++++++++++++++++++++ awesome_dashboard/static/src/dashboard.scss | 3 +++ awesome_dashboard/static/src/dashboard.xml | 7 ++++++- 3 files changed, 30 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 637fa4bb972..c57878e117b 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,10 +1,31 @@ /** @odoo-module **/ +import { _t } from "@web/core/l10n/translation"; 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"; + static components = { Layout }; + + setup() { + this.action = useService("action"); + } + + openCustomers() { + this.action.doAction('base.action_partner_form') + } + + openLeads() { + this.action.doAction({ + type: 'ir.actions.act_window', + name: _t('Leads'), + 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..6be5e0f83c9 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard.scss @@ -0,0 +1,3 @@ +.o_dashboard { + background-color: gray; +} diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 1a2ac9a2fed..6ff5d43a338 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -2,7 +2,12 @@ - hello dashboard + + + + + + From 3c99f455f92414c549c8bdb5c1b602fd8d3e8461 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Tue, 23 Sep 2025 15:41:08 +0200 Subject: [PATCH 07/21] [IMP] awesome_dashboard: add a dashboard item --- awesome_dashboard/static/src/dashboard.js | 3 ++- awesome_dashboard/static/src/dashboard.xml | 5 +++++ awesome_dashboard/static/src/dashboard_item.js | 13 +++++++++++++ awesome_dashboard/static/src/dashboard_item.xml | 11 +++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 awesome_dashboard/static/src/dashboard_item.js create mode 100644 awesome_dashboard/static/src/dashboard_item.xml diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index c57878e117b..ee07328fbf9 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -5,10 +5,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"; 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 6ff5d43a338..428d04abc42 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -7,6 +7,11 @@
+
+ some content + I love milk + some content +
diff --git a/awesome_dashboard/static/src/dashboard_item.js b/awesome_dashboard/static/src/dashboard_item.js new file mode 100644 index 00000000000..ddd2217fddd --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item.js @@ -0,0 +1,13 @@ +import { Component } from "@odoo/owl"; + +export class DashboardItem extends Component { + static template = "awesome_dashboard.DashboardItem" + + static props = {'size': {type: Number, optional: true }} + + setup() { + if(!this.props.size) { + this.props.size = 1 + } + } +} diff --git a/awesome_dashboard/static/src/dashboard_item.xml b/awesome_dashboard/static/src/dashboard_item.xml new file mode 100644 index 00000000000..16024bcb704 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item.xml @@ -0,0 +1,11 @@ + + + +
+
+ + +
+
+
+
From 2726b2e12db9b6e92dedd608592625058b12b29b Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Tue, 23 Sep 2025 15:55:51 +0200 Subject: [PATCH 08/21] [IMP] awesome_dashboard: call the server, add some statistics --- awesome_dashboard/static/src/dashboard.js | 9 +++-- awesome_dashboard/static/src/dashboard.xml | 33 +++++++++++++++++-- .../static/src/dashboard_item.scss | 3 ++ 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard_item.scss diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index ee07328fbf9..e04f5d7cf60 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,11 +1,12 @@ /** @odoo-module **/ import { _t } from "@web/core/l10n/translation"; -import { Component } from "@odoo/owl"; +import { Component, useState, onWillStart } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; -import { useService } from "@web/core/utils/hooks"; +import { useService, } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item"; +import { rpc } from "@web/core/network/rpc"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -13,6 +14,10 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); + this.state = useState({stats: []}) + onWillStart(async () => { + this.state.stats = await rpc("/awesome_dashboard/statistics") + }) } openCustomers() { diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 428d04abc42..9fde21b0a0f 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -8,11 +8,38 @@
- some content - I love milk - some content + + Average amount of t-shirt by order this month +

+
+ + Average time for an order to go from 'new' to 'sent' or 'cancelled' +

+
+ + Number of new orders this month +

+
+ + Number of cancelled orders this month +

+
+ + Total amount of new orders this month +

+
+ + + diff --git a/awesome_dashboard/static/src/dashboard_item.scss b/awesome_dashboard/static/src/dashboard_item.scss new file mode 100644 index 00000000000..6345fd32280 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item.scss @@ -0,0 +1,3 @@ +h1 { + color: green; +} From 01348039e42a0514ab93512108e3998fc1bebb4d Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Tue, 23 Sep 2025 16:59:34 +0200 Subject: [PATCH 09/21] [IMP] awesome_dashboard: cache network calls, create a service --- awesome_dashboard/static/src/dashboard.js | 7 ++++--- .../services/awesome_dashboard.statistics.js | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 awesome_dashboard/static/src/services/awesome_dashboard.statistics.js diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index e04f5d7cf60..6e2568fc57e 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -6,7 +6,7 @@ import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService, } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item"; -import { rpc } from "@web/core/network/rpc"; + class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -14,9 +14,10 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); - this.state = useState({stats: []}) + this.statisticsService = useService("awesome_dashboard.statistics"); + this.state = useState({stats: {}}) onWillStart(async () => { - this.state.stats = await rpc("/awesome_dashboard/statistics") + this.state.stats = await this.statisticsService.loadStatistics() }) } diff --git a/awesome_dashboard/static/src/services/awesome_dashboard.statistics.js b/awesome_dashboard/static/src/services/awesome_dashboard.statistics.js new file mode 100644 index 00000000000..c14ce547ce5 --- /dev/null +++ b/awesome_dashboard/static/src/services/awesome_dashboard.statistics.js @@ -0,0 +1,17 @@ +import { rpc } from "@web/core/network/rpc"; +import { registry } from "@web/core/registry"; +import { memoize } from "@web/core/utils/functions"; + +export function loadStatistics() { + return rpc("/awesome_dashboard/statistics") +} + +export const awesomeDashboardStatisticsService = { + start() { + return { loadStatistics: memoize(loadStatistics) }; + } +} + +registry.category( + "services").add( + "awesome_dashboard.statistics", awesomeDashboardStatisticsService) From 4346a21a83e8ed801b95942ac9111edf71d4310e Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Wed, 24 Sep 2025 09:30:52 +0200 Subject: [PATCH 10/21] [IMP] awesome_dashboard: display a pie chart --- awesome_dashboard/static/src/dashboard.js | 5 ++-- awesome_dashboard/static/src/dashboard.xml | 15 +++-------- .../static/src/pie_chart/pie_chart.js | 27 +++++++++++++++++++ .../static/src/pie_chart/pie_chart.xml | 6 +++++ 4 files changed, 40 insertions(+), 13 deletions(-) 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 6e2568fc57e..dc760608473 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -4,13 +4,14 @@ import { _t } from "@web/core/l10n/translation"; import { Component, useState, onWillStart } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; -import { useService, } from "@web/core/utils/hooks"; +import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./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 9fde21b0a0f..d4d7e834b95 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -7,7 +7,7 @@ -
+
Average amount of t-shirt by order this month

@@ -28,18 +28,11 @@ Total amount of new orders this month

+ + +
- - - 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..4b5d00d0675 --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.js @@ -0,0 +1,27 @@ +import { Component, onWillStart, useEffect, useRef } from "@odoo/owl" +import { loadJS } from "@web/core/assets" + +export class PieChart extends Component { + static template = "awesome_dashboard.PieChart"; + + static props = {'data':{optional: false}, 'size': {type: Number, optional: true}} + + setup() { + onWillStart(() => loadJS(["/web/static/lib/Chart/Chart.js"])); + this.ctx = useRef('pieChart') + this.chart = null + useEffect(() => { + if(this.chart) { + this.chart.destroy() + } + const dataset = { + labels: Object.keys(this.props.data), + datasets: [{ + label: 'T-Shirt Size Distribution', + data: Object.values(this.props.data) + }] + } + this.chart = new Chart(this.ctx.el, {type: 'pie', data: dataset}) + }) + } +} 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..ce4bf017d70 --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.xml @@ -0,0 +1,6 @@ + + + + + + From a5fa22ab2f32626448b02c63b4967b2c42e99ef9 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Wed, 24 Sep 2025 10:55:46 +0200 Subject: [PATCH 11/21] [IMP] awesome_dashboard: real life update --- awesome_dashboard/static/src/dashboard.js | 9 +++------ .../src/services/awesome_dashboard.statistics.js | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index dc760608473..96c53cca34b 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { _t } from "@web/core/l10n/translation"; -import { Component, useState, 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"; @@ -15,11 +15,8 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); - this.statisticsService = useService("awesome_dashboard.statistics"); - this.state = useState({stats: {}}) - onWillStart(async () => { - this.state.stats = await this.statisticsService.loadStatistics() - }) + this.statistics = useService("awesome_dashboard.statistics"); + this.state = useState({stats: this.statistics}); } openCustomers() { diff --git a/awesome_dashboard/static/src/services/awesome_dashboard.statistics.js b/awesome_dashboard/static/src/services/awesome_dashboard.statistics.js index c14ce547ce5..c775a11fe85 100644 --- a/awesome_dashboard/static/src/services/awesome_dashboard.statistics.js +++ b/awesome_dashboard/static/src/services/awesome_dashboard.statistics.js @@ -1,6 +1,6 @@ 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 function loadStatistics() { return rpc("/awesome_dashboard/statistics") @@ -8,7 +8,17 @@ export function loadStatistics() { export const awesomeDashboardStatisticsService = { start() { - return { loadStatistics: memoize(loadStatistics) }; + let stats = reactive({}) + const getStats = async () => { + let newStats = await loadStatistics() + Object.assign(stats, newStats) + } + + setInterval(getStats, 1000 * 60 * 10) + + getStats() + + return stats } } From abddaa5ee2fb43b128ea36af959fa03d87e31aa6 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Wed, 24 Sep 2025 11:20:32 +0200 Subject: [PATCH 12/21] [IMP] awesome_dashboard: lazy loading the dashboard --- .../static/src/{ => dashboard}/dashboard.js | 2 +- .../static/src/{ => dashboard}/dashboard.scss | 0 .../static/src/{ => dashboard}/dashboard.xml | 0 .../static/src/{ => dashboard}/dashboard_item.js | 0 .../static/src/{ => dashboard}/dashboard_item.scss | 0 .../static/src/{ => dashboard}/dashboard_item.xml | 0 .../src/{ => dashboard}/pie_chart/pie_chart.js | 0 .../src/{ => dashboard}/pie_chart/pie_chart.xml | 0 .../services/awesome_dashboard.statistics.js | 0 awesome_dashboard/static/src/dashboard_action.js | 12 ++++++++++++ 10 files changed, 13 insertions(+), 1 deletion(-) 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.js (100%) rename awesome_dashboard/static/src/{ => dashboard}/dashboard_item.scss (100%) rename awesome_dashboard/static/src/{ => dashboard}/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}/services/awesome_dashboard.statistics.js (100%) create mode 100644 awesome_dashboard/static/src/dashboard_action.js 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 96c53cca34b..b47082ed1b6 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -33,4 +33,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.js b/awesome_dashboard/static/src/dashboard/dashboard_item.js similarity index 100% rename from awesome_dashboard/static/src/dashboard_item.js rename to awesome_dashboard/static/src/dashboard/dashboard_item.js diff --git a/awesome_dashboard/static/src/dashboard_item.scss b/awesome_dashboard/static/src/dashboard/dashboard_item.scss similarity index 100% rename from awesome_dashboard/static/src/dashboard_item.scss rename to awesome_dashboard/static/src/dashboard/dashboard_item.scss diff --git a/awesome_dashboard/static/src/dashboard_item.xml b/awesome_dashboard/static/src/dashboard/dashboard_item.xml similarity index 100% rename from awesome_dashboard/static/src/dashboard_item.xml rename to awesome_dashboard/static/src/dashboard/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/services/awesome_dashboard.statistics.js b/awesome_dashboard/static/src/dashboard/services/awesome_dashboard.statistics.js similarity index 100% rename from awesome_dashboard/static/src/services/awesome_dashboard.statistics.js rename to awesome_dashboard/static/src/dashboard/services/awesome_dashboard.statistics.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..76d73df846d --- /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 DashboardAction extends Component { + static components = { LazyComponent } + static template = xml` + + ` +} + +registry.category("actions").add("awesome_dashboard.dashboard", DashboardAction) From 3416192b9ef60467f6e99318856a371c9a4f9b4f Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Wed, 24 Sep 2025 13:18:35 +0200 Subject: [PATCH 13/21] [IMP] awesome_dashboard: making the dashboard extensible --- .../static/src/dashboard/dashboard.js | 3 + .../static/src/dashboard/dashboard.xml | 31 +++------ .../static/src/dashboard/dashboard_item.js | 5 +- .../static/src/dashboard/dashboard_items.js | 65 +++++++++++++++++++ .../static/src/dashboard/number_card.js | 12 ++++ .../static/src/dashboard/pie_chart_card.js | 15 +++++ 6 files changed, 107 insertions(+), 24 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard/dashboard_items.js create mode 100644 awesome_dashboard/static/src/dashboard/number_card.js create mode 100644 awesome_dashboard/static/src/dashboard/pie_chart_card.js diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index b47082ed1b6..86ae69360df 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -6,6 +6,7 @@ import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item"; +import { items } from "./dashboard_items"; import { PieChart } from "./pie_chart/pie_chart"; @@ -17,6 +18,8 @@ class AwesomeDashboard extends Component { this.action = useService("action"); this.statistics = useService("awesome_dashboard.statistics"); this.state = useState({stats: this.statistics}); + + this.items = items } openCustomers() { diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index d4d7e834b95..03a9298d2ae 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -8,29 +8,14 @@
- - Average amount of t-shirt by order this month -

-
- - Average time for an order to go from 'new' to 'sent' or 'cancelled' -

-
- - Number of new orders this month -

-
- - Number of cancelled orders this month -

-
- - Total amount of new orders this month -

-
- - - + + + + + +
diff --git a/awesome_dashboard/static/src/dashboard/dashboard_item.js b/awesome_dashboard/static/src/dashboard/dashboard_item.js index ddd2217fddd..1c92b7b8b49 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_item.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_item.js @@ -3,7 +3,10 @@ import { Component } from "@odoo/owl"; export class DashboardItem extends Component { static template = "awesome_dashboard.DashboardItem" - static props = {'size': {type: Number, optional: true }} + static props = { + 'size': {type: Number, optional: true }, + 'slots': {} + } setup() { if(!this.props.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..84620ed044a --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -0,0 +1,65 @@ +import { NumberCard } from "./number_card"; +import { PieChartCard } from "./pie_chart_card"; + +export const items = [ + { + id: "average_quantity", + description: "Average amount of t-shirt", + Component: NumberCard, + size: 1, + props: (data) => ({ + title: "Average amount of t-shirt by order this month", + value: data.average_quantity + }) + }, + { + id: "average_time", + description: "Average time for orders", + Component: NumberCard, + size: 1, + props: (data) => ({ + title: "Average time for an order to go from 'new' to 'sent' or 'cancelled'", + value: data.average_time + }) + }, + { + id: "nb_new_orders", + description: "Number of new orders", + Component: NumberCard, + size: 1, + props: (data) => ({ + title: "Number of new orders this month", + value: data.nb_new_orders + }) + }, + { + id: "nb_cancelled_orders", + description: "Number of cancelled orders", + Component: NumberCard, + size: 1, + props: (data) => ({ + title: "Number of cancelled orders this month", + value: data.nb_cancelled_orders + }) + }, + { + id: "total_amount", + description: "Total amount of new orders", + Component: NumberCard, + size: 1, + props: (data) => ({ + title: "Total amount of new orders this month", + value: data.total_amount + }) + }, + { + id: "orders_by_size", + description: "Shirt orders by size", + Component: PieChartCard, + size: 2, + props: (data) => ({ + title: "Shirt orders by size", + value: data.orders_by_size + }) + }, +] diff --git a/awesome_dashboard/static/src/dashboard/number_card.js b/awesome_dashboard/static/src/dashboard/number_card.js new file mode 100644 index 00000000000..c3e5bd195c6 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/number_card.js @@ -0,0 +1,12 @@ +import { Component, xml } from "@odoo/owl" + +export class NumberCard extends Component{ + static template = xml` +

+

+ ` + static props = { + title: [String], + value: [String, Number] + } +} diff --git a/awesome_dashboard/static/src/dashboard/pie_chart_card.js b/awesome_dashboard/static/src/dashboard/pie_chart_card.js new file mode 100644 index 00000000000..bcd85364c68 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/pie_chart_card.js @@ -0,0 +1,15 @@ +import { Component, xml } from "@odoo/owl"; +import { PieChart } from "./pie_chart/pie_chart"; + +export class PieChartCard extends Component{ + static components = { PieChart }; + static props = { + title: [String], + value: [Object] + } + + static template = xml` +

+ + ` +} From 6e53f4ba88f33b5927a6bb20fb776b8c4e942b44 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Wed, 24 Sep 2025 13:28:21 +0200 Subject: [PATCH 14/21] [IMP] awesome_dashboard: make the dashboard extensible --- awesome_dashboard/static/src/dashboard/dashboard.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index 86ae69360df..126e6d9852e 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -19,7 +19,10 @@ class AwesomeDashboard extends Component { this.statistics = useService("awesome_dashboard.statistics"); this.state = useState({stats: this.statistics}); - this.items = items + for(let item of items) { + registry.category("awesome_dashboard").add(item.id, item); + } + this.items = registry.category("awesome_dashboard").getAll(); } openCustomers() { From 0df96837b6c41edb333893834ff15ea13105cf26 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Wed, 24 Sep 2025 15:47:57 +0200 Subject: [PATCH 15/21] [IMP] awesome_dashboard: add and remove dashboard items --- .../src/dashboard/configuration_dialog.js | 33 +++++++++++++++++ .../src/dashboard/configuration_dialog.xml | 22 +++++++++++ .../static/src/dashboard/dashboard.js | 37 ++++++++++++++++--- .../static/src/dashboard/dashboard.xml | 5 ++- .../static/src/dashboard/dashboard_items.js | 7 +++- .../src/dashboard/pie_chart/pie_chart.js | 5 ++- awesome_owl/static/src/playground.js | 1 - 7 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard/configuration_dialog.js create mode 100644 awesome_dashboard/static/src/dashboard/configuration_dialog.xml diff --git a/awesome_dashboard/static/src/dashboard/configuration_dialog.js b/awesome_dashboard/static/src/dashboard/configuration_dialog.js new file mode 100644 index 00000000000..19775b90821 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/configuration_dialog.js @@ -0,0 +1,33 @@ +import { Component } from "@odoo/owl"; +import { Dialog } from "@web/core/dialog/dialog"; +import { CheckBox } from "@web/core/checkbox/checkbox"; + +export class ConfigurationDialog extends Component { + static template = "awesome_dashboard.ConfigurationDialog" + static components = { Dialog, CheckBox } + static props = { + items: [Array], + close: [{}], + onApply: [Function] + } + + setup() { + this.disabledElements = this.props.items.filter(item => !item.enabled) + .map(item => item.element.id) + } + + onChange(id) { + let index = this.disabledElements.indexOf(id) + if(index === -1) { + this.disabledElements.push(id) + return; + } + this.disabledElements.splice(index, 1) + } + + apply() { + localStorage.setItem('disabledElements', this.disabledElements) + this.props.onApply(); + this.props.close() + } +} diff --git a/awesome_dashboard/static/src/dashboard/configuration_dialog.xml b/awesome_dashboard/static/src/dashboard/configuration_dialog.xml new file mode 100644 index 00000000000..15b2a204f40 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/configuration_dialog.xml @@ -0,0 +1,22 @@ + + + + +
+ +
+

+ +
+
+
+ + + +
+
+
diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index 126e6d9852e..53e24aa55d2 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -6,8 +6,8 @@ import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item"; -import { items } from "./dashboard_items"; import { PieChart } from "./pie_chart/pie_chart"; +import { ConfigurationDialog } from "./configuration_dialog"; class AwesomeDashboard extends Component { @@ -17,12 +17,22 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); this.statistics = useService("awesome_dashboard.statistics"); - this.state = useState({stats: this.statistics}); + this.state = useState({items: [], stats: this.statistics}); + this.dialog = useService("dialog"); + this.updateDashboard() + } - for(let item of items) { - registry.category("awesome_dashboard").add(item.id, item); + updateDashboard() { + let disabledElements = localStorage.getItem('disabledElements') || ''; + if(disabledElements.includes(',')) { + disabledElements = disabledElements.split(',') + } + else{ + disabledElements = [disabledElements] } - this.items = registry.category("awesome_dashboard").getAll(); + this.state.items = registry.category("awesome_dashboard") + .getAll() + .filter(el => !disabledElements.some((e) => e == el.id )) } openCustomers() { @@ -37,6 +47,23 @@ class AwesomeDashboard extends Component { views: [[false, 'list'], [false, 'form']] }) } + + customizeDashboard() { + let items = [] + let all = registry.category("awesome_dashboard").getAll(); + all.forEach(el => { + const enabled = this.state.items.some(item => item.id == el.id) + items.push({ + element: el, + enabled: enabled + }) + }) + + this.dialog.add(ConfigurationDialog, { + items: items, + onApply: this.updateDashboard.bind(this) + }) + } } 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 03a9298d2ae..c39c8d48e81 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -6,9 +6,12 @@ +
- + loadJS(["/web/static/lib/Chart/Chart.js"])); diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index ff12d353944..50394f3a639 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -14,7 +14,6 @@ export class Playground extends Component { } incrementSum() { - console.log('call') this.state.sum++ } From 9842f556a19021205f2fcfb20222edf6c0410fd5 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Wed, 24 Sep 2025 15:55:59 +0200 Subject: [PATCH 16/21] [IMP] awesome_dashboard: add translations to text --- .../static/src/dashboard/dashboard_items.js | 26 ++++++++++--------- .../src/dashboard/pie_chart/pie_chart.js | 1 - 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items.js b/awesome_dashboard/static/src/dashboard/dashboard_items.js index 821d907fd9c..dd23b1f68f5 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_items.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -1,65 +1,67 @@ import { NumberCard } from "./number_card"; import { registry } from "@web/core/registry"; import { PieChartCard } from "./pie_chart_card"; +import { _t } from "@web/core/l10n/translation"; + const items = [ { id: "average_quantity", - description: "Average amount of t-shirt", + description: _t("Average amount of t-shirt"), Component: NumberCard, size: 1, 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 orders", + description: _t("Average time for orders"), Component: NumberCard, size: 1, props: (data) => ({ - title: "Average time for an order to go from 'new' to 'sent' or 'cancelled'", + title: _t("Average time for an order to go from 'new' to 'sent' or 'cancelled'"), value: data.average_time }) }, { id: "nb_new_orders", - description: "Number of new orders", + description: _t("Number of new orders"), Component: NumberCard, size: 1, 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: "Number of cancelled orders", + description: _t("Number of cancelled orders"), Component: NumberCard, size: 1, props: (data) => ({ - title: "Number of cancelled orders this month", + title: _t("Number of cancelled orders this month"), value: data.nb_cancelled_orders }) }, { id: "total_amount", - description: "Total amount of new orders", + description: _t("Total amount of new orders"), Component: NumberCard, size: 1, props: (data) => ({ - title: "Total amount of new orders this month", + title: _t("Total amount of new 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: 2, props: (data) => ({ - title: "Shirt orders by size", + title: _t("Shirt orders by size"), value: data.orders_by_size }) }, 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 b2836eb8b1c..d1d14aacdb9 100644 --- a/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js +++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js @@ -20,7 +20,6 @@ export class PieChart extends Component { const dataset = { labels: Object.keys(this.props.data), datasets: [{ - label: 'T-Shirt Size Distribution', data: Object.values(this.props.data) }] } From bce86ab52fb020f0d2bd75c2e160e264b1d2f157 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Wed, 24 Sep 2025 16:17:23 +0200 Subject: [PATCH 17/21] [FIX] awesome_dashboard: run prettier --- .../src/dashboard/configuration_dialog.js | 29 +++++----- .../static/src/dashboard/dashboard.js | 55 +++++++++---------- .../static/src/dashboard/dashboard.scss | 2 +- .../static/src/dashboard/dashboard.xml | 5 +- .../static/src/dashboard/dashboard_item.js | 14 ++--- .../static/src/dashboard/dashboard_item.scss | 2 +- .../static/src/dashboard/dashboard_items.js | 33 +++++------ .../static/src/dashboard/number_card.js | 12 ++-- .../src/dashboard/pie_chart/pie_chart.js | 34 ++++++------ .../static/src/dashboard/pie_chart_card.js | 10 ++-- .../services/awesome_dashboard.statistics.js | 28 +++++----- .../static/src/dashboard_action.js | 14 +++-- awesome_owl/static/src/card/card.js | 8 +-- awesome_owl/static/src/card/card.xml | 2 +- awesome_owl/static/src/counter/counter.js | 9 +-- awesome_owl/static/src/playground.js | 7 +-- awesome_owl/static/src/playground.xml | 2 +- awesome_owl/static/src/todo/todo.js | 8 +-- awesome_owl/static/src/todo/todo_item.js | 4 +- awesome_owl/static/src/todo/todo_list.js | 16 +++--- awesome_owl/static/src/todo/todo_list.xml | 3 +- awesome_owl/static/src/utils.js | 8 +-- 22 files changed, 154 insertions(+), 151 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/configuration_dialog.js b/awesome_dashboard/static/src/dashboard/configuration_dialog.js index 19775b90821..71d3d9cfb34 100644 --- a/awesome_dashboard/static/src/dashboard/configuration_dialog.js +++ b/awesome_dashboard/static/src/dashboard/configuration_dialog.js @@ -3,31 +3,32 @@ import { Dialog } from "@web/core/dialog/dialog"; import { CheckBox } from "@web/core/checkbox/checkbox"; export class ConfigurationDialog extends Component { - static template = "awesome_dashboard.ConfigurationDialog" - static components = { Dialog, CheckBox } + static template = "awesome_dashboard.ConfigurationDialog"; + static components = { Dialog, CheckBox }; static props = { - items: [Array], - close: [{}], - onApply: [Function] - } + items: Array, + close: {}, + onApply: Function, + }; setup() { - this.disabledElements = this.props.items.filter(item => !item.enabled) - .map(item => item.element.id) + this.disabledElements = this.props.items + .filter((item) => !item.enabled) + .map((item) => item.element.id); } onChange(id) { - let index = this.disabledElements.indexOf(id) - if(index === -1) { - this.disabledElements.push(id) + let index = this.disabledElements.indexOf(id); + if (index === -1) { + this.disabledElements.push(id); return; } - this.disabledElements.splice(index, 1) + this.disabledElements.splice(index, 1); } apply() { - localStorage.setItem('disabledElements', this.disabledElements) + localStorage.setItem("disabledElements", this.disabledElements); this.props.onApply(); - this.props.close() + this.props.close(); } } diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index 53e24aa55d2..a51baddb1d1 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -9,7 +9,6 @@ import { DashboardItem } from "./dashboard_item"; import { PieChart } from "./pie_chart/pie_chart"; import { ConfigurationDialog } from "./configuration_dialog"; - class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; static components = { Layout, DashboardItem, PieChart }; @@ -17,52 +16,52 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); this.statistics = useService("awesome_dashboard.statistics"); - this.state = useState({items: [], stats: this.statistics}); + this.state = useState({ items: [], stats: this.statistics }); this.dialog = useService("dialog"); - this.updateDashboard() + this.updateDashboard(); } updateDashboard() { - let disabledElements = localStorage.getItem('disabledElements') || ''; - if(disabledElements.includes(',')) { - disabledElements = disabledElements.split(',') - } - else{ - disabledElements = [disabledElements] + const disabledElementsString = localStorage.getItem("disabledElements") || ""; + let disabledElementsList + if (disabledElementsString.includes(",")) { + disabledElementsList = disabledElementsString.split(","); + } else { + disabledElementsList = [disabledElementsString]; } - this.state.items = registry.category("awesome_dashboard") + this.state.items = registry + .category("awesome_dashboard") .getAll() - .filter(el => !disabledElements.some((e) => e == el.id )) + .filter((el) => !disabledElementsList.some((e) => e == el.id)); } openCustomers() { - this.action.doAction('base.action_partner_form') + this.action.doAction("base.action_partner_form"); } openLeads() { this.action.doAction({ - type: 'ir.actions.act_window', - name: _t('Leads'), - res_model: 'crm.lead', - views: [[false, 'list'], [false, 'form']] - }) + type: "ir.actions.act_window", + name: _t("Leads"), + res_model: "crm.lead", + views: [ + [false, "list"], + [false, "form"], + ], + }); } customizeDashboard() { - let items = [] let all = registry.category("awesome_dashboard").getAll(); - all.forEach(el => { - const enabled = this.state.items.some(item => item.id == el.id) - items.push({ - element: el, - enabled: enabled - }) - }) this.dialog.add(ConfigurationDialog, { - items: items, - onApply: this.updateDashboard.bind(this) - }) + items: all.map(item => ({ + element: item, + enabled: this.state.items.some((element) => item.id == element.id) + })) + , + onApply: this.updateDashboard.bind(this), + }); } } diff --git a/awesome_dashboard/static/src/dashboard/dashboard.scss b/awesome_dashboard/static/src/dashboard/dashboard.scss index 6be5e0f83c9..32862ec0d82 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.scss +++ b/awesome_dashboard/static/src/dashboard/dashboard.scss @@ -1,3 +1,3 @@ .o_dashboard { - background-color: gray; + background-color: gray; } diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index c39c8d48e81..18f1d0039ff 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -14,8 +14,9 @@ + ? item.props(state.stats) + : {'data': state.stats}" + /> diff --git a/awesome_dashboard/static/src/dashboard/dashboard_item.js b/awesome_dashboard/static/src/dashboard/dashboard_item.js index 1c92b7b8b49..baaf5a71aa4 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_item.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_item.js @@ -1,16 +1,14 @@ import { Component } from "@odoo/owl"; export class DashboardItem extends Component { - static template = "awesome_dashboard.DashboardItem" + static template = "awesome_dashboard.DashboardItem"; static props = { - 'size': {type: Number, optional: true }, - 'slots': {} - } + size: { type: Number, optional: true }, + slots: {}, + }; - setup() { - if(!this.props.size) { - this.props.size = 1 - } + static defaultProps = { + size: 1 } } diff --git a/awesome_dashboard/static/src/dashboard/dashboard_item.scss b/awesome_dashboard/static/src/dashboard/dashboard_item.scss index 6345fd32280..dda2cdf86b0 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_item.scss +++ b/awesome_dashboard/static/src/dashboard/dashboard_item.scss @@ -1,3 +1,3 @@ h1 { - color: green; + color: green; } diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items.js b/awesome_dashboard/static/src/dashboard/dashboard_items.js index dd23b1f68f5..895e06eaeb6 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_items.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -3,7 +3,6 @@ import { registry } from "@web/core/registry"; import { PieChartCard } from "./pie_chart_card"; import { _t } from "@web/core/l10n/translation"; - const items = [ { id: "average_quantity", @@ -12,8 +11,8 @@ const items = [ size: 1, props: (data) => ({ title: _t("Average amount of t-shirt by order this month"), - value: data.average_quantity - }) + value: data.average_quantity, + }), }, { id: "average_time", @@ -21,9 +20,11 @@ const items = [ Component: NumberCard, size: 1, props: (data) => ({ - title: _t("Average time for an order to go from 'new' to 'sent' or 'cancelled'"), - value: data.average_time - }) + title: _t( + "Average time for an order to go from 'new' to 'sent' or 'cancelled'", + ), + value: data.average_time, + }), }, { id: "nb_new_orders", @@ -32,8 +33,8 @@ const items = [ size: 1, props: (data) => ({ title: _t("Number of new orders this month"), - value: data.nb_new_orders - }) + value: data.nb_new_orders, + }), }, { id: "nb_cancelled_orders", @@ -42,8 +43,8 @@ const items = [ size: 1, props: (data) => ({ title: _t("Number of cancelled orders this month"), - value: data.nb_cancelled_orders - }) + value: data.nb_cancelled_orders, + }), }, { id: "total_amount", @@ -52,8 +53,8 @@ const items = [ size: 1, props: (data) => ({ title: _t("Total amount of new orders this month"), - value: data.total_amount - }) + value: data.total_amount, + }), }, { id: "orders_by_size", @@ -62,11 +63,11 @@ const items = [ size: 2, props: (data) => ({ title: _t("Shirt orders by size"), - value: data.orders_by_size - }) + value: data.orders_by_size, + }), }, -] +]; -for(let item of items) { +for (let item of items) { registry.category("awesome_dashboard").add(item.id, item); } diff --git a/awesome_dashboard/static/src/dashboard/number_card.js b/awesome_dashboard/static/src/dashboard/number_card.js index c3e5bd195c6..f086666c407 100644 --- a/awesome_dashboard/static/src/dashboard/number_card.js +++ b/awesome_dashboard/static/src/dashboard/number_card.js @@ -1,12 +1,12 @@ -import { Component, xml } from "@odoo/owl" +import { Component, xml } from "@odoo/owl"; -export class NumberCard extends Component{ +export class NumberCard extends Component { static template = xml`

- ` + `; static props = { - title: [String], - value: [String, Number] - } + title: String, + value: [String, Number], + }; } 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 d1d14aacdb9..e276550b05a 100644 --- a/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js +++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js @@ -1,29 +1,31 @@ -import { Component, onWillStart, useEffect, useRef } from "@odoo/owl" -import { loadJS } from "@web/core/assets" +import { Component, onWillStart, useRef, onMounted } from "@odoo/owl"; +import { loadJS } from "@web/core/assets"; export class PieChart extends Component { static template = "awesome_dashboard.PieChart"; static props = { - 'data':{optional: false}, - 'size': {type: Number, optional: true} - } + data: { }, + size: { type: Number, optional: true }, + }; setup() { onWillStart(() => loadJS(["/web/static/lib/Chart/Chart.js"])); - this.ctx = useRef('pieChart') - this.chart = null - useEffect(() => { - if(this.chart) { - this.chart.destroy() + this.ctx = useRef("pieChart"); + this.chart = null; + onMounted(() => { + if (this.chart) { + this.chart.destroy(); } const dataset = { labels: Object.keys(this.props.data), - datasets: [{ - data: Object.values(this.props.data) - }] - } - this.chart = new Chart(this.ctx.el, {type: 'pie', data: dataset}) - }) + datasets: [ + { + data: Object.values(this.props.data), + }, + ], + }; + this.chart = new Chart(this.ctx.el, { type: "pie", data: dataset }); + }); } } diff --git a/awesome_dashboard/static/src/dashboard/pie_chart_card.js b/awesome_dashboard/static/src/dashboard/pie_chart_card.js index bcd85364c68..6f31edac3b8 100644 --- a/awesome_dashboard/static/src/dashboard/pie_chart_card.js +++ b/awesome_dashboard/static/src/dashboard/pie_chart_card.js @@ -1,15 +1,15 @@ import { Component, xml } from "@odoo/owl"; import { PieChart } from "./pie_chart/pie_chart"; -export class PieChartCard extends Component{ +export class PieChartCard extends Component { static components = { PieChart }; static props = { - title: [String], - value: [Object] - } + title: String, + value: Object, + }; static template = xml`

- ` + `; } diff --git a/awesome_dashboard/static/src/dashboard/services/awesome_dashboard.statistics.js b/awesome_dashboard/static/src/dashboard/services/awesome_dashboard.statistics.js index c775a11fe85..b08c57780bb 100644 --- a/awesome_dashboard/static/src/dashboard/services/awesome_dashboard.statistics.js +++ b/awesome_dashboard/static/src/dashboard/services/awesome_dashboard.statistics.js @@ -3,25 +3,25 @@ import { registry } from "@web/core/registry"; import { reactive } from "@odoo/owl"; export function loadStatistics() { - return rpc("/awesome_dashboard/statistics") + return rpc("/awesome_dashboard/statistics"); } export const awesomeDashboardStatisticsService = { start() { - let stats = reactive({}) + let stats = reactive({}); const getStats = async () => { - let newStats = await loadStatistics() - Object.assign(stats, newStats) - } + let newStats = await loadStatistics(); + Object.assign(stats, newStats); + }; - setInterval(getStats, 1000 * 60 * 10) - - getStats() + setInterval(getStats, 1000 * 60 * 10); - return stats - } -} + getStats(); + + return stats; + }, +}; -registry.category( - "services").add( - "awesome_dashboard.statistics", awesomeDashboardStatisticsService) +registry + .category("services") + .add("awesome_dashboard.statistics", awesomeDashboardStatisticsService); diff --git a/awesome_dashboard/static/src/dashboard_action.js b/awesome_dashboard/static/src/dashboard_action.js index 76d73df846d..9c3383e4fa7 100644 --- a/awesome_dashboard/static/src/dashboard_action.js +++ b/awesome_dashboard/static/src/dashboard_action.js @@ -1,12 +1,14 @@ -import { Component, xml } from "@odoo/owl" -import { registry } from "@web/core/registry" -import { LazyComponent } from "@web/core/assets" +import { Component, xml } from "@odoo/owl"; +import { registry } from "@web/core/registry"; +import { LazyComponent } from "@web/core/assets"; export class DashboardAction extends Component { - static components = { LazyComponent } + static components = { LazyComponent }; static template = xml` - ` + `; } -registry.category("actions").add("awesome_dashboard.dashboard", DashboardAction) +registry + .category("actions") + .add("awesome_dashboard.dashboard", DashboardAction); diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index a26e5851357..d72dcf72278 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -3,13 +3,13 @@ import { Component, useState } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card"; - static props = ['title', 'slots'] + static props = ["title", "slots"]; setup() { - this.state = useState({ hidden: false }) + this.state = useState({ hidden: false }); } - hide() { - this.state.hidden = !this.state.hidden + toggle_visibility() { + this.state.hidden = !this.state.hidden; } } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 7dab6e4543c..6c73a1f8cfc 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -6,7 +6,7 @@
- +
diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js index a7d3eeba563..45e207f947e 100644 --- a/awesome_owl/static/src/counter/counter.js +++ b/awesome_owl/static/src/counter/counter.js @@ -5,16 +5,17 @@ export class Counter extends Component { static props = { onChange: { type: Function, - optional: true} - } + optional: true, + }, + }; setup() { - this.state = useState({ value: 1 }) + this.state = useState({ value: 1 }); } increment() { this.state.value++; - if(this.props.onChange){ + if (this.props.onChange) { this.props.onChange(); } } diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 50394f3a639..e85ac00963b 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -7,14 +7,14 @@ import { TodoList } from "./todo/todo_list"; export class Playground extends Component { static template = "awesome_owl.playground"; - static components = { TodoList, Counter, Card } + static components = { TodoList, Counter, Card }; setup() { - this.state = useState({sum: 2}) + this.state = useState({ sum: 2 }); } incrementSum() { - this.state.sum++ + this.state.sum++; } card_body = markup(` @@ -23,4 +23,3 @@ export class Playground extends Component { `); } - diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 161cd3dce47..f76e19450b9 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -19,7 +19,7 @@

Sum:

- +
diff --git a/awesome_owl/static/src/todo/todo.js b/awesome_owl/static/src/todo/todo.js index 7c399383384..a72b343beef 100644 --- a/awesome_owl/static/src/todo/todo.js +++ b/awesome_owl/static/src/todo/todo.js @@ -1,9 +1,9 @@ export class Todo { - id - description - isCompleted + id; + description; + isCompleted; constructor(id, description, isCompleted) { - this.id = id + this.id = id; this.description = description; this.isCompleted = isCompleted; } diff --git a/awesome_owl/static/src/todo/todo_item.js b/awesome_owl/static/src/todo/todo_item.js index bb94a6f3efc..43684818c52 100644 --- a/awesome_owl/static/src/todo/todo_item.js +++ b/awesome_owl/static/src/todo/todo_item.js @@ -6,13 +6,13 @@ export class TodoItem extends Component { static template = "awesome_owl.todo_item"; static components = { Card }; - static props = { todo: { type: Todo }, onRemove: { type: Function } } + static props = { todo: { type: Todo }, onRemove: { type: Function } }; toggle() { this.props.todo.isCompleted = !this.props.todo.isCompleted; } remove() { - this.props.onRemove(this.props.todo.id) + this.props.onRemove(this.props.todo.id); } } diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js index 54c16a87647..2c90d8f8b6c 100644 --- a/awesome_owl/static/src/todo/todo_list.js +++ b/awesome_owl/static/src/todo/todo_list.js @@ -8,24 +8,24 @@ export class TodoList extends Component { static template = "awesome_owl.todo_list"; static components = { Card, TodoItem }; - ids = 0 - setup() { - this.state = useState({ todos: [], input: '' }) - useAutofocus('todo_input') + this.ids = 0; + this.state = useState({ todo_list: [], input: "" }); + useAutofocus("todo_input"); } keyup(event) { if (event.keyCode === 13) { - this.state.todos.push(new Todo(this.ids++, event.srcElement.value, false)) + this.state.todo_list.push( + new Todo(this.ids++, event.target.value, false), + ); } } remove(id) { - const index = this.state.todos.findIndex((elem) => elem.id === id) + const index = this.state.todo_list.findIndex((elem) => elem.id === id); if (index >= 0) { - this.state.todos.splice(index, 1) + this.state.todo_list.splice(index, 1); } } } - diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml index 5c739261e6a..4e26b5b5635 100644 --- a/awesome_owl/static/src/todo/todo_list.xml +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -2,9 +2,8 @@
-
Todos
- +
diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js index 5b16a111dda..5a1dd53ab45 100644 --- a/awesome_owl/static/src/utils.js +++ b/awesome_owl/static/src/utils.js @@ -1,8 +1,8 @@ -import { useRef, onMounted } from "@odoo/owl" +import { useRef, onMounted } from "@odoo/owl"; export function useAutofocus(name) { - let ref = useRef(name) + let ref = useRef(name); onMounted(() => { - ref.el.focus() - }) + ref.el.focus(); + }); } From 9a064207e01e8b693c1a0c381f66e3a30b92fdbd Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Thu, 25 Sep 2025 14:30:47 +0200 Subject: [PATCH 18/21] [IMP] awesome_dashboard: opening orders on chart click --- .../src/dashboard/pie_chart/pie_chart.js | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 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 e276550b05a..250700fe7bc 100644 --- a/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js +++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js @@ -1,17 +1,20 @@ import { Component, onWillStart, useRef, onMounted } from "@odoo/owl"; +import { _t } from "@web/core/l10n/translation"; import { loadJS } from "@web/core/assets"; +import { useService } from "@web/core/utils/hooks"; export class PieChart extends Component { static template = "awesome_dashboard.PieChart"; static props = { - data: { }, + data: {}, size: { type: Number, optional: true }, }; setup() { onWillStart(() => loadJS(["/web/static/lib/Chart/Chart.js"])); this.ctx = useRef("pieChart"); + this.action = useService("action"); this.chart = null; onMounted(() => { if (this.chart) { @@ -25,7 +28,39 @@ export class PieChart extends Component { }, ], }; - this.chart = new Chart(this.ctx.el, { type: "pie", data: dataset }); + this.chart = new Chart(this.ctx.el, { + type: "pie", + data: dataset, + options: { + onClick: (event) => { + const canvasPosition = this.chart.getElementsAtEventForMode( + event, + 'nearest', + { intersect: true }, + true + ); + const variant = Object.keys(this.props.data)[ + canvasPosition[0].index + ] + this.action.doAction({ + type: "ir.actions.act_window", + name: _t("Sales"), + res_model: "sale.order", + views: [ + [false, "list"], + [false, "form"], + ], + domain: [ + ['order_line.product_id.name', 'ilike', 'T-Shirt'], + ['order_line.product_id.product_template_attribute_value_ids.name', + 'ilike', + variant] + ] + }); + } + } + }); + }); } } From abe7d49c9767969b593b2151a16edc005da3ca5c Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Thu, 25 Sep 2025 14:57:56 +0200 Subject: [PATCH 19/21] [IMP] awesome_dashboard: make cards reactive on mobile --- awesome_dashboard/static/src/dashboard/dashboard.xml | 4 ++-- .../static/src/dashboard/dashboard_item.scss | 8 ++++++++ awesome_dashboard/static/src/dashboard/dashboard_item.xml | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index 18f1d0039ff..5bff8f6d5eb 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -2,7 +2,7 @@ - + @@ -10,7 +10,7 @@ -
+
-
+
From df6646a9adbe393acb98424a28b339d7f87feeb3 Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Thu, 25 Sep 2025 15:56:00 +0200 Subject: [PATCH 20/21] [IMP] awesome_dashboard: saving dashboard in config_properties --- .../src/dashboard/configuration_dialog.js | 10 +++++++-- .../static/src/dashboard/dashboard.js | 22 +++++++++---------- .../src/dashboard/pie_chart/pie_chart.js | 3 +++ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/configuration_dialog.js b/awesome_dashboard/static/src/dashboard/configuration_dialog.js index 71d3d9cfb34..0f22e3f29dd 100644 --- a/awesome_dashboard/static/src/dashboard/configuration_dialog.js +++ b/awesome_dashboard/static/src/dashboard/configuration_dialog.js @@ -1,3 +1,4 @@ +import { useService } from "@web/core/utils/hooks"; import { Component } from "@odoo/owl"; import { Dialog } from "@web/core/dialog/dialog"; import { CheckBox } from "@web/core/checkbox/checkbox"; @@ -12,6 +13,7 @@ export class ConfigurationDialog extends Component { }; setup() { + this.orm = useService("orm"); this.disabledElements = this.props.items .filter((item) => !item.enabled) .map((item) => item.element.id); @@ -26,8 +28,12 @@ export class ConfigurationDialog extends Component { this.disabledElements.splice(index, 1); } - apply() { - localStorage.setItem("disabledElements", this.disabledElements); + async apply() { + await this.orm.call( + "ir.config_parameter", + "set_param", + ["awesome_dashboard_config", JSON.stringify(this.disabledElements)] + ) this.props.onApply(); this.props.close(); } diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index a51baddb1d1..cf61281f0b0 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { _t } from "@web/core/l10n/translation"; -import { Component, useState } from "@odoo/owl"; +import { Component, useState, onWillStart } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; @@ -15,24 +15,24 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); + this.orm = useService("orm"); this.statistics = useService("awesome_dashboard.statistics"); this.state = useState({ items: [], stats: this.statistics }); this.dialog = useService("dialog"); - this.updateDashboard(); + + onWillStart(async () => await this.updateDashboard()) } - updateDashboard() { - const disabledElementsString = localStorage.getItem("disabledElements") || ""; - let disabledElementsList - if (disabledElementsString.includes(",")) { - disabledElementsList = disabledElementsString.split(","); - } else { - disabledElementsList = [disabledElementsString]; - } + async updateDashboard() { + const config = await this.orm.call( + "ir.config_parameter", + "get_param", + ["awesome_dashboard_config"]); + const disabledElements = JSON.parse(config) this.state.items = registry .category("awesome_dashboard") .getAll() - .filter((el) => !disabledElementsList.some((e) => e == el.id)); + .filter((el) => !disabledElements.some((e) => e == el.id)); } openCustomers() { 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 250700fe7bc..540924f1ae3 100644 --- a/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js +++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js @@ -39,6 +39,9 @@ export class PieChart extends Component { { intersect: true }, true ); + if (!canvasPosition[0]) { + return + } const variant = Object.keys(this.props.data)[ canvasPosition[0].index ] From f81a9cda18f1460507f78ac1d0e1597dca5c86cc Mon Sep 17 00:00:00 2001 From: Radu Macocian Date: Fri, 26 Sep 2025 11:58:44 +0200 Subject: [PATCH 21/21] [IMP] awesome_dashboard: adding a controller action for user settings --- awesome_dashboard/controllers/controllers.py | 12 ++++++++++++ .../src/dashboard/configuration_dialog.js | 11 ++++++----- .../static/src/dashboard/dashboard.js | 19 +++++++++++-------- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/awesome_dashboard/controllers/controllers.py b/awesome_dashboard/controllers/controllers.py index 56d4a051287..a3244383063 100644 --- a/awesome_dashboard/controllers/controllers.py +++ b/awesome_dashboard/controllers/controllers.py @@ -2,6 +2,7 @@ import logging import random +from typing import Required from odoo import http from odoo.http import request @@ -34,3 +35,14 @@ def get_statistics(self): 'total_amount': random.randint(100, 1000) } + @http.route('/awesome_dashboard/set_config/', type='json', auth='user') + def save_config(self, record_id, **kwargs): + request.env['ir.config_parameter'].sudo().set_param( + 'awesome_dashboard_config:' + str(record_id), kwargs['config'] + ) + + @http.route('/awesome_dashboard/get_config/', type='json', auth='user') + def get_config(self, record_id): + return request.env['ir.config_parameter'].sudo().get_param( + 'awesome_dashboard_config:' + str(record_id)) + diff --git a/awesome_dashboard/static/src/dashboard/configuration_dialog.js b/awesome_dashboard/static/src/dashboard/configuration_dialog.js index 0f22e3f29dd..f8cb2916550 100644 --- a/awesome_dashboard/static/src/dashboard/configuration_dialog.js +++ b/awesome_dashboard/static/src/dashboard/configuration_dialog.js @@ -2,6 +2,8 @@ import { useService } from "@web/core/utils/hooks"; import { Component } from "@odoo/owl"; import { Dialog } from "@web/core/dialog/dialog"; import { CheckBox } from "@web/core/checkbox/checkbox"; +import { session } from "@web/session"; +import { rpc } from "@web/core/network/rpc"; export class ConfigurationDialog extends Component { static template = "awesome_dashboard.ConfigurationDialog"; @@ -14,6 +16,7 @@ export class ConfigurationDialog extends Component { setup() { this.orm = useService("orm"); + this.userId = session.storeData['res.partner'][1].userId; this.disabledElements = this.props.items .filter((item) => !item.enabled) .map((item) => item.element.id); @@ -29,11 +32,9 @@ export class ConfigurationDialog extends Component { } async apply() { - await this.orm.call( - "ir.config_parameter", - "set_param", - ["awesome_dashboard_config", JSON.stringify(this.disabledElements)] - ) + await rpc("/awesome_dashboard/set_config/" + this.userId, { + config: JSON.stringify(this.disabledElements) + }) this.props.onApply(); this.props.close(); } diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index cf61281f0b0..c9f5ce51c0e 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -8,6 +8,8 @@ import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item"; import { PieChart } from "./pie_chart/pie_chart"; import { ConfigurationDialog } from "./configuration_dialog"; +import { rpc } from "@web/core/network/rpc"; +import { session } from "@web/session"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -16,19 +18,20 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); this.orm = useService("orm"); + this.userId = session.storeData['res.partner'][1].userId; this.statistics = useService("awesome_dashboard.statistics"); this.state = useState({ items: [], stats: this.statistics }); this.dialog = useService("dialog"); - onWillStart(async () => await this.updateDashboard()) + onWillStart(async () => { + await this.updateDashboard() + }) } async updateDashboard() { - const config = await this.orm.call( - "ir.config_parameter", - "get_param", - ["awesome_dashboard_config"]); - const disabledElements = JSON.parse(config) + const config = JSON.parse( + await rpc("/awesome_dashboard/get_config/" + this.userId)) + const disabledElements = config || [] this.state.items = registry .category("awesome_dashboard") .getAll() @@ -52,10 +55,10 @@ class AwesomeDashboard extends Component { } customizeDashboard() { - let all = registry.category("awesome_dashboard").getAll(); + const all_dashboard_items = registry.category("awesome_dashboard").getAll(); this.dialog.add(ConfigurationDialog, { - items: all.map(item => ({ + items: all_dashboard_items.map(item => ({ element: item, enabled: this.state.items.some((element) => item.id == element.id) }))