Skip to content

Commit 0cb5c69

Browse files
committed
[ADD] awesome_owl: Chapter 2 in the web framework
1 parent fc08cdc commit 0cb5c69

File tree

17 files changed

+409
-16
lines changed

17 files changed

+409
-16
lines changed

awesome_dashboard/__manifest__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
'web.assets_backend': [
2626
'awesome_dashboard/static/src/**/*',
2727
],
28+
'awesome_dashboard.dashboard': [
29+
'awesome_dashboard/static/src/dashboard/**/*',
30+
],
2831
},
2932
'license': 'AGPL-3'
3033
}

awesome_dashboard/static/src/dashboard.js

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

awesome_dashboard/static/src/dashboard.xml

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { Component, useState, xml } from "@odoo/owl";
2+
import { registry } from "@web/core/registry";
3+
import { Layout } from "@web/search/layout";
4+
import { useService } from "@web/core/utils/hooks";
5+
import { _t } from "@web/core/l10n/translation";
6+
import { DashboardItem } from "./dashboardItem/dashboardItem";
7+
import { Dialog } from "@web/core/dialog/dialog";
8+
import { CheckBox } from "@web/core/checkbox/checkbox";
9+
10+
class AwesomeDashboard extends Component {
11+
static template = "awesome_dashboard.AwesomeDashboard";
12+
13+
static components = { Layout, DashboardItem };
14+
15+
static props = {
16+
statistics: { type: Array, optional: true },
17+
};
18+
19+
setup() {
20+
this.display = {
21+
controlPanel: {},
22+
}
23+
24+
this.action = useService("action");
25+
26+
const statisticsService = useService("awesome_dashboard.statistics");
27+
28+
this.statistics = useState(statisticsService.statistics);
29+
30+
this.items = registry.category("awesome_dashboard").getAll();
31+
32+
this.dialog = useService("dialog");
33+
34+
this.state = useState({ disabledItemsIds: [] });
35+
}
36+
37+
openCustomersKanban() {
38+
this.action.doAction("base.action_partner_form");
39+
}
40+
41+
openCrmLeads() {
42+
this.action.doAction({
43+
type: "ir.actions.act_window",
44+
name: _t("Leads"),
45+
target: "current",
46+
res_model: "crm.lead",
47+
views: [[false, "list"], [false, "form"]],
48+
});
49+
}
50+
51+
openConfiguration() {
52+
this.dialog.add(ConfigurationDialog, {
53+
title: _t("Dashboard Items Configuration"),
54+
items: this.items,
55+
disabledItemsIds: this.state.disabledItemsIds,
56+
onApply: (newDisabledItemsIds) => {
57+
this.state.disabledItemsIds = newDisabledItemsIds;
58+
},
59+
size: "medium",
60+
showFooter: true,
61+
});
62+
}
63+
64+
}
65+
66+
67+
class ConfigurationDialog extends Component {
68+
static template = xml`
69+
<Dialog title="props.title">
70+
<div class="p-4">
71+
<p t-esc="this._t('Which cards do you wish to see?')"/>
72+
<t t-foreach="props.items" t-key="item.id" t-as="item">
73+
<CheckBox
74+
value="!props.disabledItemsIds.includes(item.id)"
75+
t-on-change="() => this.toggleItem(item.id)"
76+
>
77+
<t t-esc="item.description"/>
78+
</CheckBox>
79+
</t>
80+
</div>
81+
<t t-set-slot="footer">
82+
<button class="btn btn-primary" t-on-click="onApply">Apply</button>
83+
</t>
84+
</Dialog>
85+
`;
86+
87+
static components = { Dialog, CheckBox };
88+
89+
setup() {
90+
this._t = _t;
91+
this.newDisabledItemsIds = [...this.props.disabledItemsIds];
92+
}
93+
94+
toggleItem(itemId) {
95+
if (this.newDisabledItemsIds.includes(itemId)) {
96+
this.newDisabledItemsIds = this.newDisabledItemsIds.filter(id => id !== itemId);
97+
} else {
98+
this.newDisabledItemsIds = [...this.newDisabledItemsIds, itemId];
99+
}
100+
}
101+
102+
onApply() {
103+
this.props.onApply(this.newDisabledItemsIds);
104+
this.props.close();
105+
}
106+
}
107+
108+
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: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<templates xml:space="preserve">
3+
4+
<t t-name="awesome_dashboard.AwesomeDashboard">
5+
<Layout display="display" className="'o_dashboard h-100'">
6+
<t t-set-slot="layout-buttons">
7+
<button class="btn btn-primary" t-on-click="openCustomersKanban">Customers</button>
8+
<button class="btn btn-primary" t-on-click="openCrmLeads">Leads</button>
9+
</t>
10+
<t t-set-slot="control-panel-additional-actions">
11+
<button t-on-click="openConfiguration" class="btn p-0 ms-1 border-0">
12+
<i class="fa fa-cog"></i>
13+
</button>
14+
</t>
15+
<t t-foreach="items" t-key="item.id" t-as="item">
16+
<t t-if="!state.disabledItemsIds.includes(item.id)">
17+
<DashboardItem size="item.size || 1">
18+
<t t-set="itemProp" t-value="item.props ? item.props(statistics) : {'data': statistics}"/>
19+
<t t-component="item.Component" t-props="itemProp" />
20+
</DashboardItem>
21+
</t>
22+
</t>
23+
</Layout>
24+
</t>
25+
26+
</templates>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Component, useState } from "@odoo/owl";
2+
3+
export class DashboardItem extends Component {
4+
static template = "awesome_dashboard.dashboardItem";
5+
6+
static props = {
7+
size: { type: Number, optional: true},
8+
slots: { type: Object, optional: true },
9+
};
10+
11+
static defaultProps = {
12+
size: 1,
13+
};
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<templates xml:space="preserve">
3+
4+
<t t-name="awesome_dashboard.dashboardItem">
5+
<div class="p-3" t-attf-style="width: {{ props.size * 18 }}rem; background-color: white; color: black; border-radius: 5px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); margin: 10px;">
6+
<t t-slot="default"/>
7+
</div>
8+
</t>
9+
10+
</templates>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { _t } from "@web/core/l10n/translation";
2+
import { NumberCard } from "./numberCard/numberCard";
3+
import { PieChartCard } from "./pieChartCard/pieChartCard";
4+
import { registry } from "@web/core/registry";
5+
6+
const dashboardRegistry = registry.category("awesome_dashboard");
7+
8+
dashboardRegistry.add("average_quantity", {
9+
id: "average_quantity",
10+
description: _t("Average amount of t-shirts"),
11+
Component: NumberCard,
12+
size: 3,
13+
props: (data) => ({
14+
title: _t("Average Quantity"),
15+
value: data.average_quantity
16+
}),
17+
});
18+
19+
dashboardRegistry.add("average_time", {
20+
id: "average_time",
21+
description: _t("Average time for an order"),
22+
Component: NumberCard,
23+
props: (data) => ({
24+
title: _t("Average Time"),
25+
value: data.average_time
26+
}),
27+
});
28+
29+
dashboardRegistry.add("nb_cancelled_orders", {
30+
id: "nb_cancelled_orders",
31+
description: _t("Number of cancelled orders"),
32+
Component: NumberCard,
33+
props: (data) => ({
34+
title: _t("Cancelled Orders"),
35+
value: data.nb_cancelled_orders
36+
}),
37+
});
38+
39+
dashboardRegistry.add("orders_by_size", {
40+
id: "orders_by_size",
41+
description: _t("Shirt orders by size"),
42+
Component: PieChartCard,
43+
props: (data) => ({
44+
title: _t("Shirt orders by size"),
45+
values: data.orders_by_size,
46+
})
47+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Component } from "@odoo/owl";
2+
3+
export class NumberCard extends Component {
4+
static template = "awesome_dashboard.numberCard";
5+
6+
static props = {
7+
title: { type: String},
8+
value: { type: Number, optional: true },
9+
};
10+
}

0 commit comments

Comments
 (0)