Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d5d906d
[IMP] estate: Chapter 2
kiro6 Mar 16, 2026
cf959b4
[IMP] estate: Chapter 3
kiro6 Mar 16, 2026
b73e0fc
[IMP] estate: Chapter 3 & 4
kiro6 Mar 16, 2026
f204eee
[IMP] estate: Chapter 5
kiro6 Mar 16, 2026
f7ddc92
[IMP] estate: Chapter 6
kiro6 Mar 17, 2026
f03c6a5
[FIX] estate: Chapter 6
kiro6 Mar 17, 2026
22f9301
[IMP] estate: Chapter 7
kiro6 Mar 17, 2026
ac008cf
[IMP] estate: Chapter 8
kiro6 Mar 17, 2026
ee5fa5d
[IMP] estate: Chapter 9
kiro6 Mar 17, 2026
f93709c
[ADD] estate: Chapter 9
kiro6 Mar 17, 2026
f098761
[IMP] estate: Chapter 10
kiro6 Mar 17, 2026
01adb9c
[IMP] estate: Chapter 11
kiro6 Mar 18, 2026
83eac1d
[IMP] estate: Chapter 12
kiro6 Mar 18, 2026
883e229
[IMP] estate: Chapter 13
kiro6 Mar 18, 2026
cc76050
[IMP] estate: Chapter 14
kiro6 Mar 19, 2026
36e88af
[IMP] Owl: Chapter 1
kiro6 Mar 23, 2026
cb6ad2b
[FIX] estate: Styling
kiro6 Mar 23, 2026
d89fc64
[FIX] estate: Styling
kiro6 Mar 23, 2026
6e03d88
[IMP] Owl: Chapter 2
kiro6 Mar 24, 2026
91f476b
[FIX] estate
kiro6 Mar 24, 2026
9c4cdd7
[FIX] estate: estate.property.offer
kiro6 Mar 24, 2026
a97bded
[FIX] estate: cleanup manifest & fix duplicate property_ids label
kiro6 Mar 24, 2026
2d6e717
[FIX] estate_account: add license
kiro6 Mar 24, 2026
422f2b6
[FIX] estate: dublicte view ID
kiro6 Mar 25, 2026
cf8481b
[IMP] Restrict access to data
kiro6 Mar 26, 2026
921ebe0
[IMP] unit tests
kiro6 Mar 26, 2026
b73ea4f
[FIX] unit tests styling
kiro6 Mar 26, 2026
e7e1945
[IMP] Define module data
kiro6 Mar 27, 2026
a02e4d7
[FIX] Define module data
kiro6 Mar 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 22 additions & 20 deletions awesome_dashboard/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
# -*- coding: utf-8 -*-
{
'name': "Awesome Dashboard",

'summary': """
"name": "Awesome Dashboard",
"summary": """
Starting module for "Discover the JS framework, chapter 2: Build a dashboard"
""",

'description': """
"description": """
Starting module for "Discover the JS framework, chapter 2: Build a dashboard"
""",

'author': "Odoo",
'website': "https://www.odoo.com/",
'category': 'Tutorials',
'version': '0.1',
'application': True,
'installable': True,
'depends': ['base', 'web', 'mail', 'crm'],

'data': [
'views/views.xml',
"author": "Odoo",
"website": "https://www.odoo.com/",
"category": "Tutorials",
"version": "0.1",
"application": True,
"installable": True,
"depends": ["base", "web", "mail", "crm"],
"data": [
"views/views.xml",
],
'assets': {
'web.assets_backend': [
'awesome_dashboard/static/src/**/*',
"assets": {
"web.assets_backend": [
"awesome_dashboard/static/src/statistics_service.js",
"awesome_dashboard/static/src/dashboard_action.js",
],
"awesome_dashboard.dashboard": [
"awesome_dashboard/static/src/dashboard/**/*.js",
"awesome_dashboard/static/src/dashboard/**/*.xml",
"awesome_dashboard/static/src/dashboard/**/*.scss",
],
},
'license': 'AGPL-3'
"license": "AGPL-3",
}
8 changes: 0 additions & 8 deletions awesome_dashboard/static/src/dashboard.js

This file was deleted.

8 changes: 0 additions & 8 deletions awesome_dashboard/static/src/dashboard.xml

This file was deleted.

19 changes: 19 additions & 0 deletions awesome_dashboard/static/src/dashboard/card/card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Component } from "@odoo/owl";
import { PieChart } from "../pie_chart/pie_chart";

export class NumberCard extends Component {
static template = "awesome_dashboard.NumberCard";
static props = {
title: String,
value: [Number, String],
};
}

export class PieChartCard extends Component {
static components = { PieChart };
static template = "awesome_dashboard.PieChartCard";
static props = {
data: Object,
title: String,
};
}
15 changes: 15 additions & 0 deletions awesome_dashboard/static/src/dashboard/card/card.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<templates xml:space="preserve">
<t t-name="awesome_dashboard.NumberCard">
<div class="h-100 d-flex flex-column align-items-center justify-content-center">
<div class="text-muted text-uppercase fw-bold"><t t-esc="props.title"/></div>
<div class="display-4 fw-bold text-primary"><t t-esc="props.value"/></div>
</div>
</t>

<t t-name="awesome_dashboard.PieChartCard">
<div class="h-100 d-flex flex-column">
<div class="text-muted small mb-2"><t t-esc="props.title"/></div>
<PieChart data="props.data"/>
</div>
</t>
</templates>
63 changes: 63 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
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 { browser } from "@web/core/browser/browser";
import { DashboardSettingsDialog } from "./settings_dialog/settings_dialog"

class AwesomeDashboard extends Component {
static template = "awesome_dashboard.AwesomeDashboard";
static components = { Layout, DashboardItem, DashboardSettingsDialog }

setup() {
this.action = useService("action")
this.dialog = useService("dialog");

this.display = {
controlPanel: {
"layout-buttons": true
}
};

const statsService = useService("awesome_dashboard.statistics");
this.statistics = useState(statsService.statistics);

this.state = useState({
items: this.getFilteredItems()
});

}

openCustomers() {
this.action.doAction("base.action_partner_form");
}

openLeads() {
this.action.doAction({
type: "ir.actions.act_window",
name: "Leads",
res_model: "crm.lead",
views: [
[false, "list"],
[false, "form"],
],
});
}

getFilteredItems() {
const allItems = registry.category("awesome_dashboard").getAll();
const removedIds = JSON.parse(browser.localStorage.getItem("awesome_dashboard.removed_ids") || "[]");
return allItems.filter(item => !removedIds.includes(item.id));
}

openConfiguration() {
this.dialog.add(DashboardSettingsDialog, {
onConfigSaved: () => {
this.state.items = this.getFilteredItems();
}
});
}
}

registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard);
3 changes: 3 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.o_dashboard {
background-color: #6a7b8c;
}
24 changes: 24 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<templates xml:space="preserve">
<t t-name="awesome_dashboard.AwesomeDashboard">
<Layout display="display" className="'o_dashboard h-100'">
<t t-set-slot="layout-buttons">
<button t-on-click="openCustomers" class="btn btn-primary">Customers</button>
<button t-on-click="openLeads" class="btn btn-primary">Leads</button>
<button class="btn btn-outline-secondary" t-on-click="openConfiguration">
<i class="oi oi-settings"/> Settings
</button>
</t>
<div class="p-3">Hellooooooooooooooooooo.</div>
<div class="row m-0">
<t t-foreach="this.state.items" t-as="item" t-key="item.id">
<DashboardItem size="item.size || 1">
<t t-set="itemProps" t-value="item.props ? item.props(statistics) : { 'data': statistics }"/>

<t t-component="item.Component" t-props="itemProps" />
</DashboardItem>
</t>
</div>
</Layout>
</t>
</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Component } from "@odoo/owl";
import { NumberCard, PieChartCard } from "./../card/card";
import { registry } from "@web/core/registry";

