-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Web Tutorial PR: trcaz #967
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 20 commits
dfc2387
f7b4680
dc2211e
a22285a
8611d61
70e3c05
aa4125a
bf99024
03af1db
86806ec
143eec9
3156e29
60483e6
2209933
adf412a
ac47f9b
71636b1
4115506
82f496d
cabcad9
036b648
164bc52
a502aa5
292c7b8
9f7c018
82c0d40
b62f551
113773f
6f4a297
0ad1da4
6aacfbe
3231834
44e0d49
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /** @odoo-module **/ | ||
|
|
||
| import { Component, onWillStart, useState } from "@odoo/owl"; | ||
| import { registry } from "@web/core/registry"; | ||
| import { Layout } from "@web/search/layout"; | ||
| import { useService } from "@web/core/utils/hooks"; | ||
| import { _t } from "@web/core/l10n/translation"; | ||
| import { DashboardItem } from "./dashboard_item"; | ||
| import { PieChart } from "./pie_chart/pie_chart"; | ||
|
|
||
| class AwesomeDashboard extends Component { | ||
| static template = "awesome_dashboard.awesome_dashboard"; | ||
| static components = { Layout, DashboardItem, PieChart } | ||
|
|
||
| setup() { | ||
| this.action = useService("action"); | ||
| this.stats = useState(useService("awesome_dashboard.statistics")) | ||
| } | ||
| openPartners() { | ||
| this.action.doAction("base.action_partner_form"); | ||
| } | ||
| async openLeads() { | ||
| this.action.doAction({ | ||
| type: 'ir.actions.act_window', | ||
| name: _t('All Leads'), | ||
| res_model: 'crm.lead', | ||
| views: [ | ||
| [false, 'list'], | ||
| [false, 'form'] | ||
| ], | ||
| }); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| registry.category("lazy_components").add("awesome_dashboard.dashboard", AwesomeDashboard); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| .o_dashboard { | ||
| background-color: purple | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <?xml version="1.0" encoding="UTF-8" ?> | ||
| <templates xml:space="preserve"> | ||
|
|
||
| <t t-name="awesome_dashboard.awesome_dashboard"> | ||
| <button class="btn btn-primary" t-on-click="() => this.openPartners()"> | ||
| Customers | ||
| </button> | ||
| <button class="btn btn-primary" t-on-click="() => this.openLeads()"> | ||
| Leads | ||
| </button> | ||
| <Layout className="'o_dashboard h-100'" display="{controlPanel: {} }"> | ||
| <DashboardItem> | ||
| no size | ||
| </DashboardItem> | ||
| <DashboardItem size="2"> | ||
| size of 2 | ||
| </DashboardItem> | ||
| <t t-foreach="Object.keys(this.stats)" t-as="s" t-key="s"> | ||
| <!-- please don't make me use css --> | ||
| <DashboardItem> | ||
| <t t-esc="s"/> | ||
| <t t-esc="this.stats[s]"/> | ||
| </DashboardItem> | ||
| </t> | ||
| <DashboardItem> | ||
| <PieChart data="this.stats"/> | ||
| </DashboardItem> | ||
| </Layout> | ||
| </t> | ||
|
|
||
| </templates> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import { LazyComponent } from "@web/core/assets"; | ||
| import { Component, xml, onWillStart, useState } from "@odoo/owl"; | ||
| import { registry } from "@web/core/registry"; | ||
|
|
||
|
|
||
| export class AwesomeDashboardLoader extends Component { | ||
| static components = { LazyComponent }; | ||
| static template = xml` | ||
| <LazyComponent bundle="'awesome_dashboard.dashboard'" Component="'awesome_dashboard.dashboard'"/> | ||
| `; | ||
| } | ||
|
|
||
| registry.category("actions").add("awesome_dashboard.dashboard", AwesomeDashboardLoader); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import { Component } from "@odoo/owl"; | ||
|
|
||
| export class DashboardItem extends Component { | ||
| static template = "awesome_dashboard.dashboard_item" | ||
| static props = { | ||
| size: {type: Number, optional: true}, | ||
| slots: {optional: true} | ||
| } | ||
|
|
||
| setup() { | ||
| this.size = this.props.size || 1 | ||
| this.width = `${18 * this.size}rem` | ||
trcazier marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| <?xml version="1.0" encoding="UTF-8" ?> | ||
| <templates xml:space="preserve"> | ||
|
|
||
| <t t-name="awesome_dashboard.dashboard_item"> | ||
| <div class="dashboard_item d-inline-block m-2" t-att-style="'width: ' + this.width + '; border: 1px solid black; border-radius: 5px'"> | ||
| <div class="dashboard_item-body"> | ||
| <h5 class="dashboard_item-title"><t t-esc="this.title"/></h5> | ||
| <p class="dashboard_item-text"> | ||
| <t t-slot="default"/> | ||
| </p> | ||
| </div> | ||
| </div> | ||
| </t> | ||
|
|
||
| </templates> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import { registry } from "@web/core/registry"; | ||
| import { memoize } from "@web/core/utils/functions"; | ||
| import { rpc } from "@web/core/network/rpc"; | ||
| import { reactive } from "@odoo/owl"; | ||
|
|
||
| const dashboardService = { | ||
| start() { | ||
| let stats = reactive({ | ||
| average_quantity: 0, | ||
| average_time: 0, | ||
| nb_cancelled_orders: 0, | ||
| nb_new_orders: 0, | ||
| orders_by_size: {}, | ||
| total_amount: 0 | ||
| }); | ||
| async function loadData() { | ||
| console.log("slt") | ||
| const newStats = await rpc("/awesome_dashboard/statistics"); | ||
| Object.keys(newStats).forEach((k) => stats[k] = newStats[k]) | ||
|
||
| console.log(newStats) | ||
| } | ||
| setInterval(loadData, 2*1000); | ||
trcazier marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| loadData(); | ||
|
|
||
| return stats; | ||
| }, | ||
| }; | ||
|
|
||
|
|
||
| registry.category("services").add("awesome_dashboard.statistics", dashboardService); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import { Component, onMounted, onWillUnmount, onWillStart, useEffect, useRef } from "@odoo/owl"; | ||
| import { loadJS } from "@web/core/assets"; | ||
|
|
||
| export class PieChart extends Component { | ||
| static template = "awesome_dashboard.pie_chart"; | ||
trcazier marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| static props = { data: {optional: false}} | ||
|
||
|
|
||
| setup() { | ||
| this.canvasRef = useRef("canvas"); | ||
|
|
||
| onWillStart(() => loadJS("/web/static/lib/Chart/Chart.js")); | ||
|
|
||
| useEffect(() => { | ||
| if (this.pieChart) { | ||
| this.pieChart.destroy() | ||
| } | ||
| this.data = Object.values(this.props.data.orders_by_size) | ||
| this.labels = Object.keys(this.props.data.orders_by_size) | ||
|
|
||
| this.buildChart() | ||
| }); | ||
|
|
||
| onWillUnmount(() => this.pieChart.destroy()); | ||
| } | ||
|
|
||
| buildChart() { | ||
| this.pieChart = new Chart(this.canvasRef.el, { | ||
| type: "pie", | ||
| data: { | ||
| labels: this.labels, | ||
| datasets: [{ | ||
| data: this.data, | ||
| }], | ||
| }, | ||
| }); | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,6 @@ | ||
| <?xml version="1.0" encoding="UTF-8" ?> | ||
| <templates xml:space="preserve"> | ||
|
|
||
| <t t-name="awesome_dashboard.AwesomeDashboard"> | ||
| hello dashboard | ||
| <t t-name="awesome_dashboard.pie_chart"> | ||
trcazier marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| <canvas t-ref="canvas"/> | ||
| </t> | ||
|
|
||
| </templates> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { Component, useState } from "@odoo/owl"; | ||
cgun-odoo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| export class Card extends Component { | ||
| static template = "awesome_owl.card"; | ||
| static props = { | ||
| title: String, | ||
| slots: { | ||
| type: Object, | ||
| shape: { | ||
| default: true | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| setup() { | ||
| this.state = useState({open: true}); | ||
| this.title = this.props.title; | ||
| } | ||
| } | ||
| 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_owl.card"> | ||
| <div class="card d-inline-block m-2" style="width: 18rem;"> | ||
| <div class="card-body"> | ||
| <h5 class="card-title"><t t-esc="this.title"/></h5> | ||
| <button class="btn btn-primary" t-on-click="() => this.state.open = !this.state.open">Toggle</button> | ||
| <t t-if="this.state.open"> | ||
| <p class="card-text"> | ||
| <t t-slot="default"/> | ||
| </p> | ||
| </t> | ||
| </div> | ||
| </div> | ||
| </t> | ||
|
|
||
| </templates> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { Component, useState } from "@odoo/owl"; | ||
|
|
||
| export class Counter extends Component { | ||
| static template = "awesome_owl.counter"; | ||
| static props = { | ||
| value: {optional: true}, | ||
| side_effect: {type: Function, optional: true} | ||
| }; | ||
|
|
||
| setup() { | ||
| this.state = useState({ value: this.props.value || 0}); | ||
| } | ||
|
|
||
| increment() { | ||
| if (this.props.side_effect) { | ||
| this.props.side_effect(); | ||
| } | ||
| this.state.value++; | ||
| } | ||
| } |
| 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_owl.counter"> | ||
| <div class="p-3"> | ||
| <p>Counter: <t t-esc="state.value"/></p> | ||
| <button class="btn btn-primary" t-on-click="increment">Increment</button> | ||
| </div> | ||
| </t> | ||
|
|
||
| </templates> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,20 @@ | ||
| /** @odoo-module **/ | ||
|
|
||
| import { Component } from "@odoo/owl"; | ||
| import { Component, markup, useState } from "@odoo/owl"; | ||
| import { Counter } from "./counter/counter"; | ||
| import { Card } from "./card/card"; | ||
| import { TodoList } from "./todo_list/todo_list"; | ||
|
|
||
| export class Playground extends Component { | ||
| static template = "awesome_owl.playground"; | ||
| static components = { Counter, Card, TodoList } | ||
|
|
||
| setup() { | ||
| this.str1 = "<div class='text-primary'>some content</div>"; | ||
| this.str2 = markup("<div class='text-primary'>some content</div>"); | ||
| this.state = useState({ val1: 0, val2: 10 }) | ||
| } | ||
|
|
||
| get sum() { | ||
| return this.state.val1 + this.state.val2; | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { Component, useState } from "@odoo/owl"; | ||
|
|
||
| export class TodoItem extends Component { | ||
| static template = "awesome_owl.todo_item" | ||
| static props = { | ||
| id: String, | ||
| todo: {type: {description: String, isCompleted: Boolean}}, | ||
| toggleState: Function, | ||
| removeTodo: Function | ||
| } | ||
|
|
||
| setup() { | ||
| this.id = this.props.id; | ||
| this.todo = useState(this.props.todo); | ||
| this.toggleState = this.props.toggleState; | ||
| this.removeTodo = this.props.removeTodo; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <?xml version="1.0" encoding="UTF-8" ?> | ||
| <templates xml:space="preserve"> | ||
|
|
||
| <t t-name="awesome_owl.todo_item"> | ||
| <div class="todo_item-body" t-att-class="{'text-muted text-decoration-line-through': this.todo.isCompleted}"> | ||
| <p class="todo_item-text"> | ||
| <input type="checkbox" t-att-checked="this.todo.isCompleted" t-on-change="this.toggleState"/> | ||
| <t t-esc="this.id"/>. <t t-out="this.todo.description"/> <span class="fa fa-remove" t-on-click="this.removeTodo"/> | ||
| </p> | ||
| </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.
You can also use defaultProps