From 52a820abb452e06a6d5f2668dcdf31ae2c94e81b Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Fri, 24 Oct 2025 13:47:14 +0200 Subject: [PATCH 01/15] [ADD] awesome_owl: 1.2 counter --- awesome_owl/static/src/counter/counter.js | 10 ++++++++++ awesome_owl/static/src/counter/counter.xml | 9 +++++++++ awesome_owl/static/src/playground.js | 2 ++ awesome_owl/static/src/playground.xml | 5 ++--- 4 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 awesome_owl/static/src/counter/counter.js create mode 100644 awesome_owl/static/src/counter/counter.xml diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js new file mode 100644 index 00000000000..000158b1dd2 --- /dev/null +++ b/awesome_owl/static/src/counter/counter.js @@ -0,0 +1,10 @@ +import {Component, useState} from "@odoo/owl"; + +export class Counter extends Component { + static template = "awesome_owl.counter" + state = useState({value: 0}) + + increment() { + this.state.value++; + } +} \ No newline at end of file diff --git a/awesome_owl/static/src/counter/counter.xml b/awesome_owl/static/src/counter/counter.xml new file mode 100644 index 00000000000..df9776e146d --- /dev/null +++ b/awesome_owl/static/src/counter/counter.xml @@ -0,0 +1,9 @@ + + + +
+

Counter:

