diff --git a/awesome_clicker/static/src/click_value/click_value.js b/awesome_clicker/static/src/click_value/click_value.js
new file mode 100644
index 00000000000..ecfa780a6e0
--- /dev/null
+++ b/awesome_clicker/static/src/click_value/click_value.js
@@ -0,0 +1,18 @@
+import { Component } from "@odoo/owl";
+import { useClicker } from "../clicker_hook";
+import { humanNumber } from "@web/core/utils/numbers"
+
+export class ClickValue extends Component {
+ static template = "awesome_clicker.ClickValue";
+ static props = {};
+
+ setup() {
+ this.clicker = useClicker()
+ }
+
+ get humanVal() {
+ return humanNumber(this.clicker.count.clicks, {
+ decimals: 1,
+ });
+ }
+}
diff --git a/awesome_clicker/static/src/click_value/click_value.xml b/awesome_clicker/static/src/click_value/click_value.xml
new file mode 100644
index 00000000000..8a1f150a072
--- /dev/null
+++ b/awesome_clicker/static/src/click_value/click_value.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/awesome_clicker/static/src/clicker_hook.js b/awesome_clicker/static/src/clicker_hook.js
new file mode 100644
index 00000000000..4fdaeb40980
--- /dev/null
+++ b/awesome_clicker/static/src/clicker_hook.js
@@ -0,0 +1,6 @@
+import { useService } from "@web/core/utils/hooks";
+import { useState } from "@odoo/owl";
+
+export function useClicker() {
+ return useState(useService("awesome_clicker.clicker"));
+}
\ 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..aee2d803c42
--- /dev/null
+++ b/awesome_clicker/static/src/clicker_service.js
@@ -0,0 +1,22 @@
+import { registry } from "@web/core/registry";
+import { reactive } from "@odoo/owl";
+
+export const clickerService = {
+ start() {
+
+ const count = reactive({ clicks: 0 });
+
+ function increment(c) {
+ count.clicks+= c;
+ }
+
+ document.addEventListener("click", () => increment(1), true);
+
+ return {
+ count,
+ increment,
+ };
+ },
+};
+
+registry.category("services").add("awesome_clicker.clicker", clickerService);
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..bbcf9b8d2b5
--- /dev/null
+++ b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.js
@@ -0,0 +1,35 @@
+import { registry } from "@web/core/registry";
+import { Component } from "@odoo/owl";
+import { useService } from "@web/core/utils/hooks";
+import { useClicker } from "../clicker_hook";
+import { ClickValue } from "../click_value/click_value";
+
+export class ClickerSystray extends Component {
+
+ static template = "awesome_clicker.ClickerSystray";
+ static props = {};
+ static components = {
+ ClickValue,
+ }
+
+ setup() {
+ this.action = useService("action");
+ this.clicker = useClicker()
+ }
+
+ openClientAction() {
+ this.action.doAction({
+ type: "ir.actions.client",
+ tag: "awesome_clicker.client_action",
+ target: "new",
+ name: "Clicker Game"
+ });
+ }
+
+}
+
+export const systrayItem = {
+ Component: ClickerSystray,
+};
+
+registry.category("systray").add("awesome_clicker.ClickerSystray", systrayItem, { sequence: 1000 });
\ 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..b1b4b6172bc
--- /dev/null
+++ b/awesome_clicker/static/src/clicker_systray_item/clicker_systray_item.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ Clicks:
+
+
+
+
+
\ No newline at end of file
diff --git a/awesome_clicker/static/src/clicker_systray_item/client_action.js b/awesome_clicker/static/src/clicker_systray_item/client_action.js
new file mode 100644
index 00000000000..f2e1d608e4a
--- /dev/null
+++ b/awesome_clicker/static/src/clicker_systray_item/client_action.js
@@ -0,0 +1,19 @@
+import { registry } from "@web/core/registry";
+import { Component } from "@odoo/owl";
+import { useClicker } from "../clicker_hook";
+import { ClickValue } from "../click_value/click_value";
+
+export class ClientAction extends Component {
+ static template = "awesome_clicker.ClientAction";
+ 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/clicker_systray_item/client_action.xml b/awesome_clicker/static/src/clicker_systray_item/client_action.xml
new file mode 100644
index 00000000000..c27778cbf83
--- /dev/null
+++ b/awesome_clicker/static/src/clicker_systray_item/client_action.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ Clicks:
+
+
+
+
\ No newline at end of file
diff --git a/awesome_dashboard/__manifest__.py b/awesome_dashboard/__manifest__.py
index 31406e8addb..e2363aef60b 100644
--- a/awesome_dashboard/__manifest__.py
+++ b/awesome_dashboard/__manifest__.py
@@ -24,6 +24,10 @@
'assets': {
'web.assets_backend': [
'awesome_dashboard/static/src/**/*',
+ ('remove', 'awesome_dashboard/static/src/dashboard**/*'),
+ ],
+ 'awesome_dashboard.dashboard': [
+ 'awesome_dashboard/static/src/dashboard/**/*'
],
},
'license': 'AGPL-3'
diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js
deleted file mode 100644
index 637fa4bb972..00000000000
--- a/awesome_dashboard/static/src/dashboard.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/** @odoo-module **/
-
-import { Component } from "@odoo/owl";
-import { registry } from "@web/core/registry";
-
-class AwesomeDashboard extends Component {
- static template = "awesome_dashboard.AwesomeDashboard";
-}
-
-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 1a2ac9a2fed..00000000000
--- a/awesome_dashboard/static/src/dashboard.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- hello dashboard
-
-
-
diff --git a/awesome_dashboard/static/src/dashboard/dashboard.js b/awesome_dashboard/static/src/dashboard/dashboard.js
new file mode 100644
index 00000000000..328c9db4d5b
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/dashboard.js
@@ -0,0 +1,96 @@
+/** @odoo-module **/
+
+import { Component, useState } from "@odoo/owl";
+import { registry } from "@web/core/registry";
+import { Layout } from "@web/search/layout";
+import { useService } from "@web/core/utils/hooks";
+import { DashboardItem } from "./dashboard_item/dashboard_item";
+import { Dialog } from "@web/core/dialog/dialog";
+import { CheckBox } from "@web/core/checkbox/checkbox";
+import { browser } from "@web/core/browser/browser";
+
+class AwesomeDashboard extends Component {
+ static template = "awesome_dashboard.AwesomeDashboard";
+ static components = {
+ Layout,
+ DashboardItem,
+ };
+
+ static props = {
+ display : {
+ controlPanel: {}
+ },
+ }
+
+ setup() {
+ this.action = useService("action");
+ this.result = useState(useService("awesome_dashboard.getStats"));
+ this.dialog = useService("dialog");
+ this.items = registry.category("awesome_dashboard").getAll();
+ this.state = useState({
+ disabledItems: browser.localStorage.getItem("disabledDashboardItems")?.split(",") || []
+ });
+ }
+
+ openConfiguration() {
+ this.dialog.add(ConfigurationDialog, {
+ items: this.items,
+ disabledItems: this.state.disabledItems,
+ onUpdateConfiguration: this.updateConfiguration.bind(this),
+ })
+ }
+
+ updateConfiguration(newDisabledItems) {
+ this.state.disabledItems = newDisabledItems;
+ }
+
+ openCustomerKanban() {
+ this.action.doAction("base.action_partner_form");
+ }
+
+ async openActivity() {
+ this.action.doAction({
+ type: 'ir.actions.act_window',
+ name: 'Leads',
+ target: 'current',
+ res_model: 'crm.lead',
+ views: [[false, 'list'], [false, 'form']],
+ });
+ }
+}
+
+class ConfigurationDialog extends Component {
+ static template = "awesome_dashboard.ConfigurationDialog";
+ static components = { Dialog, CheckBox };
+ static props = ["close", "items", "disabledItems", "onUpdateConfiguration"];
+
+ setup() {
+ this.items = useState(this.props.items.map((item) => {
+ return {
+ ...item,
+ enabled: !this.props.disabledItems.includes(item.id),
+ }
+ }));
+ }
+
+ done() {
+ this.props.close();
+ }
+
+ onChange(checked, changedItem) {
+ changedItem.enabled = checked;
+ const newDisabledItems = Object.values(this.items).filter(
+ (item) => !item.enabled
+ ).map((item) => item.id)
+
+ browser.localStorage.setItem(
+ "disabledDashboardItems",
+ newDisabledItems,
+ );
+
+ this.props.onUpdateConfiguration(newDisabledItems);
+ }
+
+}
+
+registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard);
diff --git a/awesome_dashboard/static/src/dashboard/dashboard.scss b/awesome_dashboard/static/src/dashboard/dashboard.scss
new file mode 100644
index 00000000000..845518d2a75
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/dashboard.scss
@@ -0,0 +1,7 @@
+.o_dashboard {
+ background-color: grey;
+}
+
+.myBtnChange {
+ margin: 2rem;
+}
diff --git a/awesome_dashboard/static/src/dashboard/dashboard.xml b/awesome_dashboard/static/src/dashboard/dashboard.xml
new file mode 100644
index 00000000000..a158437e6d1
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/dashboard.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.js b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.js
new file mode 100644
index 00000000000..235cc6fe68d
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/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,
+ optional: true,
+ },
+ }
+
+ static defaultProps = {
+ size: 1
+ }
+}
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..e7e1b959618
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.scss
@@ -0,0 +1,7 @@
+.box {
+ border: 30px black;
+ // border-color: black;
+ border-radius: 10px;
+ background-color: white;
+ margin: 1rem;
+}
diff --git a/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml
new file mode 100644
index 00000000000..0a5573ba3eb
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
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..4532ee3a413
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/dashboard_items.js
@@ -0,0 +1,65 @@
+import { NumberCard } from "./number_card/number_card";
+import { PieChartCard } from "./pie_chart_card/pie_chart_card";
+import { registry } from "@web/core/registry"
+
+const items = [
+ {
+ id: "average_quantity",
+ description: "Average amount of t-shirt",
+ Component: NumberCard,
+ 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: "number_new_orders",
+ description: "New orders this month",
+ Component: NumberCard,
+ props: (data) => ({
+ title: "Number of new orders this month",
+ value: data.nb_new_orders,
+ })
+ },
+ {
+ id: "cancelled_orders",
+ description: "Cancelled orders this month",
+ Component: NumberCard,
+ props: (data) => ({
+ title: "Number of cancelled orders this month",
+ value: data.nb_cancelled_orders,
+ })
+ },
+ {
+ id: "amount_new_orders",
+ description: "amount orders this month",
+ Component: NumberCard,
+ props: (data) => ({
+ title: "Total amount of new orders this month",
+ value: data.total_amount,
+ })
+ },
+ {
+ id: "pie_chart",
+ description: "Shirt orders by size",
+ Component: PieChartCard,
+ size: 1,
+ props: (data) => ({
+ title: "Shirt orders by size",
+ values: data.orders_by_size,
+ })
+ }
+]
+
+items.forEach(item => {
+ registry.category("awesome_dashboard").add(item.id, item);
+});
diff --git a/awesome_dashboard/static/src/dashboard/get_statistics.js b/awesome_dashboard/static/src/dashboard/get_statistics.js
new file mode 100644
index 00000000000..238a1a58d3b
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/get_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 getStatistics = {
+ async start() {
+ const statistics = reactive({ isReady: false });
+
+ async function loadData() {
+ const updates = await rpc("/awesome_dashboard/statistics");
+ Object.assign(statistics, updates, { isReady: true });
+ }
+
+ setInterval(loadData, 30*1000);
+ loadData();
+
+ return statistics;
+ },
+};
+
+registry.category("services").add("awesome_dashboard.getStats", getStatistics);
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..d3bd9c0e4ef
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/number_card/number_card.js
@@ -0,0 +1,13 @@
+import { Component } from "@odoo/owl";
+
+export class NumberCard extends Component {
+ static template = "awesome_dashboard.NumberCard";
+ static props = {
+ title: {
+ type: String,
+ },
+ value: {
+ type: Number,
+ }
+ }
+}
\ No newline at end of file
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..73bc3cac926
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/number_card/number_card.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js
new file mode 100644
index 00000000000..a273255e63d
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js
@@ -0,0 +1,36 @@
+import { Component, onWillStart, useRef, onMounted, useState } from "@odoo/owl";
+import { loadJS } from "@web/core/assets";
+
+export class PieChart extends Component {
+ static template = "awesome_dashboard.PieChart";
+
+ static props = {
+ label: String,
+ data: Object,
+ };
+
+ setup() {
+ this.canvasRef = useRef("canvas");
+ onWillStart(() => loadJS("/web/static/lib/Chart/Chart.js"));
+ onMounted(() => {
+ this.renderChart();
+ });
+ }
+
+ renderChart() {
+ const labels = Object.keys(this.props.data);
+ const data = Object.values(this.props.data);
+ this.chart = new Chart(this.canvasRef.el, {
+ type: "pie",
+ data: {
+ labels: labels,
+ datasets: [
+ {
+ label: this.props.label,
+ data: data,
+ },
+ ],
+ },
+ });
+ }
+}
diff --git a/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.xml b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.xml
new file mode 100644
index 00000000000..99711839c96
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
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..04dc61aa73a
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard/pie_chart_card/pie_chart_card.js
@@ -0,0 +1,15 @@
+import { Component } from "@odoo/owl";
+import { PieChart } from "../pie_chart/pie_chart";
+
+export class PieChartCard extends Component {
+ static template = "awesome_dashboard.PieChartCard";
+ static components = { PieChart }
+ static props = {
+ title: {
+ type: String,
+ },
+ values: {
+ type: Object,
+ },
+ }
+}
\ No newline at end of file
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..b8c94bebb64
--- /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/dashboard_loader.js b/awesome_dashboard/static/src/dashboard_loader.js
new file mode 100644
index 00000000000..861cf1900ea
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard_loader.js
@@ -0,0 +1,15 @@
+import { registry } from "@web/core/registry";
+import { LazyComponent } from "@web/core/assets";
+import { Component, xml } from "@odoo/owl";
+
+class AwesomeDashboardLoader extends Component {
+
+ // static template = "awesome_dashboard.dashboardLoader";
+ static template = xml`
+ `
+ ;
+ static components = { LazyComponent };
+
+}
+
+registry.category("actions").add("awesome_dashboard.dashboard", AwesomeDashboardLoader);
diff --git a/awesome_dashboard/static/src/dashboard_loader.xml b/awesome_dashboard/static/src/dashboard_loader.xml
new file mode 100644
index 00000000000..ce002eadb47
--- /dev/null
+++ b/awesome_dashboard/static/src/dashboard_loader.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js
new file mode 100644
index 00000000000..873cea2c369
--- /dev/null
+++ b/awesome_owl/static/src/card/card.js
@@ -0,0 +1,21 @@
+import { Component, useState } from "@odoo/owl";
+
+export class Card extends Component {
+ static template = "awesome_owl.card";
+
+ static props = {
+ title: String,
+ slots: {
+ type: Object,
+ optional: true,
+ },
+ isOpen: Boolean,
+ }
+
+ state = useState({ isOpen: this.props.isOpen });
+
+ onToggleOpen(){
+ this.state.isOpen = !this.state.isOpen
+ console.log(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..af30d0312e0
--- /dev/null
+++ b/awesome_owl/static/src/card/card.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js
new file mode 100644
index 00000000000..f236f3f3131
--- /dev/null
+++ b/awesome_owl/static/src/counter/counter.js
@@ -0,0 +1,15 @@
+import { useState, Component } from "@odoo/owl";
+
+export class Counter extends Component {
+ static template = "awesome_owl.counter";
+ static props = {
+ incrementSum: {type: Function, optional: true},
+ }
+
+ state = useState({ value: 1 });
+
+ increment() {
+ this.state.value++;
+ this.props.incrementSum()
+ }
+}
diff --git a/awesome_owl/static/src/counter/counter.xml b/awesome_owl/static/src/counter/counter.xml
new file mode 100644
index 00000000000..bacf49c6f3b
--- /dev/null
+++ b/awesome_owl/static/src/counter/counter.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ hello world :
+
+
+
+
+
+
+
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js
index 657fb8b07bb..730020c448a 100644
--- a/awesome_owl/static/src/playground.js
+++ b/awesome_owl/static/src/playground.js
@@ -1,7 +1,24 @@
/** @odoo-module **/
-import { Component } from "@odoo/owl";
+import { Component, markup, useState } from "@odoo/owl";
+import { Counter } from "./counter/counter"
+import { Card } from "./card/card"
+import { TodoList } from "./todo_list/todo_list";
export class Playground extends Component {
static template = "awesome_owl.playground";
+ static components = {
+ Counter,
+ Card,
+ TodoList,
+ }
+
+ value1 = "
some content
";
+ value2 = markup("some content
");
+
+ state = useState({ sum: 2 });
+
+ incrementSum() {
+ this.state.sum++;
+ }
}
diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml
index 4fb905d59f9..6fc309350a1 100644
--- a/awesome_owl/static/src/playground.xml
+++ b/awesome_owl/static/src/playground.xml
@@ -2,9 +2,14 @@
+
+
- hello world
+ Total 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..2a0184d8a9b
--- /dev/null
+++ b/awesome_owl/static/src/todo_list/todo_item.js
@@ -0,0 +1,33 @@
+import { Component } from "@odoo/owl";
+
+export class TodoItem extends Component {
+ static template = "awesome_owl.TodoItem";
+
+ static props = {
+ item : {
+ type: Object,
+ shape: {
+ id: Number,
+ description: String,
+ isCompleted: Boolean,
+ }
+ },
+ toggleState : {
+ type: Function,
+ optional: true,
+ },
+ deleteTodo : {
+ type: Function,
+ optional: true,
+ }
+ }
+
+ onChangeCheck (id){
+ // this.props.toggleState(id)
+ this.props.item.isCompleted = !this.props.item.isCompleted
+ }
+
+ onClickDelete (id){
+ this.props.deleteTodo(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..5fe31891404
--- /dev/null
+++ b/awesome_owl/static/src/todo_list/todo_item.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ .
+
+
+
+
+
+
+
+
+
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..389a334ef4b
--- /dev/null
+++ b/awesome_owl/static/src/todo_list/todo_list.js
@@ -0,0 +1,42 @@
+import { Component, useState, useRef, onMounted } from "@odoo/owl";
+import { TodoItem } from "./todo_item";
+
+export class TodoList extends Component {
+ static template = "awesome_owl.TodoList";
+ static components = {
+ TodoItem,
+ }
+
+ todos = useState([]);
+ ids = 1
+
+ setup() {
+ this.myRef = useRef('myInput');
+ onMounted(() => {
+ this.myRef.el.focus()
+ });
+ }
+
+ addTodos(ev) {
+ if(ev.keyCode === 13) {
+ if(ev.target.value == "") return;
+ this.todos.push({
+ id: this.ids,
+ description: ev.target.value,
+ isCompleted: false,
+ })
+ this.ids++
+ ev.target.value = ""
+ }
+ }
+
+ toggleState(id){
+ let todo = this.todos.filter((todo) => todo.id == id)
+ todo[0].isCompleted = !todo[0].isCompleted
+ }
+
+ deleteTodo(id){
+ const index = this.todos.findIndex((elem) => elem.id === id);
+ if (index >= 0) 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..7d587141503
--- /dev/null
+++ b/awesome_owl/static/src/todo_list/todo_list.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+