Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6e4093e
[ADD] estate: Init and manifest
wimar-odoo Oct 22, 2025
66a0801
[IMP] estate: Models and Basic Fields
wimar-odoo Oct 22, 2025
82e151b
[IMP] estate: Security - A Brief Introduction
wimar-odoo Oct 22, 2025
cd40928
[IMP] estate: Finally, Some UI to Play With
wimar-odoo Oct 23, 2025
9a9a4f3
[IMP] estate: Basic Views
wimar-odoo Oct 23, 2025
9a90bd7
[FIX] estate: Remove useless string parameter from model attributes
wimar-odoo Oct 23, 2025
db9ded5
[FIX] estate: adjustments after first review
wimar-odoo Oct 23, 2025
fe7da46
[IMP] estate: Chapter 7 - Types, Tags and Offers
wimar-odoo Oct 24, 2025
edaf208
[IMP] estate: Chapter 8 - Computed, Inverse, and Onchange Fields
wimar-odoo Oct 24, 2025
1d073e0
[IMP] estate: Chapter 9 - Button Actions
wimar-odoo Oct 24, 2025
4353811
[IMP] estate: Chapter 10 - SQL and Python Constraints
wimar-odoo Oct 24, 2025
cad2ef0
[IMP] estate: Chapter 11 - Sprinkles
wimar-odoo Oct 27, 2025
fb58afd
[FIX] estate: PR review adjustments
wimar-odoo Oct 27, 2025
a9e718c
[IMP] estate: Chapter 12 - Inheritance
wimar-odoo Oct 27, 2025
9081d57
[ADD] estate_account: Chapter 13 - Other modules
wimar-odoo Oct 28, 2025
f1448b2
[IMP] estate: Chapter 14 - Kanban view
wimar-odoo Oct 28, 2025
b48fa58
[IMP] awesome_owl: Chapter 1 - Intro Owl Components
wimar-odoo Oct 30, 2025
bd25287
[FIX] estate: last review adjustments
wimar-odoo Oct 30, 2025
816de58
[IMP] awesome_dashboard: Chapter 2 - Build a dashboard
wimar-odoo Oct 31, 2025
eefcaf9
[FIX] awesome_owl: Last review adjustments
wimar-odoo Nov 3, 2025
2918ab0
[FIX] awesome_dashboard: Last review adjustments
wimar-odoo Nov 3, 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
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,13 @@ dmypy.json

# Pyre type checker
.pyre/

# JetBrains specific folders
.idea/
*/.idea/

# Odoo specific folders
.run
*/.run/
.odev
*/.odev/
8 changes: 6 additions & 2 deletions awesome_owl/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@
'assets': {
'awesome_owl.assets_playground': [
('include', 'web._assets_helpers'),
('include', 'web._assets_frontend_helpers'),
'web/static/src/scss/pre_variables.scss',
'web/static/lib/bootstrap/scss/_variables.scss',
('include', 'web._assets_bootstrap'),
('include', 'web._assets_core'),
'web/static/lib/bootstrap/scss/_variables-dark.scss',
'web/static/lib/bootstrap/scss/_maps.scss',
('include', 'web._assets_bootstrap_frontend'),
'web/static/src/libs/fontawesome/css/font-awesome.css',
'web/static/src/scss/fontawesome_overridden.scss',
('include', 'web._assets_core'),
'awesome_owl/static/src/**/*',
],
},
Expand Down
21 changes: 21 additions & 0 deletions awesome_owl/static/src/card/card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Component, useState } from "@odoo/owl";


export class Card extends Component {
static template = "awesome_owl.card";
static props = {
title: String,
slots: {
type: Object,
optional: true,
},
};

setup() {
this.state = useState({ isToggled: false });
}

toggle() {
this.state.isToggled = !this.state.isToggled;
}
}
15 changes: 15 additions & 0 deletions awesome_owl/static/src/card/card.xml
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_owl.card">
<div class="card d-inline-block m-2" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title"><t t-out="props.title"/><button class="btn btn-secondary" style="margin-left: 10px" t-on-click="toggle">Toggle</button></h5>
<div class="card-text" t-if="this.state.isToggled">
<t t-slot="default"/>
</div>
</div>
</div>
</t>

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


export class Counter extends Component {
static template = "awesome_owl.counter";
static defaultProps = {
buttonText: "Increment",
}
static props = {
buttonText: { type: String, optional: true, },
onChange: { type: Function, optional: true },
};

setup() {
this.state = useState({ value: 1 });
}

increment() {
this.state.value++;
if (this.props.onChange) {
this.props.onChange();
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for your information, it's maybe less readable in this case but in JS you can do something like this

Suggested change
if (this.props.onChange) {
this.props.onChange();
}
this.props.onChange?.();

}
}
13 changes: 13 additions & 0 deletions awesome_owl/static/src/counter/counter.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.counter">
<div>
Counter: <t t-esc="state.value"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Counter: <t t-esc="state.value"/>
Counter: <t t-out="state.value"/>

<button class="btn btn-primary" t-on-click="increment" style="margin-left: 5px">
<t t-out="props.buttonText"/>
</button>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can "inline" the t-out like this

Suggested change
<button class="btn btn-primary" t-on-click="increment" style="margin-left: 5px">
<t t-out="props.buttonText"/>
</button>
<button class="btn btn-primary" t-on-click="increment" style="margin-left: 5px" t-out="props.buttonText" />

</div>
</t>

</templates>
16 changes: 15 additions & 1 deletion awesome_owl/static/src/playground.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import { Component } from "@odoo/owl";
import { Component, useState } from "@odoo/owl";
import { Counter } from "./counter/counter";
import { Card } from "./card/card";
import { TodoList } from "./todo/todolist"


export class Playground extends Component {
static template = "awesome_owl.playground";

static components = { Counter, Card, TodoList };

setup() {
this.state = useState({ value : 2 });
}

incrementSum() {
this.state.value++;
}
}
3 changes: 3 additions & 0 deletions awesome_owl/static/src/playground.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.chapter_tuto {
border: solid; padding: 10px; border-radius: 5px; margin-bottom: 5px
}
Comment on lines 1 to 6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for lisibility :)