export class DashboardItem extends Component {
static template = "awesome_dashboard.DashboardItem";
static props = {
size: { type: Number, optional: true },
slots: {
type: Object,
shape: {
default: Object,
},
},
};
static defaultProps = {
size: 1,
};
}

const dashboardRegistry = registry.category("awesome_dashboard");

dashboardRegistry.add("average_quantity", {
id: "average_quantity",
description: "Average amount of t-shirt",
Component: NumberCard,
size: 1,
props: (data) => ({
title: "Average quantity per order",
value: data.average_quantity,
}),
});

dashboardRegistry.add("average_time", {
id: "average_time",
description: "Average time",
Component: NumberCard,
size: 1,
props: (data) => ({
title: "Average Time",
value: data.average_time,
}),
});

dashboardRegistry.add("nb_cancelled_orders", {
id: "nb_cancelled_orders",
description: "Cancelled orders",
Component: NumberCard,
size: 1,
props: (data) => ({
title: "Cancelled Orders",
value: data.nb_cancelled_orders,
}),
});

dashboardRegistry.add("nb_new_orders", {
id: "nb_new_orders",
description: "New orders",
Component: NumberCard,
size: 1,
props: (data) => ({
title: "New Orders",
value: data.nb_new_orders,
}),
});

dashboardRegistry.add("total_amount", {
id: "total_amount",
description: "Total amount",
Component: NumberCard,
size: 1,
props: (data) => ({
title: "Total Amount",
value: `${data.total_amount} €`,
}),
});

