Skip to content

18.0 - Technical Onboarding - AHSL #364

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

Open
wants to merge 35 commits into
base: 18.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
13375d4
[ADD] estate: create a basic setup for the module - chapter-2
AhmedGamal2212 Feb 17, 2025
4da6e08
[IMP] estate: correct module version and add a license to manifest - …
AhmedGamal2212 Feb 18, 2025
e1eb0f4
[IMP] estate: define property model and essentials
AhmedGamal2212 Feb 18, 2025
2f634ec
[IMP] estate: add and link module access rules
AhmedGamal2212 Feb 18, 2025
1545697
[IMP] estate: create basic UI, enhance prop model
AhmedGamal2212 Feb 18, 2025
5edf1b6
[IMP] estate: make code style changes
AhmedGamal2212 Feb 19, 2025
4ea025c
[IMP] estate: add empty line at the end of files
AhmedGamal2212 Feb 19, 2025
173f26e
[IMP] estate: create custom views for properties
AhmedGamal2212 Feb 19, 2025
bb0d205
[IMP] estate: create estate property type logic
AhmedGamal2212 Feb 20, 2025
8b85b0c
[IMP] estate: create tags to estate properties
AhmedGamal2212 Feb 20, 2025
3433acd
[IMP] estate: create property offer model
AhmedGamal2212 Feb 20, 2025
059ad0f
[IMP] estate: add computed and onchange fields
AhmedGamal2212 Feb 20, 2025
6d7c899
[IMP] estate: add actions to deal with offers
AhmedGamal2212 Feb 20, 2025
22af9cd
[IMP] estate: add constraints for data consistency
AhmedGamal2212 Feb 20, 2025
ff59a9f
[REF] estate: refactor code for better approaching
AhmedGamal2212 Feb 20, 2025
406dc45
[IMP] estate: add the sprinkles
AhmedGamal2212 Feb 21, 2025
2421236
[IMP] estate: apply changes using inheretance
AhmedGamal2212 Feb 24, 2025
09df5a6
[ADD] estate_account: add invoices functionality
AhmedGamal2212 Feb 24, 2025
52690e1
[IMP] estate: add kanban view for a properties
AhmedGamal2212 Feb 24, 2025
e36a9a8
[REF] estate: refactor methods for better process
AhmedGamal2212 Feb 24, 2025
655c35b
[IMP] awesome_owl: create Counters and Cards
AhmedGamal2212 Feb 24, 2025
0f9dfa6
[IMP] awesome_owl: use callback to add counters
AhmedGamal2212 Feb 24, 2025
dee1da8
[IMP] awesome_owl: add a todo list to playground
AhmedGamal2212 Feb 25, 2025
7844bfa
[IMP] awesome_owl: enable users to add tasks
AhmedGamal2212 Feb 25, 2025
cbe834f
[IMP] awesome_owl: add autofocus to task input
AhmedGamal2212 Feb 25, 2025
eaf7030
[IMP] awesome_owl: add task toggling functionality
AhmedGamal2212 Feb 25, 2025
63e3793
[IMP] awesome_owl: enable removing todos
AhmedGamal2212 Feb 25, 2025
fe7df59
[IMP] awesome_owl: enable dynamic card content
AhmedGamal2212 Feb 25, 2025
7562113
[IMP] awesome_owl: add a fold toggle to card
AhmedGamal2212 Feb 25, 2025
b74064f
[IMP] awesome_dashboard: create dashboard stats
AhmedGamal2212 Feb 26, 2025
d53317f
[IMP] awesome_dashboard: cache network calls
AhmedGamal2212 Feb 26, 2025
86fcb08
[IMP] awesome_dashboard: create tshirt sizes chart
AhmedGamal2212 Feb 27, 2025
e4703db
[IMP] awesome_dashboard: add live updates
AhmedGamal2212 Feb 27, 2025
2d6a646
[IMP] awesome_dashboard: make the dashboard generic
AhmedGamal2212 Feb 27, 2025
fa6692a
[IMP] awesome_dashboard: customize dashboard
AhmedGamal2212 Feb 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions awesome_dashboard/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
'assets': {
'web.assets_backend': [
'awesome_dashboard/static/src/**/*',
('remove', 'awesome_dashboard/static/src/dashboard/**/*'),
],
'awesome_dashboard.dashboard': [
'awesome_dashboard/static/src/dashboard/**/*',
]
},
'license': 'AGPL-3'
}
10 changes: 0 additions & 10 deletions awesome_dashboard/static/src/dashboard.js

