Skip to content

Commit eb10d6e

Browse files
committed
[IMP] awesome_dashboard: added selective display of data
This commit introduces display of selective charts via check boxes This allows users to see only preferred charts and data points local storage enables users to automatically save selected preference of charts in browser
1 parent 7c6f7ba commit eb10d6e

Some content is hidden

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

42 files changed

+156
-69
lines changed

awesome_dashboard/__manifest__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@
3030
],
3131
},
3232
'license': 'AGPL-3'
33-
}
33+
}

awesome_dashboard/static/src/dashboard/dashboard.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,39 @@ import { registry } from "@web/core/registry";
55
import { Layout } from "@web/search/layout";
66
import { useService } from "@web/core/utils/hooks";
77
import { DashboardItem } from "./dashboard_item/dashboard_item";
8-
import { PieChart } from "./pie_chart/pie_chart";
8+
import { DashboardSettings } from "./dashboard_settings/dashboard_settings";
9+
import { browser } from "@web/core/browser/browser";
910

1011
class AwesomeDashboard extends Component {
1112
static template = "awesome_dashboard.AwesomeDashboard";
12-
13-
static components = { Layout, DashboardItem, PieChart};
13+
static components = { Layout, DashboardItem };
1414

1515
setup() {
1616
this.actionService = useService("action");
1717
this.statisticsService = useService("awesome_dashboard.statistics");
1818
this.statistics = useState(this.statisticsService.data);
19+
20+
this.dialogService = useService("dialog");
21+
1922
const dashboardItemsRegistry = registry.category("awesome_dashboard");
2023
this.items = dashboardItemsRegistry.getAll();
24+
25+
this.state = useState({
26+
uncheckedItems: browser.localStorage.getItem("uncheckedItems")?.split(",").filter(id => id) || [],
27+
});
28+
}
29+
30+
updateConfiguration(newUncheckedItems) {
31+
this.state.uncheckedItems.length = 0;
32+
this.state.uncheckedItems.push(...newUncheckedItems);
33+
}
34+
35+
openConfiguration() {
36+
this.dialogService.add(DashboardSettings, {
37+
items: this.items,
38+
initialUncheckedItems: this.state.uncheckedItems,
39+
updateConfiguration: this.updateConfiguration.bind(this),
40+
});
2141
}
2242

2343
openCustomers() {
@@ -34,4 +54,4 @@ class AwesomeDashboard extends Component {
3454
}
3555
}
3656

37-
registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard);
57+
registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
.o_dashboard {
22
background-color: grey;
3-
}
3+
}

awesome_dashboard/static/src/dashboard/dashboard.xml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,22 @@
77
<button t-on-click="openCustomers" type="button" class="btn btn-primary me-2" title="Customers">Customers</button>
88
<button t-on-click="openLeads" type="button" class="btn btn-primary" title="Leads">Leads</button>
99
</t>
10+
11+
<t t-set-slot="control-panel-additional-actions">
12+
<button class="btn btn-light" title="Dashboard Settings" t-on-click="openConfiguration">
13+
<i class="fa fa-cog"></i>
14+
</button>
15+
</t>
1016
<div class="p-3">
1117
<div class="d-flex flex-wrap">
12-
<t t-foreach="items" t-as="item" t-key="item.id">
13-
<DashboardItem size="item.size || 1">
14-
<t t-set="itemProp" t-value="item.props ? item.props(statistics) : {'data': statistics}"/>
15-
<t t-component="item.Component" t-props="itemProp" />
18+
<t t-foreach="Object.values(items)" t-as="item" t-key="item.id">
19+
<DashboardItem t-if="!state.uncheckedItems.includes(item.id)" size="item.size || 1">
20+
<t t-set="itemProp" t-value="item.props ? item.props(statistics) : {'data': statistics}"/>
21+
<t t-component="item.Component" t-props="itemProp" />
1622
</DashboardItem>
17-
</t>
23+
</t>
1824
</div>
1925
</div>
2026
</Layout>
2127
</t>
22-
</templates>
28+
</templates>

awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ export class DashboardItem extends Component {
1616
shape: {default: Object}
1717
}
1818
}
19-
}
19+
}

awesome_dashboard/static/src/dashboard/dashboard_item/dashboard_item.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
</div>
88
</div>
99
</t>
10-
</templates>
10+
</templates>

