diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index c4fb245621b..88527030c13 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,8 +1,36 @@ -import { Component } from "@odoo/owl"; +import { Component, onWillStart, useState } from "@odoo/owl"; import { registry } from "@web/core/registry"; +import { useService } from "@web/core/utils/hooks"; +import { _t } from "@web/core/l10n/translation"; + +import { DashboardItem } from "./dashboard_item/dashboard_item"; +import { Layout } from "@web/search/layout" +import { PieChart } from "./pie_chart/pie_chart"; + class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; + static components = { Layout, DashboardItem, PieChart }; + + setup() { + this.action = useService("action"); + this.state = useState({ + stats: useService("awesome_dashboard.statistics"), + }); + } + + async openCustomersKanban() { + this.action.doAction('base.action_partner_form'); + } + + async openLeads() { + this.action.doAction({ + type: 'ir.actions.act_window', + name: _t('Lots of 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..12d12f7d1f8 --- /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..07d9d85249d 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -2,7 +2,20 @@ - hello dashboard + + + + + + + +

Counter:

+
+ + + + +
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..62fa57253ff --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js @@ -0,0 +1,19 @@ +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: true + } + }, + }; +} 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..b1bb5acc1a2 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml @@ -0,0 +1,11 @@ + + + +
+
+ +
+
+
+ +
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..45265fd3581 --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.js @@ -0,0 +1,54 @@ +import { Component, onMounted, onPatched, onWillStart, onWillUnmount, useRef, useState } from "@odoo/owl" +import { loadJS } from "@web/core/assets"; +import { getColor } from "@web/core/colors/colors"; + + +export class PieChart extends Component { + static template = "awesome_dashboard.pie_chart" + static props = { + data: Object, + optional: true + } + + setup() { + onWillStart(async () => { + await loadJS("/web/static/lib/Chart/Chart.js") + }) + + this.canvasRef = useRef("canvas"); + + if (this.props.data) { + onMounted(() => { + this.renderChart() + }) + + onPatched(() => { + this.chart.destroy() + this.renderChart() + }) + + onWillUnmount(() => { + this.chart.destroy() + }); + } + } + + renderChart() { + const keys = Object.keys(this.props.data) + const values = Object.values(this.props.data) + const colors = keys.map((_, index) => getColor(index)); + + this.chart = new Chart(this.canvasRef.el, { + type: "pie", + data: { + labels: keys, + datasets: [ + { + backgroundColor: colors, + data: values, + }, + ] + } + }); + } +} 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..09b6f9835f7 --- /dev/null +++ b/awesome_dashboard/static/src/pie_chart/pie_chart.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/awesome_dashboard/static/src/statistics_service.js b/awesome_dashboard/static/src/statistics_service.js new file mode 100644 index 00000000000..48d5ea2fb31 --- /dev/null +++ b/awesome_dashboard/static/src/statistics_service.js @@ -0,0 +1,22 @@ +import { registry } from "@web/core/registry"; +import { rpc } from "@web/core/network/rpc"; +import { reactive } from "@odoo/owl"; + + +const statisticsService = { + start() { + let stats = reactive({}) + + async function getStats() { + let updates = await rpc("/awesome_dashboard/statistics"); + Object.assign(stats, updates); + } + + getStats() + setInterval(getStats, 10*1000) + + return stats + } +} + +registry.category("services").add("awesome_dashboard.statistics", statisticsService); diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js new file mode 100644 index 00000000000..5260a66fb58 --- /dev/null +++ b/awesome_owl/static/src/card/card.js @@ -0,0 +1,25 @@ +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({ + state: false, + }) + } + + toggleState() { + this.state.state = !this.state.state; + } +} diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml new file mode 100644 index 00000000000..85b728a00fe --- /dev/null +++ b/awesome_owl/static/src/card/card.xml @@ -0,0 +1,17 @@ + + + +
+
+
+ + +
+

+ +

+
+
+
+ +
diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js new file mode 100644 index 00000000000..3289fd964ef --- /dev/null +++ b/awesome_owl/static/src/counter/counter.js @@ -0,0 +1,21 @@ +import { Component, useState } from "@odoo/owl"; + + +export class Counter extends Component { + static template = "awesome_owl.counter"; + static prop = { + onChange: { + type: Function, + optional: true, + }, + } + + setup() { + this.state = useState({ value: 0 }); + } + + increment() { + this.state.value++; + if (this.props.onChange) { this.props.onChange(); } + } +} diff --git a/awesome_owl/static/src/counter/counter.xml b/awesome_owl/static/src/counter/counter.xml new file mode 100644 index 00000000000..c5d85afe20c --- /dev/null +++ b/awesome_owl/static/src/counter/counter.xml @@ -0,0 +1,10 @@ + + + +
+