This file was deleted.

8 changes: 0 additions & 8 deletions awesome_dashboard/static/src/dashboard.xml

This file was deleted.

98 changes: 98 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/** @odoo-module **/

import { Component, useState } 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 './dashboard_item/dashboard_item';
import { Dialog } from '@web/core/dialog/dialog';
import { CheckBox } from '@web/core/checkbox/checkbox';
import { browser } from '@web/core/browser/browser';

class AwesomeDashboard extends Component {
static template = 'awesome_dashboard.AwesomeDashboard';
static components = { Layout, DashboardItem };

setup() {
this.showCustomers = this.showCustomers.bind(this);
this.showLeads = this.showLeads.bind(this);
this.action = useService('action');
this.stats = useState(useService('awesome_dashboard.statistics'));
this.items = registry.category('awesome_dashboard').getAll();
this.display = {
controlPanel: {},
};
this.dialog = useService('dialog');
this.state = useState({
disabledItems:
browser.localStorage
.getItem('disabledDashboardItems')
?.split(',') || [],
});
}

openConfiguration() {
this.dialog.add(ConfigurationDialog, {
items: this.items,
disabledItems: this.state.disabledItems,
onUpdateConfiguration: this.updateConfiguration.bind(this),
});
}

updateConfiguration(newDisabledItems) {
this.state.disabledItems = newDisabledItems;
}

showCustomers() {
this.action.doAction('base.action_partner_form');
}

showLeads() {
this.action.doAction({
type: 'ir.actions.act_window',
name: 'Leads',
target: 'current',
res_model: 'crm.lead',
views: [
[false, 'list'],
[false, 'form'],
],
});
}
}

class ConfigurationDialog extends Component {
static template = 'awesome_dashboard.ConfigurationDialog';
static components = { Dialog, CheckBox };
static props = ['close', 'items', 'disabledItems', 'onUpdateConfiguration'];

setup() {
this.items = useState(
this.props.items.map((item) => {
return {
...item,
checked: !this.props.disabledItems.includes(item.id),
};
})
);
}

done() {
this.props.close();
}

onChange(checked, changedItem) {
changedItem.enabled = checked;
const newDisabledItems = Object.values(this.items)
.filter((item) => !item.enabled)
.map((item) => item.id);

browser.localStorage.setItem(
'disabledDashboardItems',
JSON.stringify(newDisabledItems)
);
this.props.onUpdateConfiguration(newDisabledItems);
}
}

registry.category('lazy_components').add('AwesomeDashboard', AwesomeDashboard);
5 changes: 5 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.o_dashboard {
background-color: gray;
font-weight: bold;
font-size: 1.5rem;
}
40 changes: 40 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="awesome_dashboard.AwesomeDashboard">
<Layout display="display" className="'o_dashboard h-100'">
<t t-set-slot="control-panel-create-button">
<button class="btn btn-primary" t-on-click="this.showCustomers">Customers</button>
<button class="btn btn-primary" t-on-click="this.showLeads">Leads</button>
</t>
<t t-set-slot="control-panel-additional-actions">
<button class="btn p-0 ms-1 border-0" t-on-click="openConfiguration">
<i class="fa fa-cog"></i>
</button>
</t>
<div class="container d-flex flex-wrap" t-if="stats.isReady">
<t t-foreach="items" t-as="item" t-key="item.id">
<DashboardItem size="item.size || 1" t-if="!state.disabledItems.includes(item.id)">
<t t-set="itemProp" t-value="item.props ? item.props(stats) : { 'data': stats }" />
<t t-component="item.Component" t-props="itemProp" />
</DashboardItem>
</t>
</div>
</Layout>
</t>

<t t-name="awesome_dashboard.ConfigurationDialog">
<Dialog title="'Dashboard items configuration'">
Which cards do you wish to see?
<t t-foreach="items" t-as="item" t-key="item.id">
<CheckBox value="item.enabled" onChange="(ev) => this.onChange(ev, item)">
<t t-esc="item.description" />
</CheckBox>
</t>
<t t-set-slot="footer">
<button class="btn btn-primary" t-on-click="done">
Save
</button>
</t>
</Dialog>
</t>
</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Component } from '@odoo/owl';