awesome_dashboard/static/src/dashboard/dashboard_items.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,4 @@ export const items = [
6464

6565
items.forEach((item) => {
6666
registry.category("awesome_dashboard").add(item.id, item)
67-
});
67+
});
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/** @odoo-module **/
2+
3+
import { Component, useState } from "@odoo/owl";
4+
import { Dialog } from "@web/core/dialog/dialog";
5+
import { browser } from "@web/core/browser/browser";
6+
7+
export class DashboardSettings extends Component {
8+
static template = "awesome_dashboard.DashboardSettings";
9+
static components = { Dialog };
10+
11+
static props = {
12+
close: { type: Function },
13+
};
14+
15+
setup() {
16+
const items = this.props.items || {};
17+
const initialUncheckedItems = this.props.initialUncheckedItems || [];
18+
19+
this.dialogDisplayItems = useState(
20+
Object.values(items).map((item) => ({
21+
...item,
22+
checked: !initialUncheckedItems.includes(item.id),
23+
}))
24+
);
25+
}
26+
27+
onChange(checked, itemInDialog) {
28+
const targetItem = this.dialogDisplayItems.find(i => i.id === itemInDialog.id);
29+
if (targetItem) {
30+
targetItem.checked = checked;
31+
}
32+
}
33+
34+
confirmChanges() {
35+
const newUncheckedItems = this.dialogDisplayItems.filter((item) => !item.checked).map((item) => item.id);
36+
37+
browser.localStorage.setItem("uncheckedItems", newUncheckedItems.join(","));
38+
39+
if (this.props.updateConfiguration) {
40+
this.props.updateConfiguration(newUncheckedItems);
41+
}
42+
this.props.close();
43+
}
44+
}
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+
<t t-name="awesome_dashboard.DashboardSettings">
4+
<Dialog title="'Dashboard Items Configuration'">
5+
<div class="p-3">
6+
<p>Select items to display on your dashboard:</p>
7+
<div t-foreach="dialogDisplayItems" t-as="item" t-key="item.id" class="form-check mb-2">
8+
<input
9+
type="checkbox"
10+
class="form-check-input"
11+
t-att-id="'settings_item_' + item.id"
12+
t-att-checked="item.checked"
13+
t-on-change="(ev) => this.onChange(ev.target.checked, item)"
14+
/>
15+
<label class="form-check-label" t-att-for="'settings_item_' + item.id">
16+
<t t-out="item.description"/>
17+
</label>
18+
</div>
19+
</div>
20+
<t t-set-slot="footer">
21+
<button class="btn btn-primary" t-on-click="confirmChanges">Apply</button>
22+
<button class="btn btn-secondary ms-2" t-on-click="props.close">Cancel</button>
23+
</t>
24+
</Dialog>
25+
</t>
26+
</templates>

awesome_dashboard/static/src/dashboard/number_card/number_card.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ export class NumberCard extends Component {
88
title: { type: String },
99
value: { type: [String, Number] },
1010
};
11-
}
11+
}

awesome_dashboard/static/src/dashboard/number_card/number_card.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
<p class="fs-4 fw-bold text-success" t-out="props.value"/>
77
</div>
88
</t>
9-
</templates>
9+
</templates>

awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,4 @@ export class PieChart extends Component {
8888
}
8989
});
9090
}
91-
}
91+
}

awesome_dashboard/static/src/dashboard/pie_chart/pie_chart.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
<canvas t-ref="canvas"/>
66
</div>
77
</t>
8-
</templates>
8+
</templates>

awesome_dashboard/static/src/dashboard/piechart_card/piechart_card.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ export class PieChartCard extends Component {
1010
title: { type: String, optional: true },
1111
data: { type: Object },
1212
};
13-
}
13+
}

awesome_dashboard/static/src/dashboard/piechart_card/piechart_card.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
<PieChart data="props.data"/>
77
</div>
88
</t>
9-
</templates>
9+
</templates>