dashboardRegistry.add("orders_by_size", {
id: "orders_by_size",
description: "Orders by size",
Component: PieChartCard,
size: 2,
props: (data) => ({
title: "T-Shirt Sizes",
data: data.orders_by_size,
}),
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="awesome_dashboard.DashboardItem">
<div class="m-2 shadow-sm border rounded bg-white p-3"
t-att-style="'width: ' + (18 * (props.size || 1)) + 'rem; height: 250px; flex-grow: 0; flex-shrink: 0;'">

<t t-slot="default"/>

</div>
</t>
</templates>
57 changes: 57 additions & 0 deletions awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Component, onWillStart, useRef, onMounted, onWillUnmount, useEffect } from "@odoo/owl";
import { loadJS } from "@web/core/assets";

export class PieChart extends Component {
static template = "awesome_dashboard.PieChart";
static props = {
data: { type: Object },
label: { type: String, optional: true },
};

setup() {
this.canvasRef = useRef("canvas");
this.chart = null;

onWillStart(async () => {
await loadJS("/web/static/lib/Chart/Chart.js");
});

onMounted(() => {
this.renderChart();
});

useEffect(() => {
if (this.chart) {
this.chart.data.labels = Object.keys(this.props.data);
this.chart.data.datasets[0].data = Object.values(this.props.data);
this.chart.update();
}
},
() => [this.props.data]
);

onWillUnmount(() => {
if (this.chart) {
this.chart.destroy();
}
});

}

renderChart() {
const config = {
type: 'pie',
data: {
labels: Object.keys(this.props.data),
datasets: [{
label: this.props.label || 'T-Shirt Sizes',
data: Object.values(this.props.data),
backgroundColor: [
'#ff6384', '#36a2eb', '#cc65fe', '#ffce56', '#4bc0c0'
],
}]
},
};
this.chart = new Chart(this.canvasRef.el, config);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<templates xml:space="preserve">
<t t-name="awesome_dashboard.PieChart">
<div class="chart-container" style="position: relative; height:20vh; width:40vw">
<canvas t-ref="canvas"></canvas>
</div>
</t>
</templates>
Loading