export class DashboardItem extends Component {
static template = "awesome_dashboard.DashboardItem";
static props = {
size: {
type: Number,
optional: true,
},
slots: {
type: Object,
optional: true,
}
};
static defaultProps = {
size: 1,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="awesome_dashboard.DashboardItem">
<div
class="card border p-2 m-2"
t-att-style="'width: ' + props.size * 18 + 'rem;'"
>
<div class="card-header">
<t t-slot="title" />
</div>
<div class="card-body">
<t t-slot="default" />
</div>
</div>
</t>
</templates>
65 changes: 65 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard_items.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { NumberCard } from './number_card/number_card';
import { PieChartCard } from './pie_chart_card/pie_chart_card';
import { registry } from '@web/core/registry';

const items = [
{
id: 'average_quantity',
description: 'Average amount of t-shirt by order this month',
Component: NumberCard,
props: (data) => ({
title: 'Average amount of t-shirt by order this month',
value: data.average_quantity,
}),
},
{
id: 'average_time',
description: 'Average time for an order',
Component: NumberCard,
props: (data) => ({
title: "Average time for an order to go from 'new' to 'sent' or 'cancelled'",
value: data.average_time,
}),
},
{
id: 'number_new_orders',
description: 'New orders this month',
Component: NumberCard,
props: (data) => ({
title: 'Number of new orders this month',
value: data.nb_new_orders,
}),
},
{
id: 'cancelled_orders',
description: 'Cancelled orders this month',
Component: NumberCard,
props: (data) => ({
title: 'Number of cancelled orders this month',
value: data.nb_cancelled_orders,
}),
},
{
id: 'amount_new_orders',
description: 'amount orders this month',
Component: NumberCard,
props: (data) => ({
title: 'Total amount of new orders this month',
value: data.total_amount,
}),
},
{
id: 'pie_chart',
description: 'Shirt orders by size',
Component: PieChartCard,
size: 2,
props: (data) => ({
title: 'Shirt orders by size',
values: data.orders_by_size,
}),
},
];

items.forEach((item) => {
registry.category('awesome_dashboard').add(item.id, item);
});
27 changes: 27 additions & 0 deletions awesome_dashboard/static/src/dashboard/dashboard_service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { registry } from '@web/core/registry';
import { rpc } from '@web/core/network/rpc';
import { reactive } from '@odoo/owl';

const dashboardService = {
start() {
let stats = reactive({
isReady: false,
});

async function loadData() {
const result = await rpc('/awesome_dashboard/statistics');
Object.assign(stats, result, { isReady: true });
setTimeout(() => {
loadData();
}, 1000 * 10);
}

loadData();

return stats;
},
};

registry
.category('services')
.add('awesome_dashboard.statistics', dashboardService);
13 changes: 13 additions & 0 deletions awesome_dashboard/static/src/dashboard/number_card/number_card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Component } from '@odoo/owl';

export class NumberCard extends Component {
static template = "awesome_dashboard.NumberCard";
static props = {
title: {
type: String,
},
value: {
type: 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">
<t t-esc="props.title" />
<div class="fs-1 fw-bold text-success text-center">
<t t-esc="props.value" />
</div>
</t>
</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Component } from '@odoo/owl';
import { PieChart } from '../../pie_chart/pie_chart';

export class PieChartCard extends Component {
static template = 'awesome_dashboard.PieChartCard';
static components = { PieChart };
static props = {
title: {
type: String,
},
values: {
type: Object,
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="awesome_dashboard.PieChartCard">
<t t-esc="props.label" />
<PieChart data="props.values" label="props.title" />
</t>
</templates>
14 changes: 14 additions & 0 deletions awesome_dashboard/static/src/dashboard_action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { registry } from '@web/core/registry';
import { LazyComponent } from '@web/core/assets';
import { Component, xml } from '@odoo/owl';

class AwesomeDashboardLoader extends Component {
static template = xml`
<LazyComponent bundle="'awesome_dashboard.dashboard'" Component="'AwesomeDashboard'" props="props"/>
`;
static components = { LazyComponent };
}

registry
.category('actions')
.add('awesome_dashboard.dashboard', AwesomeDashboardLoader);
Loading