-
Notifications
You must be signed in to change notification settings - Fork 2.6k
chapter1-No.6 #976
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-oBoarding-yoahm
Are you sure you want to change the base?
chapter1-No.6 #976
Changes from all commits
d547bfe
126d3db
bf823a9
4dad56b
9e75e82
6704c04
a715595
66a0236
2448ca3
143511d
3867e9e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
|
||
{ | ||
"name": "Python Debugger: Current File with Arguments", | ||
"type": "debugpy", | ||
"request": "launch", | ||
"program": "${file}", | ||
"console": "integratedTerminal", | ||
"args": "${command:pickArgs}" | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from . import controllers | ||
from . import models |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from . import controllers | ||
from . import controllers | ||
from . import awesome_dashboard_controller |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
from odoo import http | ||
from odoo.http import request | ||
|
||
class AwesomeDashboardController(http.Controller): | ||
|
||
@http.route('/awesome_dashboard/save_settings', type='json', auth='user') | ||
def save_settings(self, new_disabled_items): | ||
current_user = http.request.env.user | ||
user_dashboard_settings = http.request.env['user.dashboard.settings'].sudo().search([('user_id', '=', current_user.id)], limit=1) | ||
disabled_items = ",".join(new_disabled_items) | ||
|
||
if user_dashboard_settings: | ||
user_dashboard_settings.write({'disabled_items': disabled_items}) | ||
else: | ||
http.request.env['user.dashboard.settings'].sudo().create({ | ||
'user_id': current_user.id, | ||
'disabled_items': disabled_items | ||
}) | ||
return True | ||
|
||
@http.route('/awesome_dashboard/get_settings', type='json', auth='user') | ||
def get_settings(self): | ||
current_user = http.request.env.user | ||
user_dashboard_settings = http.request.env['user.dashboard.settings'].sudo().search([('user_id', '=', current_user.id)], limit=1) | ||
if user_dashboard_settings and user_dashboard_settings.disabled_items: | ||
return user_dashboard_settings.disabled_items.split(',') | ||
return [] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import user_dashboard_settings |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from odoo import models, fields | ||
|
||
class UserDashboardSettings(models.Model): | ||
_name = "user.dashboard.settings" | ||
_description = "User Dashboard Settings" | ||
|
||
user_id = fields.Many2one('res.users', string="User", required=True) | ||
disabled_items = fields.Char(string='Dashboard Disabled Items') # Add this Field |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
access_user_dashboard_settings_model,access_user_dashboard_settings_model,model_user_dashboard_settings,base.group_user,1,1,1,1 |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { Dialog } from "@web/core/dialog/dialog"; | ||
import { CheckBox } from "@web/core/checkbox/checkbox"; | ||
import { rpc } from "@web/core/network/rpc"; | ||
import { Component, useState } from "@odoo/owl"; | ||
|
||
export class ConfigurationDialog extends Component { | ||
static template = "awesome_dashboard.ConfigurationDialog"; | ||
static components = { Dialog, CheckBox }; | ||
|
||
static props = { | ||
items: Array, | ||
disabledItems: Array, | ||
onUpdateConfiguration: Function, | ||
}; | ||
|
||
setup() { | ||
this.checkBoxItems = useState(this.props.items.map((item) => { // Add 'enabled' field to Item -> return Array of Objects | ||
return { | ||
...item, | ||
enabled: !this.props.disabledItems.includes(item.id), | ||
} | ||
})); | ||
} | ||
|
||
onChange(checked, changedItem) { | ||
changedItem.enabled = checked; | ||
} | ||
|
||
onDone() { | ||
const newDisabledItems = this.checkBoxItems.filter(item => !item.enabled).map(item => item.id); | ||
rpc("/awesome_dashboard/save_settings", { new_disabled_items: newDisabledItems }); | ||
this.props.onUpdateConfiguration(newDisabledItems); | ||
this.props.close(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<templates xml:space="preserve"> | ||
<t t-name="awesome_dashboard.ConfigurationDialog"> | ||
<Dialog title="'Dashboard items configuration'"> | ||
Which cards do you whish to see ? | ||
<t t-foreach="checkBoxItems" t-as="item" t-key="item.id"> | ||
<CheckBox value="item.enabled" onChange="(event) => this.onChange(event, item)"> | ||
<t t-esc="item.description"/> | ||
</CheckBox> | ||
</t> | ||
<t t-set-slot="footer"> | ||
<button class="btn btn-primary" t-on-click="this.onDone"> | ||
Done | ||
</button> | ||
</t> | ||
</Dialog> | ||
</t> | ||
</templates> |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,58 @@ | ||||||
import { registry } from "@web/core/registry"; | ||||||
import { Layout } from "@web/search/layout"; | ||||||
import { useService } from "@web/core/utils/hooks"; | ||||||
import { browser } from "@web/core/browser/browser"; | ||||||
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. don't need it |
||||||
import { PieChart } from "./pie_chart/pie_chart"; | ||||||
import { DashboardItem } from "./dashboard_item"; | ||||||
import { ConfigurationDialog } from "./configuration_dialog/configuration_dialog"; | ||||||
import { Component, useState, onWillStart } from "@odoo/owl"; | ||||||
import { rpc } from "@web/core/network/rpc"; | ||||||
|
||||||
|
||||||
class AwesomeDashboard extends Component { | ||||||
static template = "awesome_dashboard.AwesomeDashboard"; | ||||||
static components = { Layout, DashboardItem, PieChart }; | ||||||
|
||||||
setup() { | ||||||
this.action = useService("action"); | ||||||
this.dialog = useService("dialog"); | ||||||
this.statistics = useState(useService("awesome_dashboard.statistics")); // useState() because it's reactive | ||||||
this.items = registry.category("awesome_dashboard.items").getAll(); | ||||||
this.state = useState({ | ||||||
disabledItems: [], // useState() because it's reactive | ||||||
}); | ||||||
|
||||||
onWillStart(async () => { | ||||||
this.state.disabledItems = await rpc("/awesome_dashboard/get_settings"); | ||||||
}); | ||||||
} | ||||||
|
||||||
openCustomers() { | ||||||
this.action.doAction('base.action_partner_form'); | ||||||
} | ||||||
|
||||||
openLeads(){ | ||||||
this.action.doAction({ // define the action inline | ||||||
type: 'ir.actions.act_window', | ||||||
name: 'Leads', | ||||||
target: 'current', | ||||||
res_model: 'crm.lead', | ||||||
views: [ | ||||||
[false, 'form'], | ||||||
[false, 'list']], | ||||||
Comment on lines
+41
to
+42
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. It doesn't make much sense to give form then list. Because they can't open the list view from the form |
||||||
}); | ||||||
} | ||||||
|
||||||
openConfiguration(){ | ||||||
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.dialog.add(ConfigurationDialog, { | ||||||
items: this.items, | ||||||
disabledItems: this.state.disabledItems, | ||||||
onUpdateConfiguration: this.updateConfiguration.bind(this), | ||||||
}); | ||||||
} | ||||||
|
||||||
updateConfiguration(newDisabledItems){ | ||||||
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.state.disabledItems = newDisabledItems // update the state | ||||||
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
|
||||||
} | ||||||
} | ||||||
registry.category("lazy_components").add("AwesomeDashboard", AwesomeDashboard); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
.o_dashboard { | ||
background-color: #f5f5f5; | ||
padding: 20px; | ||
} | ||
|
||
.o_dashboard_buttons { | ||
display: flex; | ||
gap: 0.5rem; | ||
} | ||
|
||
@media (max-width: 767.98px) { | ||
.o_dashboard .card { | ||
width: 100% !important; | ||
max-width: 100% !important; | ||
display: block !important; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<templates xml:space="preserve"> | ||
|
||
<t t-name="awesome_dashboard.AwesomeDashboard"> | ||
<Layout className="'o_dashboard h-100'"> | ||
<div class="o_dashboard_content d-flex align-items-center"> | ||
<div class="o_dashboard_buttons"> | ||
<button t-on-click="openCustomers" type="button" class="btn btn-primary mr-2">Customers</button> | ||
<button t-on-click="openLeads" type="button" class="btn btn-secondary">Leads</button> | ||
</div> | ||
<div class="d-flex align-items-center" style="margin-left:10px"> | ||
<h3 class="m-0 me-2">Dashboard</h3> | ||
<button t-on-click="openConfiguration" type="button" class="btn p-0 border-0"> | ||
<i class="fa fa-cog"/> | ||
</button> | ||
</div> | ||
</div> | ||
<t t-foreach="items" t-as="item" t-key="item.id"> | ||
<DashboardItem t-if="statistics.isReady and !state.disabledItems.includes(item.id)" size="item.size"> | ||
<t t-if="statistics.isReady"> | ||
<t t-component="item.Component" t-props="item.props(statistics)" /> | ||
</t> | ||
</DashboardItem> | ||
</t> | ||
</Layout> | ||
</t> | ||
</templates> |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,9 @@ | ||||||
import { Component } from "@odoo/owl"; | ||||||
|
||||||
export class DashboardItem extends Component { | ||||||
static template = "awesome_dashboard.dashboard_item"; | ||||||
static props = { | ||||||
size: { type: Number, default: 1, optional: true }, | ||||||
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 default: 1 doesn't do anything. If you want a default value for your props you should use |
||||||
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.dashboard_item"> | ||
<div class="card d-inline-block m-2" t-attf-style="width: {{props.size *18}}rem;"> | ||
<div class="card-body d-flex justify-content-center align-items-center flex-column"> | ||
<t t-slot="default"/> | ||
</div> | ||
</div> | ||
</t> | ||
</templates> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { _t } from "@web/core/l10n/translation"; | ||
import { registry } from "@web/core/registry"; | ||
import { NumberCard } from "./number_card/number_card"; | ||
import { PieChartCard } from "./pie_chart_card/pie_chart_card"; | ||
|
||
const items = [ | ||
{ | ||
id: "average_quantity", | ||
description: _t("Average amount"), | ||
Component: NumberCard, | ||
props: (data) => ({ | ||
title: _t("Average amount of t-shirt by order this month"), | ||
value: data.average_quantity | ||
}), | ||
}, | ||
{ | ||
id: "average_time", | ||
description: _t("Average Time"), | ||
Component: NumberCard, | ||
props: (data) => ({ | ||
title: _t("Average Time"), | ||
value: data.average_time | ||
}), | ||
}, | ||
{ | ||
id: "nb_new_orders", | ||
description: _t("Number of new orders"), | ||
Component: NumberCard, | ||
props: (data) => ({ | ||
title: _t("Number of new orders"), | ||
value: data.nb_new_orders | ||
}), | ||
}, | ||
{ | ||
id: "nb_cancelled_orders", | ||
description: _t("Number of cancelled orders"), | ||
Component: NumberCard, | ||
props: (data) => ({ | ||
title: _t("Number of cancelled orders"), | ||
value: data.nb_cancelled_orders | ||
}), | ||
}, | ||
{ | ||
id: "total_amount", | ||
description: _t("Total amount"), | ||
Component: NumberCard, | ||
props: (data) => ({ | ||
title: _t("Total amount"), | ||
value: data.total_amount | ||
}), | ||
}, | ||
{ | ||
id: "pie_chart", | ||
description: _t("Shirts orders by size"), | ||
Component: PieChartCard, | ||
size: 2, | ||
props: (data) => ({ | ||
title: _t("Shirts orders by size"), | ||
value: data.orders_by_size | ||
}), | ||
}, | ||
] | ||
|
||
items.forEach((item => { | ||
registry.category("awesome_dashboard.items").add(item.id, item); | ||
})); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Component } from "@odoo/owl"; | ||
|
||
export class NumberCard extends Component { | ||
static template = "awesome_dashboard.NumberCard"; | ||
static props = { | ||
title: String, | ||
value: Number, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<templates xml:space="preserve"> | ||
<t t-name="awesome_dashboard.NumberCard" owl="1"> | ||
<t t-esc="props.title"/> | ||
<div class="fs-1 fw-bold text-success text-center"> | ||
<t t-esc="props.value"/> | ||
</div> | ||
</t> | ||
</templates> |
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.
what's that comment for 😆
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.
it's just a note for me, that item object have a new field now