Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a6ef0c0
[ADD] Estate: Chapter 2 & 3
adpaw-odoo Mar 10, 2026
09c816f
[IMP] Estate: Fixed issues and completed Chapter 4
adpaw-odoo Mar 11, 2026
85a7c03
[IMP] Estate: Completed 2 sections in chapter-5
adpaw-odoo Mar 12, 2026
94a540e
[IMP] Estate: Completed chapter 5
adpaw-odoo Mar 13, 2026
8521ee9
[FIX] estate: fixed the issues
adpaw-odoo Mar 16, 2026
5b1412b
[IMP] estate: Fixed issues and completed chapter 6
adpaw-odoo Mar 16, 2026
a7fc97b
[IMP] Estate: Partially completed chapter 7
adpaw-odoo Mar 17, 2026
68e69b0
[IMP] Estate: Completed Chapter-7
adpaw-odoo Mar 18, 2026
8e1e942
[IMP] estate: Partially completed Chapter 8
adpaw-odoo Mar 30, 2026
a6d7c9c
[IMP] estate: Completed Ch. 8
adpaw-odoo Apr 3, 2026
6d7d356
[IMP] estate: Completed Ch 9
adpaw-odoo Apr 4, 2026
06e7242
[IMP] estate: Ch 10- constraints
adpaw-odoo Apr 6, 2026
650aee2
[IMP] estate: Ch 11, partial completion
adpaw-odoo Apr 7, 2026
d337495
[IMP] estate: complete chapter 11 and extra task
adpaw-odoo Apr 10, 2026
cef3ce1
[IMP] estate:Completed Ch. 12
adpaw-odoo Apr 13, 2026
7159ec2
[IMP] estate: Completed group task
adpaw-odoo Apr 14, 2026
39aea92
[IMP] estate : Completed Group Task
adpaw-odoo Apr 16, 2026
846157e
[ADD] estate_account: Add new bridge module
adpaw-odoo Apr 16, 2026
eb3e740
[IMP] estate : Chapter 14 completed
adpaw-odoo Apr 16, 2026
abeb835
[IMP] estate : Improvements
adpaw-odoo Apr 17, 2026
dc83a25
[ADD] estate_crm : added a new module
adpaw-odoo May 7, 2026
0b3c70c
[IMP] Awesome_owl : Completed Ch1 of owl framework.
adpaw-odoo May 8, 2026
509c7f4
[IMP] Awesome_owl : Completed Ch1 of owl framework.
adpaw-odoo May 8, 2026
70cca2e
[IMP] awesome_dashboard: OWL Chapter 2 completed
adpaw-odoo May 9, 2026
c9e3259
[IMP] estate: Added multiple user groups
adpaw-odoo May 15, 2026
cc13eb6
[ADD] second_uom: Cashier can add second uom white check out
adpaw-odoo May 15, 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
3 changes: 3 additions & 0 deletions awesome_dashboard/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
'web.assets_backend': [
'awesome_dashboard/static/src/**/*',
],
'awesome_dashboard.dashboard': [
'awesome_dashboard/static/src/dashboard/**/*'
]
},
'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.

102 changes: 102 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
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";
import "./statistics_service"; // ← add this
import "./dashboard_items"; // ← add this ← THIS IS THE FIX

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

setup() {
this.action = useService("action");
this.dialog = useService("dialog");
this.display = { controlPanel: {} };
this.stats = useService("awesome_dashboard.statistics");

this.state = useState({
disabledItems: JSON.parse(
browser.localStorage.getItem("disabledDashboardItems") || "[]"
)
});

this.allItems = registry
.category("awesome_dashboard.items")
.getAll();
}

get items() {
return this.allItems.filter(
item => !this.state.disabledItems.includes(item.id)
);
}

openConfiguration() {
this.dialog.add(ConfigurationDialog, {
items: this.allItems,
disabledItems: this.state.disabledItems,
onUpdate: this.updateConfiguration.bind(this),
});
}

updateConfiguration(newDisabledItems) {
this.state.disabledItems = newDisabledItems;
browser.localStorage.setItem(
"disabledDashboardItems",
JSON.stringify(newDisabledItems)
);
}

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"]],
});
}
}

class ConfigurationDialog extends Component {
static template = "awesome_dashboard.ConfigurationDialog";
static components = { Dialog, CheckBox };
static props = ["close", "items", "disabledItems", "onUpdate"];

setup() {
const disabled = Array.isArray(this.props.disabledItems)
? this.props.disabledItems
: [];

this.items = useState(
this.props.items.map(item => ({
...item,
enabled: !disabled.includes(item.id),
}))
);
}

onChange(checked, item) {
item.enabled = checked;
const disabled = this.items
.filter(i => !i.enabled)
.map(i => i.id);
this.props.onUpdate(disabled);
}

done() {
this.props.close();
}
}

registry
.category("lazy_components")
.add("awesome_dashboard.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: rgb(16, 18, 20);
}
60 changes: 60 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-name="awesome_dashboard.AwesomeDashboard">
<Layout display="{ controlPanel: {} }" className="'o_dashboard'">
<t t-set-slot="layout-buttons">
<button class="btn btn-primary me-2" t-on-click="openCustomers">
Customers
</button>

<button class="btn btn-primary" t-on-click="openLeads">
Leads
</button>
</t>

<t t-set-slot="control-panel-additional-actions">
<button class="btn btn-secondary fa fa-cog"
t-on-click="openConfiguration"/>
</t>

<div t-if="stats" class="d-flex flex-wrap gap-3">
<t t-foreach="items" t-as="item" t-key="item.id">
<DashboardItem size="item.size || 1">
<t t-set="itemProps"
t-value="item.props ? item.props(stats) : { data: stats }"/>

