From 7f460d700ce29d1c3574cb26bb2eb4add362b9cb Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Mon, 22 Sep 2025 14:54:10 +0200 Subject: [PATCH 01/22] copy changes from other branch --- .gitignore | 3 ++ awesome_dashboard/__manifest__.py | 2 +- awesome_dashboard/static/src/dashboard.js | 4 +-- awesome_dashboard/static/src/dashboard.scss | 3 ++ awesome_dashboard/static/src/dashboard.xml | 4 ++- awesome_owl/__manifest__.py | 3 +- awesome_owl/static/src/card/card.js | 22 ++++++++++++ awesome_owl/static/src/card/card.xml | 11 ++++++ awesome_owl/static/src/counter/counter.js | 17 +++++++++ awesome_owl/static/src/counter/counter.xml | 7 ++++ awesome_owl/static/src/main.js | 3 +- awesome_owl/static/src/playground.js | 18 ++++++++-- awesome_owl/static/src/playground.xml | 13 +++++++ awesome_owl/static/src/todo_list/todo_item.js | 27 ++++++++++++++ .../static/src/todo_list/todo_item.xml | 10 ++++++ awesome_owl/static/src/todo_list/todo_list.js | 35 +++++++++++++++++++ .../static/src/todo_list/todo_list.xml | 11 ++++++ awesome_owl/static/src/utils.js | 8 +++++ 18 files changed, 191 insertions(+), 10 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard.scss 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_list/todo_item.js create mode 100644 awesome_owl/static/src/todo_list/todo_item.xml create mode 100644 awesome_owl/static/src/todo_list/todo_list.js create mode 100644 awesome_owl/static/src/todo_list/todo_list.xml create mode 100644 awesome_owl/static/src/utils.js diff --git a/.gitignore b/.gitignore index b6e47617de1..86809b7a5fe 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,6 @@ dmypy.json # Pyre type checker .pyre/ + +# vscode +.vscode/ diff --git a/awesome_dashboard/__manifest__.py b/awesome_dashboard/__manifest__.py index 31406e8addb..a1cd72893d7 100644 --- a/awesome_dashboard/__manifest__.py +++ b/awesome_dashboard/__manifest__.py @@ -12,7 +12,7 @@ 'author': "Odoo", 'website': "https://www.odoo.com/", - 'category': 'Tutorials/AwesomeDashboard', + 'category': 'Tutorials', 'version': '0.1', 'application': True, 'installable': True, diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 637fa4bb972..76e079e1a19 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,10 +1,10 @@ -/** @odoo-module **/ - import { Component } from "@odoo/owl"; import { registry } from "@web/core/registry"; +import { Layout } from "@web/core/layout"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; + static components = { Layout }; } 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..32862ec0d82 --- /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..f1cde9eba68 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -2,7 +2,9 @@ - hello dashboard + + hello dashboard + diff --git a/awesome_owl/__manifest__.py b/awesome_owl/__manifest__.py index 77abad510ef..e8ac1cda552 100644 --- a/awesome_owl/__manifest__.py +++ b/awesome_owl/__manifest__.py @@ -16,7 +16,7 @@ # Categories can be used to filter modules in modules listing # Check https://github.com/odoo/odoo/blob/15.0/odoo/addons/base/data/ir_module_category_data.xml # for the full list - 'category': 'Tutorials/AwesomeOwl', + 'category': 'Tutorials', 'version': '0.1', # any module necessary for this one to work correctly @@ -31,7 +31,6 @@ ('include', 'web._assets_helpers'), 'web/static/src/scss/pre_variables.scss', 'web/static/lib/bootstrap/scss/_variables.scss', - 'web/static/lib/bootstrap/scss/_maps.scss', ('include', 'web._assets_bootstrap'), ('include', 'web._assets_core'), 'web/static/src/libs/fontawesome/css/font-awesome.css', diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js new file mode 100644 index 00000000000..0764822d979 --- /dev/null +++ b/awesome_owl/static/src/card/card.js @@ -0,0 +1,22 @@ +import { Component, useState } from "@odoo/owl"; + +export class Card extends Component { + static template = "awesome_owl.Card"; + static props = { + title: String, + slots: { + type: Object, + shape: { + default: true, + }, + } + }; + + setup() { + this.state = useState({ isOpen: true }); + } + + toggle() { + this.state.isOpen = !this.state.isOpen; + } +} diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml new file mode 100644 index 00000000000..0ff5bc38288 --- /dev/null +++ b/awesome_owl/static/src/card/card.xml @@ -0,0 +1,11 @@ + + + +
+
+
+

