-
Notifications
You must be signed in to change notification settings - Fork 2.3k
[ADD] estate,*: added real estate module #848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 18.0
Are you sure you want to change the base?
Changes from all commits
1db8870
b5aab61
033cf42
795b8b5
3fb51b6
2193137
b5a40ba
9524cb6
6e1558e
5fb5928
6792087
5518b4e
436bb2c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** @odoo-module **/ | ||
|
||
import { Component } from "@odoo/owl"; | ||
|
||
export class DashboardItem extends Component { | ||
static template = "awesome_dashboard.DashboardItem"; | ||
static props = { | ||
size: { type: Number, optional: true, default: 1 }, | ||
slots: { type: Object, optional: true } | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<templates xml:space="preserve"> | ||
|
||
<t t-name="awesome_dashboard.DashboardItem"> | ||
<div class="card m-2" t-attf-style="width: {{ 18 * props.size }}rem;"> | ||
<div class="card-body"> | ||
<t t-slot="default"/> | ||
</div> | ||
</div> | ||
</t> | ||
</templates> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** @odoo-module **/ | ||
|
||
import { Component } from "@odoo/owl"; | ||
|
||
export class NumberCard extends Component { | ||
static template = "awesome_dashboard.NumberCard"; | ||
static props = ["title", "value"]; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<t t-name="awesome_dashboard.NumberCard" owl="1"> | ||
<h5 class="mb-1 text-muted"><t t-esc="props.title" /></h5> | ||
<h2 class="fw-bold"><t t-esc="props.value" /></h2> | ||
</t> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** @odoo-module **/ | ||
|
||
import { PieChart } from "../piechart/piechart"; | ||
import { Component } from "@odoo/owl"; | ||
|
||
export class PieChartCard extends Component { | ||
static template = "awesome_dashboard.PieChartCard"; | ||
static components = { PieChart }; | ||
static props = ["title", "data"]; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<t t-name="awesome_dashboard.PieChartCard" owl="1"> | ||
<h5 class="mb-2 text-muted"><t t-esc="props.title" /></h5> | ||
<t t-if="props.values"> | ||
<PieChart t-props="props" /> | ||
</t> | ||
<t t-else=""> | ||
<div class="text-muted text-center py-5"> | ||
No data available yet. | ||
</div> | ||
</t> | ||
</t> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { Component, onWillStart,onMounted, useRef, onWillUpdateProps } from "@odoo/owl"; | ||
import { loadJS } from "@web/core/assets"; | ||
|
||
|
||
export class PieChart extends Component{ | ||
static template = "awesome_dashboard.PieChart" | ||
setup(){ | ||
this.canvasRef = useRef("canvas") | ||
onWillStart(async()=>{ | ||
await loadJS("/web/static/lib/Chart/Chart.js") | ||
}) | ||
onMounted(() => { | ||
this.renderChart(); | ||
}); | ||
onWillUpdateProps((nextProps) => { | ||
if (this.chart) { | ||
this.chart.destroy(); | ||
} | ||
this.renderChart(nextProps.values); | ||
}); | ||
} | ||
|
||
renderChart(values = this.props.values){ | ||
if (!values) { | ||
console.warn("PieChart: No data yet, skipping render."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A normal user may not open the console, so he will have no idea of what is wrong with working, use a better way of notifying the error to the enduser |
||
return; | ||
} | ||
const labels = Object.keys(this.props.values); | ||
const data = Object.values(this.props.values); | ||
|
||
const color = ["#007BFF", "#FFA500", "#808090",]; | ||
if (!this.canvasRef.el) { | ||
console.error("Canvas element not found"); | ||
return; | ||
} | ||
const ctx = this.canvasRef.el.getContext("2d"); | ||
this.chart = new Chart(ctx,{ | ||
type:"pie", | ||
data:{ | ||
labels:labels, | ||
datasets: [ | ||
{ | ||
label: this.props.title, | ||
data:data, | ||
backgroundColor: color | ||
} | ||
] | ||
}, | ||
options: { | ||
responsive: true, | ||
maintainAspectRatio: false, | ||
}, | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<templates xml:space="preserve"> | ||
<t t-name="awesome_dashboard.PieChart"> | ||
<h4> | ||
<t t-esc="props.title"/> | ||
</h4> | ||
<div> | ||
<canvas t-ref="canvas"/> | ||
</div> | ||
</t> | ||
</templates> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Component, useState } from "@odoo/owl"; | ||
import { Dialog } from "@web/core/dialog/dialog"; | ||
|
||
export class SettingsDialog extends Component { | ||
static template = "awesome_dashboard.SettingsDialog"; | ||
static components = { Dialog }; | ||
static props = { | ||
items: Array, | ||
removedIds: Array, | ||
onSave: Function, | ||
close: { type: Function, optional: false }, | ||
}; | ||
|
||
setup() { | ||
const removedIds = this.props.removedIds || []; | ||
this.state = useState({ | ||
selected: new Set(this.props.items.map(i => i.id).filter(id => !removedIds.includes(id))), | ||
}); | ||
|
||
this.toggleItem = (id) => { | ||
if (this.state.selected.has(id)) { | ||
this.state.selected.delete(id); | ||
} else { | ||
this.state.selected.add(id); | ||
} | ||
}; | ||
} | ||
|
||
save() { | ||
const unchecked = this.props.items.map(item => item.id).filter(id => !this.state.selected.has(id)); | ||
this.props.onSave(unchecked); | ||
this.props.close(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<t t-name="awesome_dashboard.SettingsDialog" owl="1"> | ||
<Dialog title="'Dashboard items configurations'" t-on-close="props.close"> | ||
<div class="p-3"> | ||
<p>Which card do you want to see ?</p> | ||
<t t-foreach="props.items" t-as="item" t-key="item.id"> | ||
<div class="form-check mb-2"> | ||
<input type="checkbox" class="form-check-input" | ||
t-att-id="item.id" | ||
t-att-checked="state.selected.has(item.id) ? true : undefined" | ||
t-on-change="() => toggleItem(item.id)" /> | ||
<label class="form-check-label" t-att-for="item.id"> | ||
<t t-esc="item.description"/> | ||
</label> | ||
</div> | ||
</t> | ||
</div> | ||
<t t-set-slot="footer"> | ||
<button type="button" class="btn btn-primary" t-on-click="save">Apply</button> | ||
</t> | ||
</Dialog> | ||
</t> |
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,58 @@ | ||||||||||||
/** @odoo-module **/ | ||||||||||||
|
||||||||||||
import { Component } 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 "./components/dashboard_item/dashboard_item"; | ||||||||||||
import { PieChart } from "./components/piechart/piechart"; | ||||||||||||
import { useState } from "@odoo/owl"; | ||||||||||||
import { dashboardItems } from "./dashboard_items"; | ||||||||||||
import { SettingsDialog } from "./components/settings_dialog/settings_dialog"; | ||||||||||||
Comment on lines
+7
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use absolute path instead of relative ones |
||||||||||||
|
||||||||||||
class AwesomeDashboard extends Component { | ||||||||||||
static template = "awesome_dashboard.AwesomeDashboard"; | ||||||||||||
static components = {Layout, DashboardItem, PieChart} | ||||||||||||
|
||||||||||||
setup() { | ||||||||||||
this.dialog = useService("dialog"); | ||||||||||||
this.action = useService("action"); | ||||||||||||
this.display = { controlPanel: {} }; | ||||||||||||
this.statisticsService = useService("awesome_dashboard.statistics"); | ||||||||||||
this.statistics = useState(this.statisticsService.statistics); | ||||||||||||
this.allItems = registry.category('awesome_dashboard').getAll() || []; | ||||||||||||
this.removedIds = JSON.parse(localStorage.getItem("awesome_dashboard_hidden_items") || "[]"); | ||||||||||||
this.dashboardItems = this.allItems.filter( | ||||||||||||
item => !this.removedIds.includes(item.id) | ||||||||||||
); | ||||||||||||
|
||||||||||||
} | ||||||||||||
Comment on lines
+27
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
|
||||||||||||
openCustomers() { | ||||||||||||
this.action.doAction('base.action_partner_form'); | ||||||||||||
} | ||||||||||||
openLeads() { | ||||||||||||
Comment on lines
+33
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
this.action.doAction({ | ||||||||||||
type: "ir.actions.act_window", | ||||||||||||
name: "Leads", | ||||||||||||
res_model: "crm.lead", | ||||||||||||
views: [[false, "list"], [false, "form"]], | ||||||||||||
target: "current", | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
|
||||||||||||
openSettings() { | ||||||||||||
this.dialog.add(SettingsDialog, { | ||||||||||||
items: this.allItems, | ||||||||||||
removedIds: this.removedIds || [], | ||||||||||||
onSave: (removed) => { | ||||||||||||
localStorage.setItem("awesome_dashboard_hidden_items", JSON.stringify(removed)); | ||||||||||||
this.removedIds = removed; | ||||||||||||
this.dashboardItems = this.allItems.filter(item => !removed.includes(item.id)); | ||||||||||||
this.render(); | ||||||||||||
} | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<templates xml:space="preserve"> | ||
|
||
<t t-name="awesome_dashboard.AwesomeDashboard" owl="1"> | ||
<Layout display="this.display" className="'o_dashboard h-100'"> | ||
<t t-set-slot="layout-buttons"> | ||
<button class="btn btn-primary" t-on-click="openCustomers">Customers</button> | ||
<button class="btn btn-primary" t-on-click="openLeads">Leads</button> | ||
<button class="btn btn-light" title="Settings" t-on-click="openSettings"> | ||
<i class="fa fa-cog"></i> | ||
</button> | ||
</t> | ||
<div class="o_dashboard d-grid gap-3" style="grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));"> | ||
<t t-foreach="this.dashboardItems" t-as="item" t-key="item.id"> | ||
<DashboardItem size="item.size || 1"> | ||
<t t-set="itemProps" t-value="item.props ? item.props(this.statistics) : {'data': this.statistics}" /> | ||
<t t-if="itemProps"> | ||
<t t-component="item.Component" t-props="itemProps" /> | ||
</t> | ||
<t t-else=""> | ||
<div class="text-muted text-center py-5"> | ||
No data available | ||
</div> | ||
</t> | ||
</DashboardItem> | ||
</t> | ||
</div> | ||
</Layout> | ||
</t> | ||
</templates> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { NumberCard } from "../dashboard/components/number_card/number_card"; | ||
import { PieChartCard } from "../dashboard/components/pie_chart_card/pie_chart_card"; | ||
Comment on lines
+1
to
+2
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. absolute path instead of relative paths |
||
import { registry } from "@web/core/registry"; | ||
|
||
const dashboardItems = [ | ||
{ | ||
id: "average_quantity", | ||
description: "Average T-shirt Quantity", | ||
Component: NumberCard, | ||
props: (statistics) => ({ | ||
title: "Average amount of t-shirt by order this month", | ||
value: statistics.average_quantity, | ||
icon: "shopping-basket", | ||
color: "primary" | ||
}) | ||
}, | ||
{ | ||
id: "average_time", | ||
description: "Average Processing Time", | ||
Component: NumberCard, | ||
props: (statistics) => ({ | ||
title: "Average time for an order to be processed", | ||
value: statistics.average_time, | ||
icon: "clock-o", | ||
color: "info", | ||
suffix: "hrs" | ||
}) | ||
}, | ||
{ | ||
id: "number_new_orders", | ||
description: "New Orders This Month", | ||
Component: NumberCard, | ||
props: (statistics) => ({ | ||
title: "Number of new orders this month", | ||
value: statistics.nb_new_orders, | ||
icon: "shopping-cart", | ||
color: "success" | ||
}) | ||
}, | ||
{ | ||
id: "cancelled_orders", | ||
description: "Cancelled Orders This Month", | ||
Component: NumberCard, | ||
props: (statistics) => ({ | ||
title: "Number of cancelled orders this month", | ||
value: statistics.nb_cancelled_orders, | ||
icon: "times-circle", | ||
color: "danger" | ||
}) | ||
}, | ||
{ | ||
id: "amount_new_orders", | ||
description: "Total Order Amount", | ||
Component: NumberCard, | ||
props: (statistics) => ({ | ||
title: "Total amount of new orders this month", | ||
value: statistics.total_amount, | ||
icon: "money", | ||
color: "success" | ||
}) | ||
}, | ||
{ | ||
id: "pie_chart", | ||
description: "Shirt Orders by Size", | ||
Component: PieChartCard, | ||
size: 2, | ||
props: (statistics) => ({ | ||
title: "Shirt orders by size", | ||
values: statistics.orders_by_size, | ||
}) | ||
} | ||
]; | ||
|
||
// Register all dashboard items | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not needed |
||
dashboardItems.forEach(item => { | ||
registry.category("awesome_dashboard").add(item.id, item); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use absolute path instead of relative path