<!-- uppercase Component ✅ -->
<t t-component="item.Component"
t-props="itemProps"/>

</DashboardItem>
</t>
</div>
</Layout>
</t>

<t t-name="awesome_dashboard.ConfigurationDialog">
<Dialog title="'Dashboard Configuration'">
<div class="p-3">
<p>Which cards do you want to see?</p>
<t t-foreach="items" t-as="item" t-key="item.id">
<CheckBox
value="item.enabled"
onChange="(checked) => this.onChange(checked, item)">
<span>
<t t-esc="item.description"/>
</span>
</CheckBox>
</t>
</div>

<t t-set-slot="footer">
<button class="btn btn-primary" t-on-click="done">
Done
</button>
</t>
</Dialog>
</t>

</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component } from "@odoo/owl";

export class DashboardItem extends Component {
static template = "awesome_dashboard.DashboardItem";

static slots = {
default: {},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="awesome_dashboard.DashboardItem">
<div class="p-3 border bg-white" t-att-style="'width: ' + (18 * props.size) + 'rem;'">
<t t-slot="default"/>
</div>
</t>
</templates>
70 changes: 70 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard_items.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { dashboardItemRegistry } from "./dashboard_registry";
import { NumberCard } from "./number_card/number_card";
import { PieChartCard } from "./pie_chart_card/pie_chart_card";
import { _t } from "@web/core/l10n/translation";

dashboardItemRegistry.add("avg_quantity", {
id: "avg_quantity",
description: _t("Average amount of t-shirt"),
Component: NumberCard,
size: 1,
props: (data) => ({
title: _t("Average amount of t-shirt by order this month"),
value: data?.average_quantity || 0,
}),
});

dashboardItemRegistry.add("average_time", {
id: "average_time",
description: _t("Average time new to sent/cancelled"),
Component: NumberCard,
size: 1,
props: (data) => ({
title: _t("Average time for an order to go from 'new' to 'sent' or 'cancelled'"),
value: data?.average_time || 0,
}),
});

dashboardItemRegistry.add("new_orders", {
id: "new_orders",
description: _t("New orders this month"),
Component: NumberCard,
size: 1,
props: (data) => ({
title: _t("Number of new orders this month"),
value: data?.nb_new_orders || 0,
}),
});

dashboardItemRegistry.add("nb_cancelled_orders", {
id: "nb_cancelled_orders",
description: _t("Cancelled orders this month"),
Component: NumberCard,
size: 1,
props: (data) => ({
title: _t("Number of cancelled orders this month"),
value: data?.nb_cancelled_orders || 0,
}),
});

dashboardItemRegistry.add("total_amount", {
id: "total_amount",
description: _t("Total amount orders this month"),
Component: NumberCard,
size: 1,
props: (data) => ({
title: _t("Total amount of new orders this month"),
value: data?.total_amount || 0,
}),
});

dashboardItemRegistry.add("pie_chart", {
id: "pie_chart",
description: _t("Shirt orders by size"),
Component: PieChartCard,
size: 2,
props: (data) => ({
title: _t("Shirt orders by size"),
data: data?.orders_by_size || {},
}),
});
3 changes: 3 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard_registry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { registry } from "@web/core/registry";

export const dashboardItemRegistry = registry.category("awesome_dashboard.items");
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component } from "@odoo/owl";

export class NumberCard extends Component {
static template = "awesome_dashboard.NumberCard";
static props = {
title: String,
value: { type: Number, optional: true },
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<templates xml:space="preserve">
<t t-name="awesome_dashboard.NumberCard">
<div>
<div><t t-esc="props.title"/></div>
<h3><t t-esc="props.value"/></h3>
</div>
</t>
</templates>
34 changes: 34 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,34 @@
import { Component, onWillStart, onMounted, useRef } from "@odoo/owl";
import { loadJS } from "@web/core/assets";

export class PieChart extends Component {
static template = "awesome_dashboard.PieChart";

static props = {
data: Object,
};

setup() {
this.canvasRef = useRef("chart");
onWillStart(async () => {
await loadJS("/web/static/lib/Chart/Chart.js");
});
onMounted(() => {
this.renderChart();
});
}

renderChart() {
const ctx = this.canvasRef.el.getContext("2d");

new Chart(ctx, {
type: "pie",
data: {
labels: Object.keys(this.props.data),
datasets: [{
data: Object.values(this.props.data),
}],
},
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="awesome_dashboard.PieChart">
<canvas t-ref="chart" style="max-width: 300px;"/>
</t>
</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Component } from "@odoo/owl";
import { PieChart } from "../pie_chart/pie_chart";

export class PieChartCard extends Component {
static template = "awesome_dashboard.PieChartCard";
static components = { PieChart }
static props = {
title: String,
data: Object,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="awesome_dashboard.PieChartCard">
<div>
<div><t t-esc="props.title"/></div>
<PieChart data="props.data"/>
</div>
</t>
</templates>
24 changes: 24 additions & 0 deletions awesome_dashboard/static/src/dashboard/statistics_service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { registry } from "@web/core/registry";
import { rpc } from "@web/core/network/rpc";
import { reactive } from "@odoo/owl";

const statisticsService = {
name: "awesome_dashboard.statistics",

start() {
const stats = reactive({});

async function loadStatistics() {
const data = await rpc("/awesome_dashboard/statistics");
Object.assign(stats, data);
}

loadStatistics();
setInterval(loadStatistics, 10 * 60 * 1000);
return stats;
},
};

registry
.category("services")
.add("awesome_dashboard.statistics", statisticsService);
Loading