+ +
+
+
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 657fb8b07bb..593c9c7669d 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,7 +1,9 @@ /** @odoo-module **/ import { Component } from "@odoo/owl"; +import { Counter } from "./counter/counter"; export class Playground extends Component { static template = "awesome_owl.playground"; + static components = { Counter } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 4fb905d59f9..d82ea44186a 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -1,10 +1,9 @@ -
- hello world + +
-
From a404c11cfe52b607c0c16d09d7a9d1001665c958 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Fri, 24 Oct 2025 14:06:27 +0200 Subject: [PATCH 02/15] [IMP] awesome_owl: 1.3 cards --- awesome_owl/static/src/card/card.js | 5 +++++ awesome_owl/static/src/card/card.xml | 11 +++++++++++ awesome_owl/static/src/playground.js | 3 ++- awesome_owl/static/src/playground.xml | 7 ++++--- 4 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 awesome_owl/static/src/card/card.js create mode 100644 awesome_owl/static/src/card/card.xml diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js new file mode 100644 index 00000000000..6d00d5c1edf --- /dev/null +++ b/awesome_owl/static/src/card/card.js @@ -0,0 +1,5 @@ +import { Component } from "@odoo/owl"; + +export class Card extends Component { + static template = "awesome_owl.card" +} \ No newline at end of file diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml new file mode 100644 index 00000000000..793857125f2 --- /dev/null +++ b/awesome_owl/static/src/card/card.xml @@ -0,0 +1,11 @@ + + + +
+
+
+

+
+
+
+
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 593c9c7669d..d154013e13e 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -2,8 +2,9 @@ import { Component } from "@odoo/owl"; import { Counter } from "./counter/counter"; +import { Card } from "./card/card"; export class Playground extends Component { static template = "awesome_owl.playground"; - static components = { Counter } + static components = { Counter, Card } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index d82ea44186a..125b0653dc6 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -1,9 +1,10 @@ -
- - +
+ + +
From 04076e2ad8d429a70ca0a0810d5758cc821f00a0 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Fri, 24 Oct 2025 14:20:24 +0200 Subject: [PATCH 03/15] [ADD] awesome_owl: 1.4 markup --- awesome_owl/static/src/card/card.xml | 4 ++-- awesome_owl/static/src/playground.js | 15 +++++++++++---- awesome_owl/static/src/playground.xml | 4 ++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 793857125f2..ce8d28dd26d 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -3,8 +3,8 @@
-
-

+
+

diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index d154013e13e..4096c107288 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,10 +1,17 @@ /** @odoo-module **/ -import { Component } from "@odoo/owl"; -import { Counter } from "./counter/counter"; -import { Card } from "./card/card"; +import {Component, markup, useState} from "@odoo/owl"; +import {Counter} from "./counter/counter"; +import {Card} from "./card/card"; export class Playground extends Component { static template = "awesome_owl.playground"; - static components = { Counter, Card } + static components = {Counter, Card} + + setup() { + this.state = useState({ + value: "Awesome text", + htmlValue: markup('

Hello

') + }) + } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 125b0653dc6..2267b5b244a 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -3,8 +3,8 @@
- - + +
From 87c66bc17a58a6650bd9a62a61c3679f6a5809c0 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Fri, 24 Oct 2025 14:27:48 +0200 Subject: [PATCH 04/15] [ADD] awesome_owl: 1.5 props validation --- awesome_owl/static/src/card/card.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 6d00d5c1edf..556c6c18763 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -2,4 +2,8 @@ import { Component } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card" + static props = { + title: String, + content: String + } } \ No newline at end of file From 7b3b19752a5aebb08ee988ea0f0704fdd54bce42 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Mon, 27 Oct 2025 11:47:09 +0100 Subject: [PATCH 05/15] [IMP] awesome_owl: 1.6 callback --- awesome_owl/static/src/counter/counter.js | 8 +++++++- awesome_owl/static/src/playground.js | 6 ++++++ awesome_owl/static/src/playground.xml | 6 +++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js index 000158b1dd2..f7058f167d3 100644 --- a/awesome_owl/static/src/counter/counter.js +++ b/awesome_owl/static/src/counter/counter.js @@ -2,9 +2,15 @@ import {Component, useState} from "@odoo/owl"; export class Counter extends Component { static template = "awesome_owl.counter" - state = useState({value: 0}) + state = useState({value: 1}) + static props = { + onChange: { typ: Function, optional: true } + } increment() { this.state.value++; + if (this.props.onChange) { + this.props.onChange(); + } } } \ No newline at end of file diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 4096c107288..eebd5d8d542 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -10,8 +10,14 @@ export class Playground extends Component { setup() { this.state = useState({ + sum: 2, value: "Awesome text", htmlValue: markup('

Hello

') }) } + + incrementSum() { + this.state.sum++; + console.log(this.state.sum) + } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 2267b5b244a..e20761a2314 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -2,9 +2,9 @@
- - - + + +
From 1d66294a3e4b84d6f9f0597666420f0af21c23ba Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Mon, 27 Oct 2025 16:15:45 +0100 Subject: [PATCH 06/15] [IMP] awesome_owl: 1.10 autofocus hook --- awesome_owl/static/src/TodoList/todo_item.js | 11 ++++++++++ awesome_owl/static/src/TodoList/todo_item.xml | 9 ++++++++ awesome_owl/static/src/TodoList/todo_list.js | 22 +++++++++++++++++++ awesome_owl/static/src/TodoList/todo_list.xml | 11 ++++++++++ awesome_owl/static/src/playground.js | 4 +++- awesome_owl/static/src/playground.xml | 4 +--- awesome_owl/static/src/utils.js | 10 +++++++++ 7 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 awesome_owl/static/src/TodoList/todo_item.js create mode 100644 awesome_owl/static/src/TodoList/todo_item.xml create mode 100644 awesome_owl/static/src/TodoList/todo_list.js create mode 100644 awesome_owl/static/src/TodoList/todo_list.xml create mode 100644 awesome_owl/static/src/utils.js diff --git a/awesome_owl/static/src/TodoList/todo_item.js b/awesome_owl/static/src/TodoList/todo_item.js new file mode 100644 index 00000000000..73ce38f4b58 --- /dev/null +++ b/awesome_owl/static/src/TodoList/todo_item.js @@ -0,0 +1,11 @@ +import {Component} from "@odoo/owl"; + +export class TodoItem extends Component { + static template = "awesome_owl.todo_item"; + static props = { + todo: { + type: Object, shape: { id: Number, description: String, isCompleted: Boolean } + } + } + +} diff --git a/awesome_owl/static/src/TodoList/todo_item.xml b/awesome_owl/static/src/TodoList/todo_item.xml new file mode 100644 index 00000000000..25507f4872d --- /dev/null +++ b/awesome_owl/static/src/TodoList/todo_item.xml @@ -0,0 +1,9 @@ + + + +
+ . + +
+
+
diff --git a/awesome_owl/static/src/TodoList/todo_list.js b/awesome_owl/static/src/TodoList/todo_list.js new file mode 100644 index 00000000000..a03e304f4d5 --- /dev/null +++ b/awesome_owl/static/src/TodoList/todo_list.js @@ -0,0 +1,22 @@ +import { Component, useState } from "@odoo/owl"; +import { TodoItem } from "./todo_item"; +import { useAutofocus } from '../utils'; + +export class TodoList extends Component { + static template = "awesome_owl.todo_list"; + static components = {TodoItem} + static props = {} + + setup() { + this.todos = useState([]); + this.todoId = useState([1]); + useAutofocus('bestInputEver'); + } + + createTodo = (e) => { + if (e.keyCode === 13 && e.target.value) { + this.todos.push({id: this.todoId++, description: e.target.value, isCompleted: false}) + e.target.value = ""; + } + } +} diff --git a/awesome_owl/static/src/TodoList/todo_list.xml b/awesome_owl/static/src/TodoList/todo_list.xml new file mode 100644 index 00000000000..53fb36aac5b --- /dev/null +++ b/awesome_owl/static/src/TodoList/todo_list.xml @@ -0,0 +1,11 @@ + + + + +
+ + + +
+
+
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index eebd5d8d542..9b098ca4cd9 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -3,10 +3,12 @@ import {Component, markup, useState} from "@odoo/owl"; import {Counter} from "./counter/counter"; import {Card} from "./card/card"; +import {TodoList} from "./TodoList/todo_list"; export class Playground extends Component { static template = "awesome_owl.playground"; - static components = {Counter, Card} + static props = {}; + static components = {Counter, Card, TodoList} setup() { this.state = useState({ diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index e20761a2314..00edc99cc45 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -2,9 +2,7 @@
- - - +
diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js new file mode 100644 index 00000000000..f570513a1a8 --- /dev/null +++ b/awesome_owl/static/src/utils.js @@ -0,0 +1,10 @@ +import { useRef, onMounted } from "@odoo/owl"; + +export function useAutofocus(name) { + const inputRef = useRef(name); + + onMounted(() => { + console.log(`focusing on input ${inputRef.el}`); + inputRef.el.focus() + }) +} From 76c4847672f0211062878f3a50c1d39c57828124 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Tue, 28 Oct 2025 09:11:37 +0100 Subject: [PATCH 07/15] [IMP] awesome_owl: Chapter 1 --- awesome_owl/static/src/TodoList/todo_item.js | 2 ++ awesome_owl/static/src/TodoList/todo_item.xml | 6 ++++-- awesome_owl/static/src/TodoList/todo_list.js | 13 +++++++++++++ awesome_owl/static/src/TodoList/todo_list.xml | 2 +- awesome_owl/static/src/card/card.js | 13 +++++++++++-- awesome_owl/static/src/card/card.xml | 9 +++++++-- awesome_owl/static/src/playground.js | 4 +--- awesome_owl/static/src/playground.xml | 9 +++++++-- 8 files changed, 46 insertions(+), 12 deletions(-) diff --git a/awesome_owl/static/src/TodoList/todo_item.js b/awesome_owl/static/src/TodoList/todo_item.js index 73ce38f4b58..f2ef39bcb09 100644 --- a/awesome_owl/static/src/TodoList/todo_item.js +++ b/awesome_owl/static/src/TodoList/todo_item.js @@ -3,6 +3,8 @@ import {Component} from "@odoo/owl"; export class TodoItem extends Component { static template = "awesome_owl.todo_item"; static props = { + toggleState: { type: Function }, + removeTodo: { type: Function }, todo: { type: Object, shape: { id: Number, description: String, isCompleted: Boolean } } diff --git a/awesome_owl/static/src/TodoList/todo_item.xml b/awesome_owl/static/src/TodoList/todo_item.xml index 25507f4872d..bcb511939a9 100644 --- a/awesome_owl/static/src/TodoList/todo_item.xml +++ b/awesome_owl/static/src/TodoList/todo_item.xml @@ -1,9 +1,11 @@ -
- . +
+ + . +
diff --git a/awesome_owl/static/src/TodoList/todo_list.js b/awesome_owl/static/src/TodoList/todo_list.js index a03e304f4d5..afd31576f32 100644 --- a/awesome_owl/static/src/TodoList/todo_list.js +++ b/awesome_owl/static/src/TodoList/todo_list.js @@ -19,4 +19,17 @@ export class TodoList extends Component { e.target.value = ""; } } + + toggleState = (id) => { + const todo = this.todos.filter(t => t.id === id)[0]; + todo.isCompleted = !todo.isCompleted; + console.log(todo); + } + + removeTodo = (id) => { + const index = this.todos.findIndex(t => t.id === id) + if (index >= 0) { + this.todos.splice(index, 1); + } + } } diff --git a/awesome_owl/static/src/TodoList/todo_list.xml b/awesome_owl/static/src/TodoList/todo_list.xml index 53fb36aac5b..a76f58db9a5 100644 --- a/awesome_owl/static/src/TodoList/todo_list.xml +++ b/awesome_owl/static/src/TodoList/todo_list.xml @@ -4,7 +4,7 @@
- +
diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 556c6c18763..3a7a2a02274 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -1,9 +1,18 @@ -import { Component } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card" static props = { title: String, - content: String + slots: { + type: Object, + shape: { + default: true + } + } + } + + setup() { + this.state = useState({ isOpen: true }) } } \ No newline at end of file diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index ce8d28dd26d..ee27ea35697 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -3,8 +3,13 @@
-
-

+
+
+ +
+

+ +

diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 9b098ca4cd9..c0ab77f0912 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import {Component, markup, useState} from "@odoo/owl"; +import {Component, useState} from "@odoo/owl"; import {Counter} from "./counter/counter"; import {Card} from "./card/card"; import {TodoList} from "./TodoList/todo_list"; @@ -13,8 +13,6 @@ export class Playground extends Component { setup() { this.state = useState({ sum: 2, - value: "Awesome text", - htmlValue: markup('

Hello

') }) } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 00edc99cc45..25b5939e806 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -1,8 +1,13 @@ -
- +
+ + content 1 + + + +
From 9c27ce2f3a4cf57c44940a5331fb6d635bcc1643 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Tue, 28 Oct 2025 09:12:24 +0100 Subject: [PATCH 08/15] [IMP] awesome_owl: formatting --- awesome_owl/static/src/TodoList/todo_item.js | 7 +++---- awesome_owl/static/src/TodoList/todo_item.xml | 5 +++-- awesome_owl/static/src/card/card.js | 6 +++--- awesome_owl/static/src/card/card.xml | 3 ++- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/awesome_owl/static/src/TodoList/todo_item.js b/awesome_owl/static/src/TodoList/todo_item.js index f2ef39bcb09..ff3cba6dc0e 100644 --- a/awesome_owl/static/src/TodoList/todo_item.js +++ b/awesome_owl/static/src/TodoList/todo_item.js @@ -3,11 +3,10 @@ import {Component} from "@odoo/owl"; export class TodoItem extends Component { static template = "awesome_owl.todo_item"; static props = { - toggleState: { type: Function }, - removeTodo: { type: Function }, + toggleState: {type: Function}, + removeTodo: {type: Function}, todo: { - type: Object, shape: { id: Number, description: String, isCompleted: Boolean } + type: Object, shape: {id: Number, description: String, isCompleted: Boolean} } } - } diff --git a/awesome_owl/static/src/TodoList/todo_item.xml b/awesome_owl/static/src/TodoList/todo_item.xml index bcb511939a9..01ec80b0ddd 100644 --- a/awesome_owl/static/src/TodoList/todo_item.xml +++ b/awesome_owl/static/src/TodoList/todo_item.xml @@ -1,8 +1,9 @@ -
- +
+ . diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 3a7a2a02274..3cd0aa8e953 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -1,4 +1,4 @@ -import { Component, useState } from "@odoo/owl"; +import {Component, useState} from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card" @@ -13,6 +13,6 @@ export class Card extends Component { } setup() { - this.state = useState({ isOpen: true }) + this.state = useState({isOpen: true}) } -} \ No newline at end of file +} diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index ee27ea35697..cc5e894b00d 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -5,7 +5,8 @@
- +

From ae1ac48aabd6643e2049dd8e62c3664237f7ae93 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Tue, 28 Oct 2025 14:10:21 +0100 Subject: [PATCH 09/15] [IMP] awesome_dashboard: 1-3 --- awesome_dashboard/static/src/dashboard.js | 25 ++++++++++++++++++- awesome_dashboard/static/src/dashboard.scss | 3 +++ awesome_dashboard/static/src/dashboard.xml | 11 +++++++- .../src/dashboard_item/dashboard_item.js | 9 +++++++ .../src/dashboard_item/dashboard_item.xml | 10 ++++++++ 5 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard.scss create mode 100644 awesome_dashboard/static/src/dashboard_item/dashboard_item.js create mode 100644 awesome_dashboard/static/src/dashboard_item/dashboard_item.xml diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 637fa4bb972..6a8fce5298e 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,10 +1,33 @@ /** @odoo-module **/ - +import { useService } from "@web/core/utils/hooks"; import { Component } from "@odoo/owl"; import { registry } from "@web/core/registry"; +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, DashboardItem} + + setup() { + this.action = useService("action"); + } + + openCustomerView() { + this.action.doAction("base.action_partner_form"); + } + + openLeadView() { + this.action.doAction({ + type: "ir.actions.act_window", + mane: "All 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..4585c17be92 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard.scss @@ -0,0 +1,3 @@ +.o_dashboard { + background-color: #0a3622; +} \ No newline at end of file diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 1a2ac9a2fed..4c6b175d3f9 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -2,7 +2,16 @@ - hello dashboard + + + + + +

+ Hello World + Hello There +
+ 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..7fe6cf91ffc --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js @@ -0,0 +1,9 @@ +import { Component } from "@odoo/owl"; + +export class DashboardItem extends Component { + static template = 'awesome_dashboard.dashboard_item' + static props = { + size: { Type: Number, default: 1, optional: true }, + slots: { type:Object, shape: { default: Object }} + } +} \ No newline at end of file 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..143d86e543a --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml @@ -0,0 +1,10 @@ + + + +
+
+ +
+
+
+
\ No newline at end of file From dca329d8508db573e3ccf19f258ac0ea4d6af4c5 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Wed, 29 Oct 2025 10:21:27 +0100 Subject: [PATCH 10/15] [IMP] awesome_dashboard: 4-7 --- awesome_dashboard/static/src/dashboard.js | 7 +++- awesome_dashboard/static/src/dashboard.xml | 23 ++++++++++-- .../src/dashboard_item/dashboard_item.js | 5 ++- .../src/dashboard_item/dashboard_item.xml | 1 + .../dashboard_item_content.js | 8 ++++ .../dashboard_item_content.xml | 8 ++++ .../static/src/pie_chart/pie_chart.js | 37 +++++++++++++++++++ .../static/src/pie_chart/pie_chart.xml | 10 +++++ awesome_dashboard/static/src/statistics.js | 21 +++++++++++ 9 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.js create mode 100644 awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.xml create mode 100644 awesome_dashboard/static/src/pie_chart/pie_chart.js create mode 100644 awesome_dashboard/static/src/pie_chart/pie_chart.xml create mode 100644 awesome_dashboard/static/src/statistics.js diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 6a8fce5298e..acaf84739a4 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,16 +1,19 @@ /** @odoo-module **/ import { useService } from "@web/core/utils/hooks"; -import { Component } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; import { registry } from "@web/core/registry"; import { Layout } from '@web/search/layout' import { DashboardItem } from "./dashboard_item/dashboard_item"; +import {PieChart} from "./pie_chart/pie_chart"; +import {DashboardItemContent} from "./dashboard_item_content/dashboard_item_content"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; - static components = {Layout, DashboardItem} + static components = {Layout, DashboardItem, PieChart, DashboardItemContent} setup() { this.action = useService("action"); + this.stats = useState(useService("statistics")); } openCustomerView() { diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 4c6b175d3f9..d0efe9ee94c 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -7,10 +7,27 @@ -
- Hello World - Hello There +
+ + + + + + + + + + + + + + + + + +
+
Loading
diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.js b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js index 7fe6cf91ffc..d27ac159f80 100644 --- a/awesome_dashboard/static/src/dashboard_item/dashboard_item.js +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js @@ -3,7 +3,8 @@ import { Component } from "@odoo/owl"; export class DashboardItem extends Component { static template = 'awesome_dashboard.dashboard_item' static props = { - size: { Type: Number, default: 1, optional: true }, - slots: { type:Object, shape: { default: Object }} + size: { type: Number, default: 1, optional: true }, + slots: { type: Object, shape: { default: Object }}, + title: { type: String, default: '', optional: true} } } \ No newline at end of file diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml index 143d86e543a..9141bf0e454 100644 --- a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml @@ -3,6 +3,7 @@
+

diff --git a/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.js b/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.js new file mode 100644 index 00000000000..161529922e3 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.js @@ -0,0 +1,8 @@ +import { Component } from "@odoo/owl"; + +export class DashboardItemContent extends Component { + static template = 'awesome_dashboard.dashboard_item_content' + static props = { + text: String | Number + } +} \ No newline at end of file diff --git a/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.xml b/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.xml new file mode 100644 index 00000000000..652b3b8f26a --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.xml @@ -0,0 +1,8 @@ + + + +
+

+
+
+
\ No newline at end of file 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..89ac1a513a8 --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.js @@ -0,0 +1,37 @@ +import { Component, onWillStart, useRef, onMounted, onWillUnmount } from "@odoo/owl"; +import { getColor } from "@web/core/colors/colors"; +import { loadJS } from "@web/core/assets"; + +export class PieChart extends Component { + static template = 'awesome_dashboard.pie_chart'; + static props = { + data: { type: Object, shape: { m: Number, s: Number, xl: Number }} + } + + setup() { + this.canvasRef = useRef("canvas"); + onWillStart(() => loadJS("/web/static/lib/Chart/Chart.js")); + onMounted(() => this.renderChart()); + onWillUnmount(() => this.chart.destroy()); + } + + renderChart() { + const labels = Object.keys(this.props.data); + const data = Object.values(this.props.data); + const color = labels.map((_, index) => getColor(index*4)); + this.chart = new Chart(this.canvasRef.el, { + type: "pie", + data: { + labels: labels, + datasets: [ + { + label: this.props.label, + data: data, + backgroundColor: color, + }, + ], + }, + }); + } + +} \ No newline at end of file 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..43693aa8475 --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.xml @@ -0,0 +1,10 @@ + + + +
+
+ +
+
+
+
\ No newline at end of file diff --git a/awesome_dashboard/static/src/statistics.js b/awesome_dashboard/static/src/statistics.js new file mode 100644 index 00000000000..37bcb7c8b0e --- /dev/null +++ b/awesome_dashboard/static/src/statistics.js @@ -0,0 +1,21 @@ +import { registry } from "@web/core/registry"; +import { rpc } from "@web/core/network/rpc" +import { reactive } from "@odoo/owl"; + +export const statistics = { + start() { + const statistics = reactive({ isReady: false }); + + async function loadData() { + const updates = await rpc("/awesome_dashboard/statistics"); + Object.assign(statistics, updates, { isReady: true }); + } + + setInterval(loadData, 10*60*1000); + loadData(); + + return statistics + } +} + +registry.category("services").add("statistics", statistics); From 1c205074b4a73a45bba4f7a04e95d9a01c16d3b1 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Thu, 30 Oct 2025 09:26:28 +0100 Subject: [PATCH 11/15] [IMP] awesome_dashboard: 8-11 --- awesome_dashboard/static/src/dashboard.js | 36 --------- awesome_dashboard/static/src/dashboard.xml | 34 -------- .../static/src/dashboard/dashboard.js | 52 +++++++++++++ .../static/src/{ => dashboard}/dashboard.scss | 2 +- .../static/src/dashboard/dashboard.xml | 47 +++++++++++ .../dashboard_item/dashboard_item.js | 3 +- .../dashboard_item/dashboard_item.xml | 3 +- .../static/src/dashboard/dashboard_items.js | 78 +++++++++++++++++++ .../src/dashboard/number_card/number_card.js | 9 +++ .../number_card/number_card.xml} | 7 +- .../{ => dashboard}/pie_chart/pie_chart.js | 3 +- .../{ => dashboard}/pie_chart/pie_chart.xml | 2 +- .../pie_chart_card/pie_chart_card.js | 11 +++ .../pie_chart_card/pie_chart_card.xml | 7 ++ .../static/src/{ => dashboard}/statistics.js | 0 .../static/src/dashboard_action.js | 14 ++++ .../dashboard_item_content.js | 8 -- awesome_owl/static/src/utils.js | 1 - 18 files changed, 227 insertions(+), 90 deletions(-) delete mode 100644 awesome_dashboard/static/src/dashboard.js delete mode 100644 awesome_dashboard/static/src/dashboard.xml create mode 100644 awesome_dashboard/static/src/dashboard/dashboard.js rename awesome_dashboard/static/src/{ => dashboard}/dashboard.scss (95%) create mode 100644 awesome_dashboard/static/src/dashboard/dashboard.xml rename awesome_dashboard/static/src/{ => dashboard}/dashboard_item/dashboard_item.js (82%) rename awesome_dashboard/static/src/{ => dashboard}/dashboard_item/dashboard_item.xml (83%) create mode 100644 awesome_dashboard/static/src/dashboard/dashboard_items.js create mode 100644 awesome_dashboard/static/src/dashboard/number_card/number_card.js rename awesome_dashboard/static/src/{dashboard_item_content/dashboard_item_content.xml => dashboard/number_card/number_card.xml} (67%) rename awesome_dashboard/static/src/{ => dashboard}/pie_chart/pie_chart.js (99%) rename awesome_dashboard/static/src/{ => dashboard}/pie_chart/pie_chart.xml (96%) create mode 100644 awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.js create mode 100644 awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.xml rename awesome_dashboard/static/src/{ => dashboard}/statistics.js (100%) create mode 100644 awesome_dashboard/static/src/dashboard_action.js delete mode 100644 awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.js diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js deleted file mode 100644 index acaf84739a4..00000000000 --- a/awesome_dashboard/static/src/dashboard.js +++ /dev/null @@ -1,36 +0,0 @@ -/** @odoo-module **/ -import { useService } from "@web/core/utils/hooks"; -import { Component, useState } from "@odoo/owl"; -import { registry } from "@web/core/registry"; -import { Layout } from '@web/search/layout' -import { DashboardItem } from "./dashboard_item/dashboard_item"; -import {PieChart} from "./pie_chart/pie_chart"; -import {DashboardItemContent} from "./dashboard_item_content/dashboard_item_content"; - -class AwesomeDashboard extends Component { - static template = "awesome_dashboard.AwesomeDashboard"; - static components = {Layout, DashboardItem, PieChart, DashboardItemContent} - - setup() { - this.action = useService("action"); - this.stats = useState(useService("statistics")); - } - - openCustomerView() { - this.action.doAction("base.action_partner_form"); - } - - openLeadView() { - this.action.doAction({ - type: "ir.actions.act_window", - mane: "All 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.xml b/awesome_dashboard/static/src/dashboard.xml deleted file mode 100644 index d0efe9ee94c..00000000000 --- a/awesome_dashboard/static/src/dashboard.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
-
Loading
-
-
- -
diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js new file mode 100644 index 00000000000..d199f8844e5 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -0,0 +1,52 @@ +/** @odoo-module **/ +import { useService } from "@web/core/utils/hooks"; +import { Component, useState, onWillStart } from "@odoo/owl"; +import { registry } from "@web/core/registry"; +import { Layout } from '@web/search/layout' +import { DashboardItem } from "./dashboard_item/dashboard_item"; +import { PieChart } from "./pie_chart/pie_chart"; + +export class AwesomeDashboard extends Component { + static template = "awesome_dashboard.AwesomeDashboard"; + static components = { Layout, DashboardItem, PieChart } + + setup() { + this.action = useService("action"); + this.items = registry.category("awesome_dashboard").getAll() + this.stats = useState(useService("statistics")); + this.enabled = useState(this.getEnabledItems()); + this.state = useState({change: 0}) + } + + openCustomerView() { + this.action.doAction("base.action_partner_form"); + } + + openLeadView() { + this.action.doAction({ + type: "ir.actions.act_window", + mane: "All leads", + res_model: "crm.lead", + views: [ + [false, "list"], + [false, "form"], + ], + }); + } + + apply() { + this.items.forEach(item => { + const el = document.getElementById(`checkbox-${item.id}`) + localStorage.setItem(item.id, el.checked); + }) + this.enabled = this.getEnabledItems(); + this.state.change++; // Force rerender because the line above doesn't do it + console.log(this.enabled) + } + + getEnabledItems() { + return this.items.filter(item => localStorage.getItem(item.id) === 'true').map(x => x.id) + } +} + +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 95% rename from awesome_dashboard/static/src/dashboard.scss rename to awesome_dashboard/static/src/dashboard/dashboard.scss index 4585c17be92..710cf0b5222 100644 --- a/awesome_dashboard/static/src/dashboard.scss +++ b/awesome_dashboard/static/src/dashboard/dashboard.scss @@ -1,3 +1,3 @@ .o_dashboard { background-color: #0a3622; -} \ No newline at end of file +} diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml new file mode 100644 index 00000000000..c3d9ca65deb --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + +
+ + + + + + +
+
Loading
+ + +
+
+
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 82% rename from awesome_dashboard/static/src/dashboard_item/dashboard_item.js rename to awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.js index d27ac159f80..886f0a86a66 100644 --- a/awesome_dashboard/static/src/dashboard_item/dashboard_item.js +++ b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.js @@ -5,6 +5,5 @@ export class DashboardItem extends Component { static props = { size: { type: Number, default: 1, optional: true }, slots: { type: Object, shape: { default: Object }}, - title: { type: String, default: '', optional: true} } -} \ No newline at end of file +} 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 83% rename from awesome_dashboard/static/src/dashboard_item/dashboard_item.xml rename to awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml index 9141bf0e454..52b470237be 100644 --- a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml @@ -3,9 +3,8 @@
-

- \ No newline at end of file + 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..4e8b39369df --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js @@ -0,0 +1,78 @@ +import {NumberCard} from "./number_card/number_card"; +import {PieChartCard} from "./pie_chart_card/pie_chart_card"; +import { registry } from "@web/core/registry"; + +const dashboardItems = [ + { + id: "average_quantity", + description: "Average amount of t-shirt", + Component: NumberCard, + // size and props are optionals + size: 2, + 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 to go from new to sent or cancelled", + Component: NumberCard, + // size and props are optionals + size: 2, + 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 this month", + Component: NumberCard, + // size and props are optionals + size: 1, + props: (data) => ({ + title: "Number of new orders this month", + value: data.nb_new_orders + }), + }, + { + id: "nb_cancelled_orders", + description: "Number of cancelled this month", + Component: NumberCard, + // size and props are optionals + size: 1, + props: (data) => ({ + title: "Number of cancelled this month", + value: data.nb_cancelled_orders + }), + }, + { + id: "total_amount", + description: "Total amount of new orders this month", + Component: NumberCard, + // size and props are optionals + size: 2, + props: (data) => ({ + title: "Total amount of new orders this month", + value: data.total_amount + }), + }, + { + id: "pie_chart", + description: "!!! Pie !!!", + Component: PieChartCard, + // size and props are optionals + size: 1, + props: (data) => { + return ({ + title: "Pie!", + data: data.orders_by_size + }) + }, + }, +]; + +dashboardItems.forEach(item => { + registry.category("awesome_dashboard").add(item.id, item); +}) 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..acf997f321b --- /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.number_card' + static props = { + title: String, + value: Number + } +} diff --git a/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.xml b/awesome_dashboard/static/src/dashboard/number_card/number_card.xml similarity index 67% rename from awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.xml rename to awesome_dashboard/static/src/dashboard/number_card/number_card.xml index 652b3b8f26a..27fed72e9af 100644 --- a/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.xml +++ b/awesome_dashboard/static/src/dashboard/number_card/number_card.xml @@ -1,8 +1,9 @@ - + +

-

+

-
\ No newline at end of file + 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 99% rename from awesome_dashboard/static/src/pie_chart/pie_chart.js rename to awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js index 89ac1a513a8..8776547112e 100644 --- a/awesome_dashboard/static/src/pie_chart/pie_chart.js +++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js @@ -33,5 +33,4 @@ export class PieChart extends Component { }, }); } - -} \ No newline at end of file +} 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 96% rename from awesome_dashboard/static/src/pie_chart/pie_chart.xml rename to awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.xml index 43693aa8475..242451cf26c 100644 --- a/awesome_dashboard/static/src/pie_chart/pie_chart.xml +++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.xml @@ -7,4 +7,4 @@
- \ No newline at end of file + 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..6243679bd01 --- /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.pie_chart_card' + static components = { PieChart } + static props = { + title: String, + data: Object + } +} diff --git a/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.xml b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.xml new file mode 100644 index 00000000000..dbfad8eaf6e --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.xml @@ -0,0 +1,7 @@ + + + +

+ +
+
\ No newline at end of file diff --git a/awesome_dashboard/static/src/statistics.js b/awesome_dashboard/static/src/dashboard/statistics.js similarity index 100% rename from awesome_dashboard/static/src/statistics.js rename to awesome_dashboard/static/src/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..74232bef1ab --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_action.js @@ -0,0 +1,14 @@ +/** @odoo-module */ + +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); diff --git a/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.js b/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.js deleted file mode 100644 index 161529922e3..00000000000 --- a/awesome_dashboard/static/src/dashboard_item_content/dashboard_item_content.js +++ /dev/null @@ -1,8 +0,0 @@ -import { Component } from "@odoo/owl"; - -export class DashboardItemContent extends Component { - static template = 'awesome_dashboard.dashboard_item_content' - static props = { - text: String | Number - } -} \ No newline at end of file diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js index f570513a1a8..e438e44435f 100644 --- a/awesome_owl/static/src/utils.js +++ b/awesome_owl/static/src/utils.js @@ -4,7 +4,6 @@ export function useAutofocus(name) { const inputRef = useRef(name); onMounted(() => { - console.log(`focusing on input ${inputRef.el}`); inputRef.el.focus() }) } From 3179456b39bc5b9bde163d3698381e5a2356374b Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Thu, 30 Oct 2025 09:43:03 +0100 Subject: [PATCH 12/15] [IMP] awesome_dashboard: responsiveness - full width cards on phones --- .../static/src/dashboard/dashboard_item/dashboard_item.scss | 6 ++++++ .../static/src/dashboard/dashboard_item/dashboard_item.xml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.scss diff --git a/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.scss b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.scss new file mode 100644 index 00000000000..811e443797c --- /dev/null +++ b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.scss @@ -0,0 +1,6 @@ + +@media (max-width: 575.98px) { + .full-width-phone { + width: 100% !important; + } +} \ No newline at end of file diff --git a/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml index 52b470237be..89310161963 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml @@ -1,7 +1,7 @@ -
+
From 2abdc45621c10d0d79419bbf3f6cf5a6de7ba8a0 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Fri, 31 Oct 2025 08:54:58 +0100 Subject: [PATCH 13/15] [IMP] awesome_dashboard: responsiveness - reactive list fix --- awesome_dashboard/static/src/dashboard/dashboard.js | 7 ++----- awesome_dashboard/static/src/dashboard/dashboard.xml | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js index d199f8844e5..2764ebf5995 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.js +++ b/awesome_dashboard/static/src/dashboard/dashboard.js @@ -14,8 +14,7 @@ export class AwesomeDashboard extends Component { this.action = useService("action"); this.items = registry.category("awesome_dashboard").getAll() this.stats = useState(useService("statistics")); - this.enabled = useState(this.getEnabledItems()); - this.state = useState({change: 0}) + this.state = useState({ enabled: this.getEnabledItems() }) } openCustomerView() { @@ -39,9 +38,7 @@ export class AwesomeDashboard extends Component { const el = document.getElementById(`checkbox-${item.id}`) localStorage.setItem(item.id, el.checked); }) - this.enabled = this.getEnabledItems(); - this.state.change++; // Force rerender because the line above doesn't do it - console.log(this.enabled) + this.state.enabled = this.getEnabledItems(); // Force rerender because the line above doesn't do it } getEnabledItems() { diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml index c3d9ca65deb..56e5355156a 100644 --- a/awesome_dashboard/static/src/dashboard/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard/dashboard.xml @@ -11,7 +11,7 @@
- + @@ -30,7 +30,7 @@

Which cards do you wish to see?

- +
From a29e74ea1af0756f47780524ff4b49c6abd0df53 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Fri, 31 Oct 2025 08:55:48 +0100 Subject: [PATCH 14/15] [ADD] awesome_clicker: 1-8 --- .../static/src/click_value/ClickValue.js | 14 +++++++++ .../static/src/click_value/ClickValue.xml | 6 ++++ awesome_clicker/static/src/clicker_service.js | 23 ++++++++++++++ .../clicker_systray_item.js | 30 +++++++++++++++++++ .../clicker_systray_item.xml | 11 +++++++ .../static/src/client_action/client_action.js | 16 ++++++++++ .../src/client_action/client_action.xml | 20 +++++++++++++ awesome_clicker/static/src/useClicker.js | 6 ++++ awesome_clicker/static/views/views.xml | 9 ++++++ 9 files changed, 135 insertions(+) create mode 100644 awesome_clicker/static/src/click_value/ClickValue.js create mode 100644 awesome_clicker/static/src/click_value/ClickValue.xml create mode 100644 awesome_clicker/static/src/clicker_service.js create mode 100644 awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js create mode 100644 awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.xml create mode 100644 awesome_clicker/static/src/client_action/client_action.js create mode 100644 awesome_clicker/static/src/client_action/client_action.xml create mode 100644 awesome_clicker/static/src/useClicker.js create mode 100644 awesome_clicker/static/views/views.xml diff --git a/awesome_clicker/static/src/click_value/ClickValue.js b/awesome_clicker/static/src/click_value/ClickValue.js new file mode 100644 index 00000000000..1426db89941 --- /dev/null +++ b/awesome_clicker/static/src/click_value/ClickValue.js @@ -0,0 +1,14 @@ +import {Component} from "@odoo/owl"; +import { humanNumber } from "@web/core/utils/numbers"; + +export class ClickValue extends Component { + static template = 'awesome_clicker.click_value' + static props = { value: Number } + static components = {} + + setup() {} + + humanizedValue() { + return humanNumber(this.props.value); + } +} \ No newline at end of file diff --git a/awesome_clicker/static/src/click_value/ClickValue.xml b/awesome_clicker/static/src/click_value/ClickValue.xml new file mode 100644 index 00000000000..cf4b8e5c510 --- /dev/null +++ b/awesome_clicker/static/src/click_value/ClickValue.xml @@ -0,0 +1,6 @@ + + + + Clicks: + + \ No newline at end of file diff --git a/awesome_clicker/static/src/clicker_service.js b/awesome_clicker/static/src/clicker_service.js new file mode 100644 index 00000000000..84afeead7a7 --- /dev/null +++ b/awesome_clicker/static/src/clicker_service.js @@ -0,0 +1,23 @@ +import { registry } from "@web/core/registry"; +import { reactive } from "@odoo/owl"; + +const ClickerService = { + start() { + const state = reactive({ + clicks: 0, + level: 0, + clickBots: 0, + }); + + setInterval(() => state.clicks += 10*state.clickBots, 10 * 1000) + + return { + state, + increment(inc) { + state.clicks += inc + } + }; + }, +}; + +registry.category("services").add("clicker", ClickerService); \ No newline at end of file diff --git a/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js new file mode 100644 index 00000000000..9f5d74dc779 --- /dev/null +++ b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js @@ -0,0 +1,30 @@ +import { Component, useState, useExternalListener } from "@odoo/owl"; +import { registry } from "@web/core/registry"; +import { useService } from "@web/core/utils/hooks"; +import { useClicker } from "../useClicker"; +import { ClickValue } from "../click_value/ClickValue"; + +export class ClickerSystrayItem extends Component { + static template = 'awesome_clicker.systray_item' + static props = {} + static components = {ClickValue} + + setup() { + this.actionService = useService('action') + this.clicker = useClicker() + useExternalListener(window.document.body, "click", () => this.clicker.increment(1), true) + } + + openDialog() { + this.actionService.doAction({ + type: "ir.actions.client", + tag: "awesome_clicker.client_action", + target: "new", + name: "Clicker" + }) + } +} + +registry.category("systray").add("awesome_clicker.clicker", { + Component: ClickerSystrayItem, +}, { sequence: 100 }); \ No newline at end of file diff --git a/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.xml b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.xml new file mode 100644 index 00000000000..cb5b336b171 --- /dev/null +++ b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.xml @@ -0,0 +1,11 @@ + + + +
+ + +
+
+
diff --git a/awesome_clicker/static/src/client_action/client_action.js b/awesome_clicker/static/src/client_action/client_action.js new file mode 100644 index 00000000000..c66501db2e5 --- /dev/null +++ b/awesome_clicker/static/src/client_action/client_action.js @@ -0,0 +1,16 @@ +import {Component} from "@odoo/owl"; +import {registry} from "@web/core/registry"; +import {useClicker} from "../useClicker"; +import {ClickValue} from "../click_value/ClickValue"; + +export class ClientAction extends Component { + static template = 'awesome_clicker.action' + static props = {} + static components = {ClickValue} + + setup() { + this.clicker = useClicker(); + } +} + +registry.category("actions").add("awesome_clicker.client_action", ClientAction); \ No newline at end of file diff --git a/awesome_clicker/static/src/client_action/client_action.xml b/awesome_clicker/static/src/client_action/client_action.xml new file mode 100644 index 00000000000..33d6b67292b --- /dev/null +++ b/awesome_clicker/static/src/client_action/client_action.xml @@ -0,0 +1,20 @@ + + + +
+
+ + +
+

Bots

+
+ x ClickBots ( clicks/10seconds) +
+
+ +
+
+
+
\ No newline at end of file diff --git a/awesome_clicker/static/src/useClicker.js b/awesome_clicker/static/src/useClicker.js new file mode 100644 index 00000000000..8618a69199c --- /dev/null +++ b/awesome_clicker/static/src/useClicker.js @@ -0,0 +1,6 @@ +const { useState } = owl; +import { useService } from "@web/core/utils/hooks"; + +export function useClicker() { + return useState(useService('clicker')) +} \ No newline at end of file diff --git a/awesome_clicker/static/views/views.xml b/awesome_clicker/static/views/views.xml new file mode 100644 index 00000000000..6635541deb2 --- /dev/null +++ b/awesome_clicker/static/views/views.xml @@ -0,0 +1,9 @@ + + + + + Clicker Action + awesome_clicker.client_action + + + From f75bc19302ac3c312518a49ab38eb74c6b8a1ce0 Mon Sep 17 00:00:00 2001 From: Frantisek Binovsky Date: Fri, 31 Oct 2025 13:13:32 +0100 Subject: [PATCH 15/15] [ADD] awesome_clicker: 9-15 --- awesome_clicker/static/src/click_rewards.js | 26 +++++++ .../static/src/click_value/ClickValue.js | 2 +- .../static/src/clicker_command_provider.js | 26 +++++++ awesome_clicker/static/src/clicker_model.js | 71 +++++++++++++++++++ awesome_clicker/static/src/clicker_service.js | 47 ++++++++---- .../clicker_systray_item.js | 1 - .../clicker_systray_item.xml | 2 +- .../static/src/client_action/client_action.js | 12 ++++ .../src/client_action/client_action.xml | 35 +++++++-- .../form_controller/form_controller_patch.js | 13 ++++ 10 files changed, 212 insertions(+), 23 deletions(-) create mode 100644 awesome_clicker/static/src/click_rewards.js create mode 100644 awesome_clicker/static/src/clicker_command_provider.js create mode 100644 awesome_clicker/static/src/clicker_model.js create mode 100644 awesome_clicker/static/src/form_controller/form_controller_patch.js diff --git a/awesome_clicker/static/src/click_rewards.js b/awesome_clicker/static/src/click_rewards.js new file mode 100644 index 00000000000..552ffa68588 --- /dev/null +++ b/awesome_clicker/static/src/click_rewards.js @@ -0,0 +1,26 @@ +export const rewards = [ + { + description: "Get 1 click bot", + apply(clicker) { + clicker.clickBots += 1; + }, + minLevel: 0, + maxLevel: 2, + }, + { + description: "Get 10 click bots", + apply(clicker) { + clicker.clickBots += 10; + }, + minLevel: 3, + maxLevel: 4, + }, + { + description: "Increase bot power!", + apply(clicker) { + clicker.multipler += 1; + }, + minLevel: 3, + maxLevel: 10 + }, +]; \ No newline at end of file diff --git a/awesome_clicker/static/src/click_value/ClickValue.js b/awesome_clicker/static/src/click_value/ClickValue.js index 1426db89941..adc8b4aec4e 100644 --- a/awesome_clicker/static/src/click_value/ClickValue.js +++ b/awesome_clicker/static/src/click_value/ClickValue.js @@ -9,6 +9,6 @@ export class ClickValue extends Component { setup() {} humanizedValue() { - return humanNumber(this.props.value); + return humanNumber(this.props.value, { minDigits: 2 }); } } \ No newline at end of file diff --git a/awesome_clicker/static/src/clicker_command_provider.js b/awesome_clicker/static/src/clicker_command_provider.js new file mode 100644 index 00000000000..9d24821b011 --- /dev/null +++ b/awesome_clicker/static/src/clicker_command_provider.js @@ -0,0 +1,26 @@ +import { registry } from "@web/core/registry"; + +registry.category('command_provider').add("clicker", { + provide: (env, options) => { + return [{ + action() { + env.services.action.doAction({ + type: "ir.actions.client", + tag: "awesome_clicker.client_action", + target: "new", + name: "Clicker Game" + }) + }, + category: "debug", + name: "Open clicker game", + }, + { + action() { + env.services["clicker"].buyClickBot() + }, + category: "debug", + name: "Buy one click bot", + } + ] + } +}) \ No newline at end of file diff --git a/awesome_clicker/static/src/clicker_model.js b/awesome_clicker/static/src/clicker_model.js new file mode 100644 index 00000000000..b9ffbab1129 --- /dev/null +++ b/awesome_clicker/static/src/clicker_model.js @@ -0,0 +1,71 @@ +import { Reactive } from "@web/core/utils/reactive"; +import { EventBus } from "@odoo/owl"; +import {rewards} from "./click_rewards"; + +export class ClickerModel extends Reactive { + + constructor() { + super() + this.clicks = 850 + this.level = 0 + this.clickBots = 0 + this.bigBots = 0 + this.power = 1 + this.bus = new EventBus(); + } + + increment(inc) { + this.clicks += inc; + if (this.level < 1 && this.clicks >= 1000) { + this.level++; + this.bus.trigger("Level1"); + } + if (this.level === 1 && this.clicks >= 5000) { + this.level++; + this.bus.trigger("Level2") + } + if (this.level === 2 && this.clicks >= 100000) { + this.level++; + this.bus.trigger("Level3") + } + } + + tick() { + this.increment((this.clickBots * 10 + this.bigBots * 100) * this.power); + } + + buyClickBot() { + const clickBotPrice = 1000; + if (this.clicks < clickBotPrice) { + return false; + } + this.clicks -= clickBotPrice; + this.clickBots++; + } + + buyBigBot() { + const bigBotPrice = 5000; + if (this.clicks < bigBotPrice) { + return false; + } + this.clicks -= bigBotPrice; + this.bigBots++; + } + + buyPower() { + const powerPrice = 100000; + if (this.clicks < powerPrice) { + return false + } + this.clicks -= powerPrice; + this.power++; + } + + giveReward() { + const validRewards = rewards.filter((r) => r.maxLevel >= this.level && r.minLevel <= this.level); + console.log(validRewards); + const reward = validRewards[Math.floor(Math.random() * validRewards.length)]; + console.log(reward) + this.bus.trigger("Reward", reward) + } +} \ No newline at end of file diff --git a/awesome_clicker/static/src/clicker_service.js b/awesome_clicker/static/src/clicker_service.js index 84afeead7a7..93cd6459e30 100644 --- a/awesome_clicker/static/src/clicker_service.js +++ b/awesome_clicker/static/src/clicker_service.js @@ -1,22 +1,41 @@ import { registry } from "@web/core/registry"; -import { reactive } from "@odoo/owl"; +import { ClickerModel } from "./clicker_model"; const ClickerService = { - start() { - const state = reactive({ - clicks: 0, - level: 0, - clickBots: 0, - }); + dependencies: ["effect", "action", "notification"], + start(env, services) { + const clicker = new ClickerModel() - setInterval(() => state.clicks += 10*state.clickBots, 10 * 1000) + document.addEventListener("click", () => clicker.increment(1), true); + clicker.bus.addEventListener("Level1", () => services.effect.add({ message: "Level up! You can now buy click bots!"})) + clicker.bus.addEventListener("Level2", () => services.effect.add({ message: "Level up! You can now buy big bots!"})) + clicker.bus.addEventListener("Level3", () => services.effect.add({ message: "Level up! You can now buy powers!"})) + clicker.bus.addEventListener("Reward", (e) => { + const reward = e.detail; + const closeNotification = services.notification.add(`You won a reward!: "${reward.description}"`, + { + type: "success", + sticky: true, + buttons: [ + { + name: "Collect", + onClick: () => { + reward.apply(clicker); + closeNotification(); + services.action.doAction({ + type: "ir.actions.client", + tag: "awesome_clicker.client_action", + target: "new", + name: "Clicker Game" + }) + } + } + ] + }) + }) - return { - state, - increment(inc) { - state.clicks += inc - } - }; + setInterval(() => clicker.tick(), 10 * 1000) + return clicker; }, }; diff --git a/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js index 9f5d74dc779..8c3fb9648fa 100644 --- a/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js +++ b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js @@ -12,7 +12,6 @@ export class ClickerSystrayItem extends Component { setup() { this.actionService = useService('action') this.clicker = useClicker() - useExternalListener(window.document.body, "click", () => this.clicker.increment(1), true) } openDialog() { diff --git a/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.xml b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.xml index cb5b336b171..cb1b1aa4e63 100644 --- a/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.xml +++ b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.xml @@ -2,7 +2,7 @@
- + diff --git a/awesome_clicker/static/src/client_action/client_action.js b/awesome_clicker/static/src/client_action/client_action.js index c66501db2e5..0569acf8920 100644 --- a/awesome_clicker/static/src/client_action/client_action.js +++ b/awesome_clicker/static/src/client_action/client_action.js @@ -11,6 +11,18 @@ export class ClientAction extends Component { setup() { this.clicker = useClicker(); } + + canBuyClickBot() { + return this.clicker.level > 0 && this.clicker.clicks >= 1000 + } + + canBuyBigBot() { + return this.clicker.level > 1 && this.clicker.clicks >= 5000 + } + + canBuyPower() { + return this.clicker.level > 2 && this.clicker.clicks >= 100000 + } } registry.category("actions").add("awesome_clicker.client_action", ClientAction); \ No newline at end of file diff --git a/awesome_clicker/static/src/client_action/client_action.xml b/awesome_clicker/static/src/client_action/client_action.xml index 33d6b67292b..06ce6598924 100644 --- a/awesome_clicker/static/src/client_action/client_action.xml +++ b/awesome_clicker/static/src/client_action/client_action.xml @@ -3,17 +3,40 @@
- -

Bots

-
- x ClickBots ( clicks/10seconds) +
+
+
+ x ClickBots (10 clicks/10seconds) +
+
+ +
+
+
+
+ x BigBots (100 clicks/10seconds) +
+
+ +
+
-
- +

Power multiplier

+
+
+
+ x POWER!!!! +
+
+ +
+
diff --git a/awesome_clicker/static/src/form_controller/form_controller_patch.js b/awesome_clicker/static/src/form_controller/form_controller_patch.js new file mode 100644 index 00000000000..db5411e3add --- /dev/null +++ b/awesome_clicker/static/src/form_controller/form_controller_patch.js @@ -0,0 +1,13 @@ +import { FormController } from "@web/views/form/form_controller"; +import { patch } from "@web/core/utils/patch"; +import { useClicker } from "../useClicker"; + +patch(FormController.prototype, { + setup() { + super.setup(...arguments) + if (Math.random() < 0.6) { + const clicker = useClicker(); + clicker.giveReward() + } + } +}) \ No newline at end of file