Skip to content

Commit 366739f

Browse files
author
Martin Doyen
committed
[IMP] awesome_dashboard: build a dashboard
1 parent f9db9f6 commit 366739f

17 files changed

+384
-20
lines changed

awesome_dashboard/__manifest__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,19 @@
1616
'version': '0.1',
1717
'application': True,
1818
'installable': True,
19-
'depends': ['base', 'web', 'mail', 'crm'],
19+
'depends': ['base', 'web', 'mail', 'crm', 'sale'],
2020

2121
'data': [
2222
'views/views.xml',
2323
],
2424
'assets': {
2525
'web.assets_backend': [
2626
'awesome_dashboard/static/src/**/*',
27+
('remove', 'awesome_dashboard/static/src/dashboard/**/*'),
28+
],
29+
'awesome_dashboard.dashboard': [
30+
'awesome_dashboard/static/src/dashboard/**/*',
2731
],
2832
},
29-
'license': 'AGPL-3'
33+
'license': 'AGPL-3',
3034
}

awesome_dashboard/static/src/dashboard.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

awesome_dashboard/static/src/dashboard.xml

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/** @odoo-module **/
2+
3+
import { _t } from "@web/core/l10n/translation";
4+
import { Component, useState } from "@odoo/owl";
5+
import { registry } from "@web/core/registry";
6+
import { Layout } from "@web/search/layout";
7+
import { PieChart } from "./pie_chart/pie_chart";
8+
import { DashboardItem } from "./dashboard_item";
9+
import { useService } from "@web/core/utils/hooks";
10+
import { Dialog } from "@web/core/dialog/dialog";
11+
import { CheckBox } from "@web/core/checkbox/checkbox";
12+
import { browser } from "@web/core/browser/browser";
13+
14+
class AwesomeDashboard extends Component {
15+
static template = "awesome_dashboard.AwesomeDashboard";
16+
static components = { DashboardItem, Layout, PieChart };
17+
18+
setup() {
19+
this.action = useService("action");
20+
this.stats = useState(useService("awesome_dashboard.statistics"));
21+
this.items = registry.category("awesome_dashboard").getAll();
22+
this.dialog = useService("dialog");
23+
this.state = useState({
24+
disabledItems: browser.localStorage.getItem("disabledDashboardItems")?.split(",") || []
25+
})
26+
}
27+
28+
openCustomers() {
29+
this.action.doAction("base.action_partner_form");
30+
}
31+
32+
openLeads() {
33+
this.action.doAction({
34+
type: 'ir.actions.act_window',
35+
name: _t('All leads'),
36+
res_model: 'crm.lead',
37+
views: [
38+
[false, 'list'],
39+
[false, 'form'],
40+
],
41+
});
42+
}
43+
44+
openConfiguration() {
45+
this.dialog.add(ConfigurationDialog, {
46+
items: this.items,
47+
disabledItems: this.state.disabledItems,
48+
onUpdateConfiguration: this.updateConfiguration.bind(this),
49+
})
50+
}
51+
52+
updateConfiguration(newDisabledItems) {
53+
this.state.disabledItems = newDisabledItems;
54+
}
55+
}
56+
57+
class ConfigurationDialog extends Component {
58+
static template = "awesome_dashboard.ConfigurationDialog";
59+
static components = { Dialog, CheckBox };
60+
static props = ["close", "items", "disabledItems", "onUpdateConfiguration"];
61+
62+
setup() {
63+
this.items = useState(this.props.items.map((item) => {
64+
return {
65+
...item,
66+
enabled: !this.props.disabledItems.includes(item.id),
67+
}
68+
}));
69+
}
70+
71+
done() {
72+
this.props.close();
73+
}
74+
75+
onChange(checked, changedItem) {
76+
changedItem.enabled = checked;
77+
const newDisabledItems = Object.values(this.items).filter(
78+
(item) => !item.enabled
79+
).map((item) => item.id)
80+
81+
browser.localStorage.setItem(
82+
"disabledDashboardItems",
83+
newDisabledItems
84+
);
85+
86+
this.props.onUpdateConfiguration(newDisabledItems);
87+
}
88+
}
89+
90+
registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.o_dashboard {
2+
background-color: gray;
3+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<templates xml:space="preserve">
3+
<t t-name="awesome_dashboard.AwesomeDashboard">
4+
<Layout className="'o_dashboard h-100'" display="{ controlPanel: {} }">
5+
<t t-set-slot="layout-buttons">
6+
<button class="btn btn-primary" t-on-click="openCustomers">Customers</button>
7+
<button class="btn btn-primary" t-on-click="openLeads">Leads</button>
8+
</t>
9+
<t t-set-slot="control-panel-additional-actions">
10+
<button t-on-click="openConfiguration" class="btn p-0 ms-1 border-0">
11+
<i class="fa fa-cog"></i>
12+
</button>
13+
</t>
14+
<div class="d-flex flex-wrap" t-if="stats.isReady">
15+
<t t-foreach="items" t-as="item" t-key="item.id">
16+
<DashboardItem t-if="!state.disabledItems.includes(item.id)" size="item.size || 1">
17+
<t t-set="itemProp" t-value="item.props ? item.props(stats) : {'data': stats}"/>
18+
<t t-component="item.Component" t-props="itemProp" />
19+
</DashboardItem>
20+
</t>
21+
</div>
22+
</Layout>
23+
</t>
24+
25+
<t t-name="awesome_dashboard.ConfigurationDialog">
26+
<Dialog title.translate="Dashboard items configuration">
27+
Which cards do you wish to see?
28+
<t t-foreach="items" t-as="item" t-key="item.id">
29+
<CheckBox value="item.enabled" onChange="(ev) => this.onChange(ev, item)">
30+
<t t-esc="item.description" />
31+
</CheckBox>
32+
</t>
33+
<t t-slot="footer">
34+
<button class="btn btn-primary" t-on-click="done">
35+
Done
36+
</button>
37+
</t>
38+
</Dialog>
39+
</t>
40+
41+
</templates>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Component } from "@odoo/owl";
2+
3+
export class DashboardItem extends Component {
4+
static template = "awesome_dashboard.DashboardItem";
5+
static props = {
6+
slots: {
7+
type: Object,
8+
},
9+
size: {
10+
type: Number,
11+
optional: true,
12+
},
13+
};
14+
15+
setup() {
16+
if (!this.props.size) {
17+
this.props.size = 1;
18+
}
19+
}
20+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
<t t-name="awesome_dashboard.DashboardItem">
4+
<div class="card m-2 border-dark" t-attf-style="width: {{18*props.size}}rem;">
5+
<div class="card-body">
6+
<div>
7+
<t t-slot="default" />
8+
</div>
9+
</div>
10+
</div>
11+
</t>
12+
</templates>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { NumberCard } from "./number_card/number_card";
2+
import { PieChartCard } from "./pie_chart_card/pie_chart_card";
3+
import { registry } from "@web/core/registry";
4+
import { _t } from "@web/core/l10n/translation";
5+
6+
const items = [
7+
{
8+
id: "average_quantity",
9+
description: _t("Average amount of t-shirt"),
10+
Component: NumberCard,
11+
props: (data) => ({
12+
title: _t("Average amount of t-shirt by order this month"),
13+
value: data.average_quantity,
14+
}),
15+
},
16+
{
17+
id: "average_time",
18+
description: _t("Average time for an order"),
19+
Component: NumberCard,
20+
size: 2,
21+
props: (data) => ({
22+
title: _t("Average time for an order to go from 'new' to 'sent' or 'cancelled'"),
23+
value: data.average_time,
24+
}),
25+
},
26+
{
27+
id: "number_new_orders",
28+
description: _t("New orders this month"),
29+
Component: NumberCard,
30+
props: (data) => ({
31+
title: _t("Number of new orders this month"),
32+
value: data.nb_new_orders,
33+
}),
34+
},
35+
{
36+
id: "nb_cancelled_orders",
37+
description: _t("Cancelled orders this month"),
38+
Component: NumberCard,
39+
props: (data) => ({
40+
title: _t("Number of cancelled orders this month"),
41+
value: data.nb_cancelled_orders,
42+
}),
43+
},
44+
{
45+
id: "total_amount",
46+
description: _t("Amount of orders this month"),
47+
Component: NumberCard,
48+
props: (data) => ({
49+
title: _t("Total amount of new orders this month"),
50+
value: data.total_amount,
51+
}),
52+
},
53+
{
54+
id: "pie_chart",
55+
description: _t("Shirt orders by size"),
56+
Component: PieChartCard,
57+
size: 2,
58+
props: (data) => ({
59+
title: _t("Shirt orders by size"),
60+
data: data.orders_by_size,
61+
}),
62+
},
63+
]
64+
65+
items.forEach(item => {
66+
registry.category("awesome_dashboard").add(item.id, item);
67+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Component } from "@odoo/owl";
2+
3+
export class NumberCard extends Component {
4+
static template = "awesome_dashboard.NumberCard";
5+
static props = {
6+
title: {
7+
type: String,
8+
},
9+
value: {
10+
type: Number,
11+
},
12+
}
13+
}

0 commit comments

Comments
 (0)