Counter:

+ +
+
+ +
diff --git a/awesome_owl/static/src/main.js b/awesome_owl/static/src/main.js index 1aaea902b55..6c108687e29 100644 --- a/awesome_owl/static/src/main.js +++ b/awesome_owl/static/src/main.js @@ -9,4 +9,3 @@ const config = { // 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 4ac769b0aa5..53bc34c32d3 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,5 +1,17 @@ -import { Component } from "@odoo/owl"; +import {Component, useState} from "@odoo/owl"; +import { Card } from "./card/card"; +import { Counter } from "./counter/counter"; +import { TodoList } from "./todo/todo_list"; export class Playground extends Component { static template = "awesome_owl.playground"; + static components = { Counter, Card, TodoList }; + + setup() { + this.sum = useState({ value: 0 }); + } + + incrementSum() { + this.sum.value++ + } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 4fb905d59f9..0dc4b3d5e4d 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -4,6 +4,18 @@
hello world + + +
The sum is:
+ + + + + +
some content
+
+ +
diff --git a/awesome_owl/static/src/todo/todo_item.js b/awesome_owl/static/src/todo/todo_item.js new file mode 100644 index 00000000000..fd63fcba41c --- /dev/null +++ b/awesome_owl/static/src/todo/todo_item.js @@ -0,0 +1,37 @@ +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, + } + }, + toggleState: { + type: Function, + optional: true + }, + + deleteTodo: { + type: Function, + optional: true + } + }; + + onChange() { + if (this.props.toggleState) { + this.props.toggleState(this.props.todo.id); + } + } + + onRemove() { + if (this.props.deleteTodo) { + this.props.deleteTodo(this.props.todo.id) + } + } +} diff --git a/awesome_owl/static/src/todo/todo_item.xml b/awesome_owl/static/src/todo/todo_item.xml new file mode 100644 index 00000000000..19beb0d32ff --- /dev/null +++ b/awesome_owl/static/src/todo/todo_item.xml @@ -0,0 +1,15 @@ + + + + +
+ + +
+
+ +
diff --git a/awesome_owl/static/src/todo/todo_list.js b/awesome_owl/static/src/todo/todo_list.js new file mode 100644 index 00000000000..727a1f3d434 --- /dev/null +++ b/awesome_owl/static/src/todo/todo_list.js @@ -0,0 +1,41 @@ +import { Component, useState } from "@odoo/owl" +import { TodoItem } from "./todo_item"; +import { Autofocus } from "../utils"; + + +export class TodoList extends Component { + static template = "awesome_owl.todo_list"; + static components = { TodoItem }; + + setup() { + this.nextId = 0; + this.todos = useState([]); + Autofocus("input") + } + + addTodo(event) { + if (event.key === 'Enter' && event.target.value !== '') { + this.todos.push({ + id: this.nextId++, + description: event.target.value, + isCompleted: false + }); + + event.target.value = ''; + } + } + + listToggleComplete(itemId) { + const todoItem = this.todos.find(item => item.id === itemId); + if (todoItem) { + todoItem.isCompleted = !todoItem.isCompleted; + } + } + + removeTodo(itemId) { + const todoIndex = this.todos.findIndex((todo) => todo.id === itemId); + if (todoIndex >= 0) { + this.todos.splice(todoIndex, 1); + } + } +} diff --git a/awesome_owl/static/src/todo/todo_list.xml b/awesome_owl/static/src/todo/todo_list.xml new file mode 100644 index 00000000000..6366d399b6c --- /dev/null +++ b/awesome_owl/static/src/todo/todo_list.xml @@ -0,0 +1,15 @@ + + + + +
+ +
+ + + +
+
+
+ +
diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js new file mode 100644 index 00000000000..696db80c603 --- /dev/null +++ b/awesome_owl/static/src/utils.js @@ -0,0 +1,10 @@ +import { onMounted, useRef } from "@odoo/owl" + + +export function Autofocus(refName) { + const ref = useRef(refName); + + onMounted(() => { + ref.el.focus() + }) +}