+
+
+
+
diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js new file mode 100644 index 00000000000..320183af8be --- /dev/null +++ b/awesome_owl/static/src/counter/counter.js @@ -0,0 +1,17 @@ +import { Component, useState } from "@odoo/owl"; + +export class Counter extends Component { + static template = "awesome_owl.Counter"; + static props = { + onChange: {type: Function, required: false}, + }; + + setup() { + this.state = useState({ value: 0 }); + } + + increment() { + this.state.value++; + 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..257ad908916 --- /dev/null +++ b/awesome_owl/static/src/counter/counter.xml @@ -0,0 +1,7 @@ + + + +

Counter:

+ +
+
diff --git a/awesome_owl/static/src/main.js b/awesome_owl/static/src/main.js index 1af6c827e0b..1aaea902b55 100644 --- a/awesome_owl/static/src/main.js +++ b/awesome_owl/static/src/main.js @@ -4,8 +4,9 @@ import { Playground } from "./playground"; const config = { dev: true, - name: "Owl Tutorial", + name: "Owl Tutorial" }; // Mount the Playground component when the document.body is ready whenReady(() => mountComponent(Playground, document.body, config)); + diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 657fb8b07bb..08a73def040 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,7 +1,19 @@ -/** @odoo-module **/ - -import { Component } from "@odoo/owl"; +import { Component, markup, useState } from "@odoo/owl"; +import { Card } from "./card/card"; +import { Counter } from "./counter/counter"; +import { TodoList } from "./todo_list/todo_list"; export class Playground extends Component { static template = "awesome_owl.playground"; + static components = { Card, Counter, TodoList }; + content1 = '
some content
'; + content2 = markup`
some content
`; + + setup() { + this.state = useState({ sum: 0 }); + } + + incrementSum() { + this.state.sum++; + } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 4fb905d59f9..b4d578a07b8 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -4,7 +4,20 @@
hello world + + + + card content + + +
other card content
+
+ + + + The sum is:
+
diff --git a/awesome_owl/static/src/todo_list/todo_item.js b/awesome_owl/static/src/todo_list/todo_item.js new file mode 100644 index 00000000000..b1b89f671ea --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_item.js @@ -0,0 +1,27 @@ +import { Component } from "@odoo/owl"; + +export class TodoItem extends Component { + static template = "awesome_owl.TodoItem"; + static props = { + todo: { + type: Object, + shape: { + id: Number, + description: String, + isCompleted: Boolean, + }, + }, + toggleState: Function, + delete: Function, + }; + + onChange() { + if (this.props.toggleState) { + this.props.toggleState(this.props.todo.id); + } + } + + onDelete() { + this.props.delete(this.props.todo.id); + } +} diff --git a/awesome_owl/static/src/todo_list/todo_item.xml b/awesome_owl/static/src/todo_list/todo_item.xml new file mode 100644 index 00000000000..61029cbf4e0 --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_item.xml @@ -0,0 +1,10 @@ + + + +

+ + . + x +

+
+
diff --git a/awesome_owl/static/src/todo_list/todo_list.js b/awesome_owl/static/src/todo_list/todo_list.js new file mode 100644 index 00000000000..a22aece9588 --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_list.js @@ -0,0 +1,35 @@ +import { Component, useState } from "@odoo/owl"; +import { TodoItem } from "./todo_item"; +import { useAutofocus } from "../utils"; + +export class TodoList extends Component { + static template = "awesome_owl.TodoList"; + static components = { TodoItem }; + + setup() { + this.todos = useState([]); + this.nextId = useState({value: 0}); + useAutofocus("input"); + } + + addTodo(ev) { + if (ev.keyCode === 13 && ev.target.value) { + this.todos.push({ id: this.nextId.value++, description: ev.target.value, isCompleted: false }); + ev.target.value = ""; + } + } + + toggleState(id) { + const index = this.todos.findIndex(todo => todo.id === id); + if (index !== -1) { + this.todos[index].isCompleted = !this.todos[index].isCompleted; + } + } + + delete(id) { + const index = this.todos.findIndex(todo => todo.id === id); + if (index !== -1) { + this.todos.splice(index, 1); + } + } +} diff --git a/awesome_owl/static/src/todo_list/todo_list.xml b/awesome_owl/static/src/todo_list/todo_list.xml new file mode 100644 index 00000000000..c13197d0117 --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_list.xml @@ -0,0 +1,11 @@ + + + +
+ + + + +
+
+
diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js new file mode 100644 index 00000000000..3c01262eb68 --- /dev/null +++ b/awesome_owl/static/src/utils.js @@ -0,0 +1,8 @@ +import { onMounted, useRef } from "@odoo/owl"; + +export function useAutofocus(refName) { + const ref = useRef(refName); + onMounted(() => { + ref.el.focus(); + }); +} From 981e046ea56cc261d1292a0686e80d9fbb3422d8 Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Mon, 22 Sep 2025 15:44:18 +0200 Subject: [PATCH 02/22] [FIX] awesome_owl: fix manifest --- awesome_owl/__manifest__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/awesome_owl/__manifest__.py b/awesome_owl/__manifest__.py index e8ac1cda552..50e22de4d15 100644 --- a/awesome_owl/__manifest__.py +++ b/awesome_owl/__manifest__.py @@ -31,6 +31,7 @@ ('include', 'web._assets_helpers'), 'web/static/src/scss/pre_variables.scss', 'web/static/lib/bootstrap/scss/_variables.scss', + 'web/static/lib/bootstrap/scss/_maps.scss', ('include', 'web._assets_bootstrap'), ('include', 'web._assets_core'), 'web/static/src/libs/fontawesome/css/font-awesome.css', From 465f1361bca92b0ea32fadb9f4cde83770f40122 Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Tue, 23 Sep 2025 12:25:10 +0200 Subject: [PATCH 03/22] [ADD] awesome_dashboard: dashboard-item --- .../src/dashboard-item/dashboard-item.js | 20 +++++++++++++ .../src/dashboard-item/dashboard-item.scss | 5 ++++ .../src/dashboard-item/dashboard-item.xml | 9 ++++++ awesome_dashboard/static/src/dashboard.js | 29 +++++++++++++++++-- awesome_dashboard/static/src/dashboard.xml | 9 +++++- 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard-item/dashboard-item.js create mode 100644 awesome_dashboard/static/src/dashboard-item/dashboard-item.scss create mode 100644 awesome_dashboard/static/src/dashboard-item/dashboard-item.xml 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..9f2106a3934 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard-item/dashboard-item.js @@ -0,0 +1,20 @@ +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.scss b/awesome_dashboard/static/src/dashboard-item/dashboard-item.scss new file mode 100644 index 00000000000..dba714d3a38 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard-item/dashboard-item.scss @@ -0,0 +1,5 @@ +.dashboard-item { + background-color: white; + display: inline-block; + margin: 1rem; +} 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..50d89a029ee --- /dev/null +++ b/awesome_dashboard/static/src/dashboard-item/dashboard-item.xml @@ -0,0 +1,9 @@ + + + + +
+ +
+
+
diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 76e079e1a19..19411761d62 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,10 +1,35 @@ import { Component } from "@odoo/owl"; +import { rpc } from "@web/core/network/rpc"; import { registry } from "@web/core/registry"; -import { Layout } from "@web/core/layout"; +import { useService, useState } from "@web/core/utils/hooks"; +import { Layout } from "@web/search/layout"; +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"); + this.state = useState({ statistics: {} }); + onWillStart(async () => { + this.state.statistics = await rpc('/awesome_dashboard/statistics'); + }); + } + + openCustomers() { + this.action.doAction("base.action_partner_form"); + } + + openLeads() { + this.action.doAction({ + type: 'ir.actions.act_window', + name: "Leads", + target: 'current', + res_model: 'crm.lead', + views: [[false, 'form'], [false, 'list']], + }); + } } 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 f1cde9eba68..46c3a2c8aeb 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -3,7 +3,14 @@ - hello dashboard + + + + + + some content + I love milk + some content From d74534d79388aaf9f8dc42be8c83a6b6852dc5ce Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Tue, 23 Sep 2025 17:03:48 +0200 Subject: [PATCH 04/22] [ADD] awesome_dashboard: statistics in dashboard --- .../src/dashboard-item/dashboard-item.scss | 2 ++ awesome_dashboard/static/src/dashboard.js | 4 ++-- awesome_dashboard/static/src/dashboard.scss | 11 +++++++++ awesome_dashboard/static/src/dashboard.xml | 24 +++++++++++++++---- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard-item/dashboard-item.scss b/awesome_dashboard/static/src/dashboard-item/dashboard-item.scss index dba714d3a38..ac0ba69ba42 100644 --- a/awesome_dashboard/static/src/dashboard-item/dashboard-item.scss +++ b/awesome_dashboard/static/src/dashboard-item/dashboard-item.scss @@ -2,4 +2,6 @@ background-color: white; display: inline-block; margin: 1rem; + padding: 1rem; + text-align: center; } diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 19411761d62..a7ca38a274b 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,7 +1,7 @@ -import { Component } from "@odoo/owl"; +import { Component, useState, onWillStart } from "@odoo/owl"; import { rpc } from "@web/core/network/rpc"; import { registry } from "@web/core/registry"; -import { useService, useState } from "@web/core/utils/hooks"; +import { useService } from "@web/core/utils/hooks"; import { Layout } from "@web/search/layout"; import { DashboardItem } from "./dashboard-item/dashboard-item"; diff --git a/awesome_dashboard/static/src/dashboard.scss b/awesome_dashboard/static/src/dashboard.scss index 32862ec0d82..7cc7f864c93 100644 --- a/awesome_dashboard/static/src/dashboard.scss +++ b/awesome_dashboard/static/src/dashboard.scss @@ -1,3 +1,14 @@ .o_dashboard { background-color: gray; } + +.stats-name { + font-size: medium; + color: black; +} + +.stats-number { + font-size: larger; + font-weight: bold; + color: green; +} diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 46c3a2c8aeb..2415040cce5 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -6,11 +6,27 @@ - - 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

+

+
From dabc8669124b0699d7b4a962bb785e5df87fc9ee Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Wed, 24 Sep 2025 09:10:48 +0200 Subject: [PATCH 05/22] [FIX] awesome_dashboard: file naming convention --- awesome_dashboard/static/src/dashboard.js | 2 +- .../dashboard-item.js => dashboard_item/dashboard_item.js} | 0 .../dashboard-item.scss => dashboard_item/dashboard_item.scss} | 0 .../dashboard-item.xml => dashboard_item/dashboard_item.xml} | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename awesome_dashboard/static/src/{dashboard-item/dashboard-item.js => dashboard_item/dashboard_item.js} (100%) rename awesome_dashboard/static/src/{dashboard-item/dashboard-item.scss => dashboard_item/dashboard_item.scss} (100%) rename awesome_dashboard/static/src/{dashboard-item/dashboard-item.xml => dashboard_item/dashboard_item.xml} (100%) diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index a7ca38a274b..7860c40e277 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -3,7 +3,7 @@ import { rpc } from "@web/core/network/rpc"; import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; import { Layout } from "@web/search/layout"; -import { DashboardItem } from "./dashboard-item/dashboard-item"; +import { DashboardItem } from "./dashboard_item/dashboard_item"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; diff --git a/awesome_dashboard/static/src/dashboard-item/dashboard-item.js b/awesome_dashboard/static/src/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_item/dashboard_item.js diff --git a/awesome_dashboard/static/src/dashboard-item/dashboard-item.scss b/awesome_dashboard/static/src/dashboard_item/dashboard_item.scss similarity index 100% rename from awesome_dashboard/static/src/dashboard-item/dashboard-item.scss rename to awesome_dashboard/static/src/dashboard_item/dashboard_item.scss diff --git a/awesome_dashboard/static/src/dashboard-item/dashboard-item.xml b/awesome_dashboard/static/src/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_item/dashboard_item.xml From b6826af0311939f55f2c85c037911ec3dd488ad0 Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Wed, 24 Sep 2025 09:20:11 +0200 Subject: [PATCH 06/22] [ADD] awesome_dashboard: statistics service --- awesome_dashboard/static/src/dashboard.js | 4 ++-- .../static/src/statistics_service.js | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 awesome_dashboard/static/src/statistics_service.js diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 7860c40e277..8d47965ae45 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,5 +1,4 @@ import { Component, useState, onWillStart } from "@odoo/owl"; -import { rpc } from "@web/core/network/rpc"; import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; import { Layout } from "@web/search/layout"; @@ -11,9 +10,10 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); + this.statisticsService = useService("statistics"); this.state = useState({ statistics: {} }); onWillStart(async () => { - this.state.statistics = await rpc('/awesome_dashboard/statistics'); + this.state.statistics = await this.statisticsService.loadStatistics(); }); } diff --git a/awesome_dashboard/static/src/statistics_service.js b/awesome_dashboard/static/src/statistics_service.js new file mode 100644 index 00000000000..bf926f76f1a --- /dev/null +++ b/awesome_dashboard/static/src/statistics_service.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 async function loadStatistics() { + return await rpc('/awesome_dashboard/statistics'); +} + +export const statisticsService = { + start() { + return { + loadStatistics: memoize(loadStatistics), + } + }, +} + +registry.category("services").add("statistics", statisticsService); From 74e79a857ef754762e801be7a2c8d2d55842968d Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Wed, 24 Sep 2025 10:27:07 +0200 Subject: [PATCH 07/22] [ADD] awesome_dashboard: shirt orders by size pie chart --- awesome_dashboard/static/src/dashboard.js | 3 +- awesome_dashboard/static/src/dashboard.xml | 4 ++ .../static/src/pie_chart/pie_chart.js | 51 +++++++++++++++++++ .../static/src/pie_chart/pie_chart.xml | 7 +++ 4 files changed, 64 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 8d47965ae45..1ccc71b73b5 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 { useService } from "@web/core/utils/hooks"; import { Layout } from "@web/search/layout"; 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 2415040cce5..5d65a3146af 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -27,6 +27,10 @@

Total amount of new 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..5a3d14dc119 --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.js @@ -0,0 +1,51 @@ +import { Component, onWillStart, onMounted, onWillUnmount, useEffect, useRef } from "@odoo/owl"; +import { loadJS } from "@web/core/assets"; + +export class PieChart extends Component { + static template = 'awesome_dashboard.PieChart'; + static props = { + data: Object, + }; + + setup() { + const canvasRef = useRef('canvas'); + + onWillStart(async () => { + await loadJS('/web/static/lib/Chart/Chart.js'); + }); + + onMounted(() => { + const canvas = canvasRef.el; + const ctx = canvas.getContext('2d'); + this.chart = new Chart(ctx, { + type: 'pie', + data: { + labels: Object.keys(this.props.data), + datasets: [ + { + data: Object.values(this.props.data), + }, + ], + }, + options: {}, + }); + this.chart.update(); + }); + + useEffect( + data => { + this.chart.data.labels = Object.keys(data); + this.chart.data.datasets[0].data = Object.values(data); + this.chart.update(); + }, + () => [this.props.data], + ); + + onWillUnmount(() => { + console.log("will unmount"); + if (this.chart) { + this.chart.destroy(); + } + }); + } +} 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..8b1d661047c --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.xml @@ -0,0 +1,7 @@ + + + + + + + From eab21f4aaab69dca5387b4e5554ccc7633c46610 Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Wed, 24 Sep 2025 11:15:07 +0200 Subject: [PATCH 08/22] [ADD] awesome_dashboard: periodically update statistics --- awesome_dashboard/static/src/dashboard.js | 7 ++----- awesome_dashboard/static/src/statistics_service.js | 13 ++++++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 1ccc71b73b5..860bc991bee 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,4 +1,4 @@ -import { Component, useState, onWillStart } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; import { Layout } from "@web/search/layout"; @@ -12,10 +12,7 @@ class AwesomeDashboard extends Component { setup() { this.action = useService("action"); this.statisticsService = useService("statistics"); - this.state = useState({ statistics: {} }); - onWillStart(async () => { - this.state.statistics = await this.statisticsService.loadStatistics(); - }); + this.state = useState(this.statisticsService); } openCustomers() { diff --git a/awesome_dashboard/static/src/statistics_service.js b/awesome_dashboard/static/src/statistics_service.js index bf926f76f1a..a7ec665582f 100644 --- a/awesome_dashboard/static/src/statistics_service.js +++ b/awesome_dashboard/static/src/statistics_service.js @@ -1,17 +1,20 @@ +import { reactive } from "@odoo/owl"; import { rpc } from "@web/core/network/rpc"; import { registry } from "@web/core/registry"; -import { memoize } from "@web/core/utils/functions"; export async function loadStatistics() { return await rpc('/awesome_dashboard/statistics'); } export const statisticsService = { - start() { - return { - loadStatistics: memoize(loadStatistics), - } + async start() { + const statisticsBox = reactive({statistics: await loadStatistics()}); + setInterval(async () => { + statisticsBox.statistics = await loadStatistics(); + }, 10 * 60 * 1000); + return statisticsBox; }, + } registry.category("services").add("statistics", statisticsService); From 22c573bc9310ae2036ec86d5cf5c0ddecdb37ce9 Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Wed, 24 Sep 2025 11:39:45 +0200 Subject: [PATCH 09/22] [ADD] awesome_dashboard: lazy load dashboard --- awesome_dashboard/__manifest__.py | 7 ++++++- .../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.scss | 0 .../dashboard_item/dashboard_item.xml | 0 .../src/{ => dashboard}/pie_chart/pie_chart.js | 0 .../src/{ => dashboard}/pie_chart/pie_chart.xml | 0 awesome_dashboard/static/src/dashboard_action.js | 12 ++++++++++++ 10 files changed, 19 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.scss (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%) create mode 100644 awesome_dashboard/static/src/dashboard_action.js diff --git a/awesome_dashboard/__manifest__.py b/awesome_dashboard/__manifest__.py index a1cd72893d7..18331002cc7 100644 --- a/awesome_dashboard/__manifest__.py +++ b/awesome_dashboard/__manifest__.py @@ -22,8 +22,13 @@ 'views/views.xml', ], 'assets': { + 'awesome_dashboard.dashboard': [ + 'awesome_dashboard/static/src/dashboard/*', + 'awesome_dashboard/static/src/dashboard/**/*', + ], 'web.assets_backend': [ - 'awesome_dashboard/static/src/**/*', + 'awesome_dashboard/static/src/dashboard_action.js', + 'awesome_dashboard/static/src/statistics_service.js', ], }, '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 860bc991bee..13939ec6298 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -30,4 +30,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.scss b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.scss similarity index 100% rename from awesome_dashboard/static/src/dashboard_item/dashboard_item.scss rename to awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.scss 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/dashboard_action.js b/awesome_dashboard/static/src/dashboard_action.js new file mode 100644 index 00000000000..dced3df087f --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_action.js @@ -0,0 +1,12 @@ +import { Component, xml } from "@odoo/owl"; +import { LazyComponent } from "@web/core/assets"; +import { registry } from "@web/core/registry"; + +export class AwesomeDashboardLoader extends Component { + static components = { LazyComponent }; + static template = xml` + + `; +} + +registry.category('actions').add('awesome_dashboard.dashboard', AwesomeDashboardLoader); From 662c8da32685ee02c470ec6c2b4c2ce4fe962cd3 Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Wed, 24 Sep 2025 12:42:58 +0200 Subject: [PATCH 10/22] [ADD] awesome_dashboard: generic dashboard --- .../static/src/dashboard/dashboard.js | 7 ++- .../static/src/dashboard/dashboard.xml | 31 +++------- .../static/src/dashboard/dashboard_items.js | 60 +++++++++++++++++++ .../src/dashboard/number_card/number_card.js | 9 +++ .../dashboard/number_card/number_card.scss | 0 .../src/dashboard/number_card/number_card.xml | 8 +++ .../pie_chart_card/pie_chart_card.js | 11 ++++ .../pie_chart_card/pie_chart_card.scss | 0 .../pie_chart_card/pie_chart_card.xml | 8 +++ 9 files changed, 108 insertions(+), 26 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.scss 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.scss 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 13939ec6298..6344ac10e18 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -3,16 +3,19 @@ import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; import { Layout } from "@web/search/layout"; import { DashboardItem } from "./dashboard_item/dashboard_item"; -import { PieChart } from "./pie_chart/pie_chart"; +import { items } from "./dashboard_items"; +import { NumberCard } from "./number_card/number_card"; +import { PieChartCard } from "./pie_chart_card/pie_chart_card"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; - static components = { Layout, DashboardItem, PieChart }; + static components = { Layout, DashboardItem, NumberCard, PieChartCard }; setup() { this.action = useService("action"); this.statisticsService = useService("statistics"); this.state = useState(this.statisticsService); + this.items = items; } openCustomers() { diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index 5d65a3146af..b6c62236fef 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -7,30 +7,13 @@ - -

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

-

-
- -

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..ac98380eee2 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -0,0 +1,60 @@ +import { NumberCard } from "./number_card/number_card"; +import { PieChartCard } from "./pie_chart_card/pie_chart_card"; + +export const items = [ + { + id: 'average_quantity', + description: "Average amount of t-shirt", + Component: NumberCard, + 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, + 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, + 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, + 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, + props: data => ({ + title: "Total amount of new orders this month", + value: data.total_amount, + }), + }, + { + id: 'orders_by_size', + description: "Orders by size", + Component: PieChartCard, + props: data => ({ + title: "Shirt orders by size", + value: 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..79384da6fce --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/number_card/number_card.js @@ -0,0 +1,9 @@ +import { Component } from "@odoo/owl"; + +export class NumberCard extends Component { + static template = 'awesome_dashboard.NumberCard'; + static props = { + title: String, + value: Number, + }; +} diff --git a/awesome_dashboard/static/src/dashboard/number_card/number_card.scss b/awesome_dashboard/static/src/dashboard/number_card/number_card.scss new file mode 100644 index 00000000000..e69de29bb2d 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..6b0aa98c379 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/number_card/number_card.xml @@ -0,0 +1,8 @@ + + + + +

+

+
+
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..bfa6d20619d --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.js @@ -0,0 +1,11 @@ +import { Component } from "@odoo/owl"; +import { PieChart } from "../pie_chart/pie_chart"; + +export class PieChartCard extends Component { + static template = 'awesome_dashboard.PieChartCard'; + static props = { + title: String, + value: Object, + }; + static components = { PieChart }; +} diff --git a/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.scss b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.scss new file mode 100644 index 00000000000..e69de29bb2d 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..b7ffed3da0e --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.xml @@ -0,0 +1,8 @@ + + + + +

+ +
+
From f7418919317204a9991a92b4ed7b51806a9f3bea Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Wed, 24 Sep 2025 12:58:50 +0200 Subject: [PATCH 11/22] [ADD] awesome_dashboard: dashboard item registry --- awesome_dashboard/static/src/dashboard/dashboard.js | 4 ++-- awesome_dashboard/static/src/dashboard/dashboard_items.js | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index 6344ac10e18..a2a07addf50 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -3,9 +3,9 @@ import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; import { Layout } from "@web/search/layout"; import { DashboardItem } from "./dashboard_item/dashboard_item"; -import { items } from "./dashboard_items"; import { NumberCard } from "./number_card/number_card"; import { PieChartCard } from "./pie_chart_card/pie_chart_card"; +import { dashboardItemRegistry } from "./dashboard_items"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; @@ -15,7 +15,7 @@ class AwesomeDashboard extends Component { this.action = useService("action"); this.statisticsService = useService("statistics"); this.state = useState(this.statisticsService); - this.items = items; + this.items = dashboardItemRegistry.getAll(); } openCustomers() { diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items.js b/awesome_dashboard/static/src/dashboard/dashboard_items.js index ac98380eee2..7bfa67ba024 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_items.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -1,6 +1,9 @@ +import { registry } from "@web/core/registry"; import { NumberCard } from "./number_card/number_card"; import { PieChartCard } from "./pie_chart_card/pie_chart_card"; +export const dashboardItemRegistry = registry.category("dashboard_items"); + export const items = [ { id: 'average_quantity', @@ -58,3 +61,7 @@ export const items = [ }), }, ]; + +for (const item of items) { + dashboardItemRegistry.add(item.id, item); +} From dd9cf1cb96b5bda07a50e32bc9cdaa2b7a618bc0 Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Thu, 25 Sep 2025 10:34:19 +0200 Subject: [PATCH 12/22] [ADD] awesome_dashboard: settings to include/exclude dashboard items --- .../static/src/dashboard/dashboard.js | 41 +++++++++++++-- .../static/src/dashboard/dashboard.xml | 3 +- .../static/src/dashboard/dashboard_items.js | 2 + .../dashboard_items_dialog.js | 50 +++++++++++++++++++ .../dashboard_items_dialog.xml | 20 ++++++++ 5 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.js create mode 100644 awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.xml diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index a2a07addf50..c52b731e36c 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -1,21 +1,38 @@ -import { Component, useState } from "@odoo/owl"; +import { Component, reactive, useState } from "@odoo/owl"; import { registry } from "@web/core/registry"; -import { useService } from "@web/core/utils/hooks"; +import { useBus, useService } from "@web/core/utils/hooks"; import { Layout } from "@web/search/layout"; import { DashboardItem } from "./dashboard_item/dashboard_item"; import { NumberCard } from "./number_card/number_card"; import { PieChartCard } from "./pie_chart_card/pie_chart_card"; -import { dashboardItemRegistry } from "./dashboard_items"; +import { DashboardItemsDialog } from "./dashboard_items_dialog/dashboard_items_dialog"; + +const EXCLUDED_DASHBOARD_ITEMS_LS_KEY = 'excluded_dashboard_items'; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; - static components = { Layout, DashboardItem, NumberCard, PieChartCard }; + static components = { Layout, DashboardItem, DashboardItemsDialog, NumberCard, PieChartCard }; setup() { this.action = useService("action"); + this.dialog = useService("dialog"); + this.statisticsService = useService("statistics"); this.state = useState(this.statisticsService); - this.items = dashboardItemRegistry.getAll(); + + this.items = registry.category('dashboard_items').getAll(); + useBus(registry.category('dashboard_items'), 'UPDATE', this.handleDashboardItemsUpdate.bind(this)); + + const initExcludedItems = JSON.parse(localStorage.getItem(EXCLUDED_DASHBOARD_ITEMS_LS_KEY)) ?? []; + const storedStateObj = { excludedItems: initExcludedItems }; + const store = obj => localStorage.setItem(EXCLUDED_DASHBOARD_ITEMS_LS_KEY, JSON.stringify(obj.excludedItems)); + const reactiveStoredState = reactive(storedStateObj, () => store(reactiveStoredState)); + store(reactiveStoredState); + this.storedState = useState(storedStateObj); + } + + handleDashboardItemsUpdate(event) { + this.items = registry.category('dashboard_item').getAll(); } openCustomers() { @@ -31,6 +48,20 @@ class AwesomeDashboard extends Component { views: [[false, 'form'], [false, 'list']], }); } + + handleDashboardItemsConfigChange(excludedItems) { + // localStorage.setItem(EXCLUDED_DASHBOARD_ITEMS_LS_KEY, JSON.stringify(excludedItems)); + this.storedState.excludedItems = excludedItems; + } + + openSettings() { + console.log("open settings") + this.removeSettingsDialog = this.dialog.add(DashboardItemsDialog, { + items: this.items, + excludedItems: this.storedState.excludedItems, + onApply: this.handleDashboardItemsConfigChange.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 b6c62236fef..1d0065392e5 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -6,10 +6,11 @@ + - + diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items.js b/awesome_dashboard/static/src/dashboard/dashboard_items.js index 7bfa67ba024..af4b03817e3 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_items.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -62,6 +62,8 @@ export const items = [ }, ]; +console.log('dashboard_items'); + for (const item of items) { dashboardItemRegistry.add(item.id, item); } diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.js b/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.js new file mode 100644 index 00000000000..6e61e38c9f9 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.js @@ -0,0 +1,50 @@ +import { Component, useState } from "@odoo/owl"; +import { Dialog } from "@web/core/dialog/dialog"; + +export class DashboardItemsDialog extends Component { + static template = 'awesome_dashboard.DashboardItemsDialog'; + static components = { Dialog }; + static props = { + items: { + type: Array, + element: { + type: Object, + // shape: { + // id: String, + // description: String, + // }, + }, + }, + excludedItems: { + type: Array, + element: String, + }, + close: Function, + onApply: Function, + }; + + setup() { + console.log("setup dialog"); + this.state = useState( + this.props.items.map( + item => ({ + ...item, + checked: !this.props.excludedItems.includes(item.id), + }), + ), + ); + } + + toggle(event) { + const index = this.state.findIndex(item => item.id === event.target.name); + if (index !== -1) { + this.state[index].checked = !this.state[index].checked; + } + } + + apply() { + const newExcludedItems = this.state.filter(item => !item.checked).map(item => item.id); + this.props.onApply(newExcludedItems); + this.props.close(); + } +} diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.xml b/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.xml new file mode 100644 index 00000000000..22f55b392d1 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.xml @@ -0,0 +1,20 @@ + + + + + + +

Dashboard items configuration

+ +
+

Which cards do you wish to see?

+

+ + +

+ + + +
+
+
From 6c5926d55587ab728f9db6a619ea03680cd1ac0a Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Mon, 29 Sep 2025 11:45:41 +0200 Subject: [PATCH 13/22] [CLN] awesome_dashboard: clean up logs --- awesome_dashboard/static/src/dashboard/dashboard.js | 2 -- awesome_dashboard/static/src/dashboard/dashboard_items.js | 2 -- .../dashboard/dashboard_items_dialog/dashboard_items_dialog.js | 1 - awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js | 1 - 4 files changed, 6 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index c52b731e36c..f1060e26e61 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -50,12 +50,10 @@ class AwesomeDashboard extends Component { } handleDashboardItemsConfigChange(excludedItems) { - // localStorage.setItem(EXCLUDED_DASHBOARD_ITEMS_LS_KEY, JSON.stringify(excludedItems)); this.storedState.excludedItems = excludedItems; } openSettings() { - console.log("open settings") this.removeSettingsDialog = this.dialog.add(DashboardItemsDialog, { items: this.items, excludedItems: this.storedState.excludedItems, diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items.js b/awesome_dashboard/static/src/dashboard/dashboard_items.js index af4b03817e3..7bfa67ba024 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_items.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -62,8 +62,6 @@ export const items = [ }, ]; -console.log('dashboard_items'); - for (const item of items) { dashboardItemRegistry.add(item.id, item); } diff --git a/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.js b/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.js index 6e61e38c9f9..1fb5d9155da 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_items_dialog/dashboard_items_dialog.js @@ -24,7 +24,6 @@ export class DashboardItemsDialog extends Component { }; setup() { - console.log("setup dialog"); this.state = useState( this.props.items.map( item => ({ 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 5a3d14dc119..8780448e298 100644 --- a/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js +++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js @@ -42,7 +42,6 @@ export class PieChart extends Component { ); onWillUnmount(() => { - console.log("will unmount"); if (this.chart) { this.chart.destroy(); } From 2227ad4f77d87879ed58be0237e9a4b5330b3ae8 Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Mon, 29 Sep 2025 11:51:16 +0200 Subject: [PATCH 14/22] [CLN] awesome_owl: restore comma --- awesome_owl/static/src/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awesome_owl/static/src/main.js b/awesome_owl/static/src/main.js index 1aaea902b55..f495b89f124 100644 --- a/awesome_owl/static/src/main.js +++ b/awesome_owl/static/src/main.js @@ -4,7 +4,7 @@ import { Playground } from "./playground"; const config = { dev: true, - name: "Owl Tutorial" + name: "Owl Tutorial", }; // Mount the Playground component when the document.body is ready From d4b7c1f6dcc14bb82f12d0f77c2d9cf6b3ec2a57 Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Mon, 29 Sep 2025 13:17:38 +0200 Subject: [PATCH 15/22] [FIX] awesome_owl: required: false -> optional: true --- awesome_owl/static/src/counter/counter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js index 320183af8be..c33f218a965 100644 --- a/awesome_owl/static/src/counter/counter.js +++ b/awesome_owl/static/src/counter/counter.js @@ -3,7 +3,7 @@ import { Component, useState } from "@odoo/owl"; export class Counter extends Component { static template = "awesome_owl.Counter"; static props = { - onChange: {type: Function, required: false}, + onChange: {type: Function, optional: true}, }; setup() { From 72155fa8e45c775d89af8709542c8d3e08fced0f Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Mon, 29 Sep 2025 14:28:12 +0200 Subject: [PATCH 16/22] [CLN] awesome_owl: use ?. instead of if condition call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cemal Faruk Güney <63407686+cgun-odoo@users.noreply.github.com> --- awesome_owl/static/src/todo_list/todo_item.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/awesome_owl/static/src/todo_list/todo_item.js b/awesome_owl/static/src/todo_list/todo_item.js index b1b89f671ea..ac4d21de10c 100644 --- a/awesome_owl/static/src/todo_list/todo_item.js +++ b/awesome_owl/static/src/todo_list/todo_item.js @@ -16,9 +16,7 @@ export class TodoItem extends Component { }; onChange() { - if (this.props.toggleState) { - this.props.toggleState(this.props.todo.id); - } + this.props.toggleState?.(this.props.todo.id); } onDelete() { From 3c9dd0b953ec66164b544e4e2b9b628bc6b6f3db Mon Sep 17 00:00:00 2001 From: Avery Pinko Date: Mon, 29 Sep 2025 14:29:11 +0200 Subject: [PATCH 17/22] [CLN] awesome_dashboard: self-closing +