Skip to content

Commit 4a60287

Browse files
committed
[ADD] Chapter 3: Customize a kanban view
1 parent eea421e commit 4a60287

File tree

6 files changed

+165
-1
lines changed

6 files changed

+165
-1
lines changed
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
/** @odoo-module */
22

3-
// TODO: Define here your AwesomeKanban view
3+
import { registry } from "@web/core/registry";
4+
import { kanbanView } from "@web/views/kanban/kanban_view";
5+
import { AwesomeKanbanController } from "./kanban_controller";
6+
7+
export const awesomeKanbanView = {
8+
...kanbanView,
9+
Controller: AwesomeKanbanController,
10+
};
11+
12+
registry.category("views").add("awesome_kanban", awesomeKanbanView);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/** @odoo-module */
2+
3+
import { Component, onWillStart, useState } from "@odoo/owl";
4+
import { useService } from "@web/core/utils/hooks";
5+
import { KeepLast } from "@web/core/utils/concurrency";
6+
import { fuzzyLookup } from "@web/core/utils/search";
7+
import { Pager } from "@web/core/pager/pager";
8+
9+
export class CustomerList extends Component {
10+
static template = "awesome_kanban.CustomerList";
11+
12+
static components = { Pager };
13+
14+
static props = {
15+
selectCustomer: Function
16+
}
17+
18+
setup() {
19+
this.orm = useService("orm");
20+
this.customers = useState({ data: [] });
21+
this.keepLast = new KeepLast();
22+
this.state = useState({ displayActiveCustomers: false, searchString: ''})
23+
onWillStart(async () => {
24+
this.customers.data = await this.loadCustomers([]);
25+
this.pager.total = this.customers.data.length;
26+
})
27+
this.pager = useState({ offset: 0, limit: 20 });
28+
}
29+
30+
loadCustomers() {
31+
const domain = this.state.displayActiveCustomers ? [["opportunity_ids", "!=", false]] : [];
32+
return this.orm.searchRead("res.partner", domain, ["display_name"]);
33+
}
34+
35+
get displayedCustomers() {
36+
const displayCustomers = this.filterCustomers(this.state.searchString);
37+
this.pager.total = displayCustomers.length;
38+
return displayCustomers.slice(this.pager.offset, this.pager.offset + this.pager.limit);
39+
}
40+
41+
async checkboxChange(ev) {
42+
this.pager.offset = 0;
43+
this.state.displayActiveCustomers = ev.target.checked;
44+
this.customers.data = await this.keepLast.add(this.loadCustomers());
45+
this.pager.total = this.customers.data.length;
46+
}
47+
48+
filterCustomers(name) {
49+
if (name) {
50+
const filteredCustomers = fuzzyLookup(
51+
name,
52+
this.customers.data,
53+
(customer) => customer.display_name
54+
);
55+
while (this.pager.offset > filteredCustomers.length) this.pager.offset -= this.pager.limit;
56+
return filteredCustomers;
57+
} else {
58+
return this.customers.data;
59+
}
60+
}
61+
62+
onUpdatePager(data) {
63+
Object.assign(this.pager, data);
64+
}
65+
66+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<templates xml:space="preserve">
3+
4+
<t t-name="awesome_kanban.CustomerList">
5+
6+
<table class="table table-striped">
7+
<thead>
8+
<tr>
9+
<td>
10+
<span>Customers</span>
11+
<div class="form-check">
12+
<input class="form-check-input" type="checkbox" value="this.state.displayActiveCustomers" id="flexCheckDefault" t-on-change="checkboxChange"/>
13+
<label class="form-check-label" for="flexCheckDefault">
14+
Active customers
15+
</label>
16+
</div>
17+
<input placeholder="Filter customers" t-model="state.searchString"/>
18+
</td>
19+
<Pager offset="this.pager.offset" limit="this.pager.limit" total="this.pager.total" onUpdate.bind="onUpdatePager"/>
20+
</tr>
21+
</thead>
22+
<tbody>
23+
<tr t-foreach="this.displayedCustomers" t-as="customer" t-key="customer.id">
24+
<td class="o_awesome_kanban_customer_hover" t-esc="customer.display_name" t-on-click="() => this.props.selectCustomer(customer.id, customer.display_name)"/>
25+
</tr>
26+
</tbody>
27+
</table>
28+
29+
</t>
30+
31+
</templates>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/** @odoo-module */
2+
3+
import { KanbanController } from "@web/views/kanban/kanban_controller";
4+
import { CustomerList } from "./customer_list/customer_list"
5+
6+
7+
export class AwesomeKanbanController extends KanbanController {
8+
static template = "awesome_kanban.AwesomeKanbanController";
9+
10+
static components = { ...KanbanController.components, CustomerList };
11+
12+
setup() {
13+
super.setup();
14+
}
15+
16+
emptyFunction(customerId, customerName) {
17+
const customerFilters = this.env.searchModel.getSearchItems((searchItem) =>
18+
searchItem.isFromAwesomeKanban
19+
);
20+
21+
for (const customerFilter of customerFilters) {
22+
if (customerFilter.isActive) {
23+
this.env.searchModel.toggleSearchItem(customerFilter.id);
24+
}
25+
}
26+
27+
console.log(customerId);
28+
this.env.searchModel.createNewFilters([{
29+
description: customerName,
30+
domain: [["partner_id", "=", customerId]],
31+
isFromAwesomeKanban: true, // this is a custom key to retrieve our filters later
32+
}])
33+
};
34+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.o_awesome_kanban_sidebar {
2+
width: 300px;
3+
float: left;
4+
}
5+
6+
.o_awesome_kanban_customer_hover {
7+
&:hover {
8+
background-color: $gray-200;
9+
}
10+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<templates xml:space="preserve">
3+
4+
<t t-name="awesome_kanban.AwesomeKanbanController" t-inherit="web.KanbanView">
5+
6+
<xpath expr="//t[@t-component='props.Renderer']" position="before">
7+
<div class="o_awesome_kanban_sidebar">
8+
<CustomerList selectCustomer.bind="emptyFunction"/>
9+
</div>
10+
</xpath>
11+
12+
</t>
13+
14+
</templates>

0 commit comments

Comments
 (0)