Suggested change
.chapter_tuto {
border: solid; padding: 10px; border-radius: 5px; margin-bottom: 5px
}
.chapter_tuto {
border: solid;
padding: 10px;
border-radius: 5px;
margin-bottom: 5px
}

22 changes: 21 additions & 1 deletion awesome_owl/static/src/playground.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,29 @@
<templates xml:space="preserve">

<t t-name="awesome_owl.playground">
<div class="p-3">
<div class="p-3 chapter_tuto">
hello world
</div>

<div class="chapter_tuto">
<Counter onChange.bind="incrementSum" t-props="{'buttonText': 'Custom Incr.'}"/>
<Counter onChange.bind="incrementSum"/>
<p>The sum id: <t t-esc="state.value"/></p>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<p>The sum id: <t t-esc="state.value"/></p>
<p>The sum id: <t t-out="state.value"/></p>

</div>

<div class="chapter_tuto">
<Card t-props="{'title': 'Card 1'}">
<p>Some content</p>
</Card>

<Card t-props="{'title': 'Card 2'}">
<Counter/>
</Card>
</div>

<div class="chapter_tuto">
<TodoList/>
</div>
</t>

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


export class TodoItem extends Component {
static template = "awesome_owl.todoitem";
static props = {
id: Number,
description: String,
isCompleted: Boolean,
onToggle: {
Function,
optional: true,
},
onClick: {
Function,
optional: true,
},
};

toggleState() {
this.props.onToggle(this.props.id);
}

removeTodo() {
this.props.onClick(this.props.id);
}
}
13 changes: 13 additions & 0 deletions awesome_owl/static/src/todo/todoitem.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.todoitem">
<p t-att-class="{'text-muted': props.isCompleted, 'text-decoration-line-through': props.isCompleted}">
<input type="checkbox" style="margin-right: 10px" t-att-checked="props.isCompleted" t-on-change="toggleState"/>
<t t-out="props.id"/>.
<t t-out="props.description"/>
<span class="fa fa-remove text-danger" t-on-click="removeTodo"/>
</p>
</t>

</templates>
39 changes: 39 additions & 0 deletions awesome_owl/static/src/todo/todolist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Component, useState, useRef } from "@odoo/owl";
import { TodoItem } from "./todoitem"
import { useAutofocus } from "@awesome_owl/utils"


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

setup() {
this.todos = useState([]);
this.nextId = 0;
this.description_inputRef = useRef("todo_input");
useAutofocus(this.description_inputRef);
}

addTodo(ev) {
const description = this.description_inputRef.el.value.trim();
if (ev.keyCode === 13 && description) {
this.todos.push({ id: this.nextId, description: description, isCompleted: false });
this.nextId++;
this.description_inputRef.el.value = "";
}
}

toggleTodo(id) {
const todo = this.todos.find(t => t.id === id);
if (todo) {
todo.isCompleted = !todo.isCompleted;
}
}

removeTodo(id) {
const index = this.todos.findIndex(t => t.id === id);
if (index >= 0) {
this.todos.splice(index, 1);
}
}
}
15 changes: 15 additions & 0 deletions awesome_owl/static/src/todo/todolist.xml
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_owl.todolist">
<input placeholder="Add a todo" t-on-keyup="addTodo" t-ref="todo_input"/>
<t t-foreach="this.todos" t-as="i" t-key="i.id">
<TodoItem
t-props="{'id': i.id, 'description': i.description, 'isCompleted': i.isCompleted}"
onToggle.bind="toggleTodo"
onClick.bind="removeTodo"
/>
</t>
</t>

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


export function useAutofocus(ref) {
useEffect(
() => {
if (ref.el) {
ref.el.focus();
}
},
() => [ref.el]
);
}
1 change: 1 addition & 0 deletions estate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
23 changes: 23 additions & 0 deletions estate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "Real Estate",
"version": "1.0",
"summary": "Manage properties and buyers.",
"license": "OEEL-1",
"depends": [
"base",
],
"author": "wimar-odoo",
"description": """
Manage efficiently real estate properties for sale and match them with potential buyers.
""",
"application": True,
"data": [
"security/ir.model.access.csv",
"views/estate_property_views.xml",
"views/estate_property_type_views.xml",
"views/estate_property_tag_views.xml",
"views/estate_property_offer_views.xml",
"views/res_users_views.xml",
"views/estate_menus.xml",
],
}
5 changes: 5 additions & 0 deletions estate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from . import estate_property
from . import estate_property_type
from . import estate_property_tag
from . import estate_property_offer
from . import res_users
Loading