Skip to content

Commit be4499c

Browse files
committed
[ADD] awesome_owl,*: add dashboard using owl framework
*= awesome_dashboard In this tutorial, understand owl framework and complete task and implement to-do list using owl framework. Also create dashboard. in dashboard component implement piechart , learn to display real life update and implement logic for add and remove items from the dashboard.
1 parent c3d9946 commit be4499c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+744
-108
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,3 @@ dmypy.json
127127

128128
# Pyre type checker
129129
.pyre/
130-
131-
# Ignore VS Code settings
132-
.vscode

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 & 10 deletions
This file was deleted.

awesome_dashboard/static/src/dashboard.xml

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

0 commit comments

Comments
 (0)