awesome_dashboard/static/src/dashboard_action.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ export class AwesomeDashboardLoader extends Component {
1111
`;
1212
}
1313

14-
registry.category("actions").add("awesome_dashboard.dashboard", AwesomeDashboardLoader);
14+
registry.category("actions").add("awesome_dashboard.dashboard", AwesomeDashboardLoader);

awesome_owl/static/src/card/card.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ export class Card extends Component {
1818
// Toggle the open/closed state
1919
this.state.isOpen = !this.state.isOpen;
2020
}
21-
}
21+
}

awesome_owl/static/src/card/card.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@
1717
</div>
1818
</div>
1919
</t>
20-
</templates>
20+
</templates>

awesome_owl/static/src/counter/counter.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ export class Counter extends Component {
2020
this.props.onChange();
2121
}
2222
}
23-
}
23+
}

awesome_owl/static/src/counter/counter.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
<p> Counter :<t t-esc="state.value"/></p>
55
<button class="btn btn-primary" t-on-click="increment" style="border: 2px solid #007bff; background-color: #28a745; color: #fff;">Increment</button>
66
</t>
7-
</templates>
7+
</templates>

awesome_owl/static/src/playground.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ export class Playground extends Component {
1616
incrementSum() {
1717
this.state.sum += 1;
1818
}
19-
}
19+
}

awesome_owl/static/src/playground.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
22
<templates xml:space="preserve">
3+
34
<t t-name="awesome_owl.playground">
45
<div class="container py-4">
56
<h1 class="mb-4 text-primary text-center">Owl Playground</h1>
@@ -33,4 +34,4 @@
3334
</div>
3435
</div>
3536
</t>
36-
</templates>
37+
</templates>

awesome_owl/static/src/todo_list/todo_items.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ export class TodoItem extends Component {
2727
// Call the parent's removeTodo function with the todo id
2828
this.props.removeTodo(this.props.todo.id);
2929
}
30-
}
30+
}

awesome_owl/static/src/todo_list/todo_items.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
<span class="fa fa-remove" t-on-click="removeTodo" title="Delete Todo" style="color: #dc3545; padding:5px"/>
1111
</div>
1212
</t>
13-
</templates>
13+
</templates>

awesome_owl/static/src/todo_list/todo_list.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ export class TodoList extends Component {
4040
this.todos.splice(index, 1);
4141
}
4242
}
43-
}
43+
}

awesome_owl/static/src/todo_list/todo_list.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
</t>
1313
</div>
1414
</t>
15-
</templates>
15+
</templates>

awesome_owl/static/src/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ export function useAutoFocus(refname) {
1010
inputRef.el.focus();
1111
}
1212
});
13-
}
13+
}

estate/data/estate_property_demo.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@
6262
]"/>
6363
</record>
6464
</data>
65-
</odoo>
65+
</odoo>

estate/data/estate_property_offer_demo.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@
2525
<value eval="ref('demo_big_villa_offer_2')"/>
2626
</function>
2727
</data>
28-
</odoo>
28+
</odoo>

estate/data/estate_property_type_demo.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@
1515
<field name="name">Industrial</field>
1616
</record>
1717
</data>
18-
</odoo>
18+
</odoo>

estate/models/estate_property.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,22 +74,20 @@ class EstateProperty(models.Model):
7474
compute="_compute_total_area",
7575
store=True,
7676
)
77-
7877
company_id = fields.Many2one(
7978
"res.company", required=True, default=lambda self: self.env.company
8079
)
81-
82-
@api.depends("living_area", "garden_area")
83-
def _compute_total_area(self):
84-
for record in self:
85-
record.total_area = record.living_area + record.garden_area
86-
8780
best_price = fields.Float(
8881
string="Best Price",
8982
compute="_compute_best_price",
9083
store=True,
9184
)
9285

86+
@api.depends("living_area", "garden_area")
87+
def _compute_total_area(self):
88+
for record in self:
89+
record.total_area = record.living_area + record.garden_area
90+
9391
@api.depends("offer_ids.price")
9492
def _compute_best_price(self):
9593
for record in self:
@@ -127,8 +125,6 @@ def action_set_cancel(self):
127125
"Only refused offers can set the property as cancelled."
128126
)
129127

130-
# we will not accept the offer if the price is less than 10% of the selling price
131-
132128
@api.constrains("selling_price", "expected_price")
133129
def _check_price(self):
134130
for record in self:
@@ -148,8 +144,6 @@ def _ondelete_property(self):
148144

149145
@api.onchange("offer_ids")
150146
def _onchange_offer_ids(self):
151-
if self.offer_ids:
152-
self.state = "offer_received"
153147
if not self.offer_ids and self.state != "new":
154148
self.state = "new"
155149

0 commit comments

Comments
 (0)