Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
dfc2387
[IMP] awesome_owl: free me from this pain
trcazier Sep 22, 2025
f7b4680
[IMP] awesome_owl: save this counter implementation because I like it…
trcazier Sep 22, 2025
dc2211e
[IMP] awesome_owl: add up to section 7
trcazier Sep 22, 2025
a22285a
[IMP] awesome_owl: apply PR suggestions
trcazier Sep 23, 2025
8611d61
[IMP] awesome_owl: add sections 8-10
trcazier Sep 23, 2025
70e3c05
[IMP] awesome_owl: add section 11
trcazier Sep 23, 2025
aa4125a
[IMP] awesome_owl: replace redundant ternary operator with ||
trcazier Sep 23, 2025
bf99024
[IMP] awesome_owl: replace redundant ternary operator with if
trcazier Sep 23, 2025
03af1db
[IMP] awesome_owl: add missing ;
trcazier Sep 23, 2025
86806ec
[IMP] awesome_owl: add section 12 and missing ;s
trcazier Sep 23, 2025
143eec9
[IMP] awesome_owl: add section 13
trcazier Sep 23, 2025
3156e29
[IMP] awesome_owl: set the starting todo index as 1
trcazier Sep 23, 2025
60483e6
[IMP] awesome_owl: add section 14
trcazier Sep 23, 2025
2209933
[IMP] awesome_dashboard: add section 1
trcazier Sep 23, 2025
adf412a
[IMP] awesome_dashboard: add section 2
trcazier Sep 23, 2025
ac47f9b
[IMP] awesome_dashboard: add sections 3-4
trcazier Sep 23, 2025
71636b1
[IMP] awesome_dashboard: add section 5
trcazier Sep 23, 2025
4115506
[IMP] awesome_dashboard: section 6
trcazier Sep 23, 2025
82f496d
[IMP] awesome_dashboard: add section 7
trcazier Sep 24, 2025
cabcad9
[IMP] awesome_dashboard: add section 8
trcazier Sep 24, 2025
036b648
[IMP] awesome_dashboard: add section 9
trcazier Sep 24, 2025
164bc52
[IMP] awesome_dashboard: remove console logs
trcazier Sep 24, 2025
a502aa5
[IMP] awesome_dashboard: add section 10
trcazier Sep 24, 2025
292c7b8
[IMP] awesome_dashboard: add section 10
trcazier Sep 24, 2025
9f7c018
[MERGE] branch '18.0-web-tutorial-trcaz' of github.com:odoo-dev/tutor…
trcazier Sep 24, 2025
82c0d40
[IMP] awesome_dashboard: move buttons into layout button bar
trcazier Sep 24, 2025
b62f551
[IMP] awesome_dashboard: rewrite xml ids using PascalCase
trcazier Sep 24, 2025
113773f
[IMP] awesome_dashboard: apply PR feedback
trcazier Sep 24, 2025
6f4a297
[IMP] awesome_dashboard: add section 11
trcazier Sep 24, 2025
0ad1da4
[IMP] awesome_dashboard: refactor settings dialog props
trcazier Sep 25, 2025
6aacfbe
[IMP] awesome_dashboard: change var name for clarity
trcazier Sep 25, 2025
3231834
[IMP] awesome_dashboard: add newline to file end
trcazier Sep 25, 2025
44e0d49
[IMP] awesome_dashboard: apply PR suggestion
trcazier Sep 25, 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
23 changes: 23 additions & 0 deletions awesome_dashboard/static/src/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,32 @@

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 { _t } from "@web/core/l10n/translation";

class AwesomeDashboard extends Component {
static template = "awesome_dashboard.AwesomeDashboard";
static components = { Layout }

setup() {
this.action = useService("action");
}
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("actions").add("awesome_dashboard.dashboard", AwesomeDashboard);
3 changes: 3 additions & 0 deletions awesome_dashboard/static/src/dashboard.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.o_dashboard {
background-color: purple
}
10 changes: 9 additions & 1 deletion awesome_dashboard/static/src/dashboard.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@
<templates xml:space="preserve">

<t t-name="awesome_dashboard.AwesomeDashboard">
hello 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: {} }">
some content
</Layout>
</t>

</templates>
19 changes: 19 additions & 0 deletions awesome_owl/static/src/card/card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Component, useState } from "@odoo/owl";

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;
}
}
18 changes: 18 additions & 0 deletions awesome_owl/static/src/card/card.xml
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>
20 changes: 20 additions & 0 deletions awesome_owl/static/src/counter/counter.js
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++;
}
}
11 changes: 11 additions & 0 deletions awesome_owl/static/src/counter/counter.xml
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>
19 changes: 16 additions & 3 deletions awesome_owl/static/src/playground.js
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;
}

}
16 changes: 16 additions & 0 deletions awesome_owl/static/src/playground.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@
<div class="p-3">
hello world
</div>
<Counter value="this.state.val1" side_effect.bind="() => this.state.val1++"/>
<Counter value="this.state.val2" side_effect.bind="() => this.state.val2++"/>
<div>The sum is: <t t-esc="sum"/></div>
<Counter/>
<Card title="'epic card title'">
New content for the new card
</Card>
<Card title="'cute card title'">
this should work with arbitrary html content
</Card>
<Card title="'scary card title'">
Here is a cool counter for you
<Counter/>
</Card>

<TodoList/>
</t>

</templates>
18 changes: 18 additions & 0 deletions awesome_owl/static/src/todo_list/todo_item.js
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;
}
}
13 changes: 13 additions & 0 deletions awesome_owl/static/src/todo_list/todo_item.xml
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>
33 changes: 33 additions & 0 deletions awesome_owl/static/src/todo_list/todo_list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Component, useState, useRef, onMounted } from "@odoo/owl";
import { TodoItem } from "./todo_item";
import { useAutoFocus } from "../utils";

export class TodoList extends Component {
static template = "awesome_owl.todo_list";
static components = { TodoItem };

setup() {
useAutoFocus("todo-input");
this.state = useState({todos: {
1: { description: "buy milk", isCompleted: false },
2: { description: "buy tomatoes", isCompleted: true }
},
lastId: 2
});
}

toggleState(id) {
this.state.todos[id].isCompleted = !this.state.todos[id].isCompleted;
}

addTodo(ev) {
if (ev.keyCode === 13 && ev.target.value != "") {
this.state.todos[++this.state.lastId] = {description: ev.target.value, isCompleted: false};
ev.target.value = "";
}
}

removeTodo(id) {
delete this.state.todos[id];
}
}
25 changes: 25 additions & 0 deletions awesome_owl/static/src/todo_list/todo_list.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-name="awesome_owl.todo_list">
<div class="card d-inline-block m-2">
<div class="todo_list-body border p-2 m-2">
<input
type="text"
t-on-keyup="addTodo"
placeholder="Enter something to do..."
t-ref="todo-input"
/>
<t t-foreach="Object.keys(this.state.todos)" t-as="id" t-key="id">
<TodoItem
id="id"
todo="this.state.todos[id]"
toggleState.bind="() => this.toggleState(id)"
removeTodo.bind="() => this.removeTodo(id)"
/>
</t>
</div>
</div>
</t>

</templates>
9 changes: 9 additions & 0 deletions awesome_owl/static/src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { onMounted, useRef } from '@odoo/owl'

export function useAutoFocus(refName) {
const inputRef = useRef(refName);

onMounted(() => {
inputRef.el.focus();
});
}