Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 18 additions & 0 deletions awesome_owl/static/src/card/card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Component, useState} from "@odoo/owl";

export class Card extends Component{
static template = "awesome_owl.card";

static props = {
title: {type: String},
slots: { type: Object, optional: true },
};

setup() {
this.state = useState({ isOpen: true });
}

toggleContent() {
this.state.isOpen = !this.state.isOpen;
}
}
30 changes: 30 additions & 0 deletions awesome_owl/static/src/card/card.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?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 text-start align-top shadow-sm" style="width: 18rem;">
<div class="card-body">

<div class="d-flex align-items-center justify-content-between border-bottom pb-2 mb-3">
<h5 class="card-title fw-bold text-dark m-0">
<t t-esc="props.title"/>
</h5>

<button class="btn btn-sm btn-link"
t-on-click="toggleContent">
<span t-att-class="state.isOpen ? 'fa fa-eye' : 'fa fa-eye-slash'"/>
</button>
</div>

<div class="card-text" t-if="state.isOpen">
<t t-slot="default"/>
</div>
<t t-else="">
<p class="text-muted small font-italic m-0 text-center py-1">Content hidden.</p>
</t>

</div>
</div>
</t>

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

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

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

increment() {
this.state.value++;
if (this.props.onChange) {
this.props.onChange();
}
}
}
16 changes: 16 additions & 0 deletions awesome_owl/static/src/counter/counter.xml
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_owl.Counter">
<div class="p-4 my-3 bg-white border rounded shadow-sm text-center">

<p class="fs-4 fw-semibold text-success mb-3">
Counter: <t t-esc="state.value"/>
</p>

<button class="btn btn-outline-success px-4 py-2 fw-medium rounded-pill shadow-sm" t-on-click="increment">
Increment
</button>

</div>
</t>
</templates>
19 changes: 18 additions & 1 deletion awesome_owl/static/src/playground.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import { Component } from "@odoo/owl";
import { Component, useState, markup } 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 = { Card, Counter, TodoList};

setup() {
this.state = useState({ value: 2, sum: 0 });
this.cardContent = markup("This content is <b>bold</b>");
}

increment() {
this.state.value++;
}

incrementSum() {
this.state.sum++;
}
}
42 changes: 38 additions & 4 deletions awesome_owl/static/src/playground.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,43 @@
<templates xml:space="preserve">

<t t-name="awesome_owl.playground">
<div class="p-3">
hello world
</div>
<div class="p-4 border rounded shadow-sm m-4 mx-auto" style="max-width: 800px; background-color: #ffe4e1;">
<h2 class="text-muted text-center fw-normal mb-4">Owl Playground</h2>

<h3 class="text-center text-dark mb-3">
The Sum is: <t t-esc="state.sum"/>
</h3>

<div class="d-flex justify-content-around">
<Counter onChange="incrementSum.bind(this)"/>
<Counter onChange="incrementSum.bind(this)"/>
</div>

<hr class="text-muted my-4" />

<h4 class="text-muted mb-3">Slots Containers</h4>
<div class="text-center">

<Card title="'Standard Text'">
<p class="text-secondary small m-0">
text text text UwU
</p>
</Card>

<Card title="'Interactive Counter'">
<Counter onChange="incrementSum.bind(this)"/>
</Card>

</div>

<hr class="text-muted my-4" />

<h2 class="text-center text-secondary mb-3">Todo Workspace</h2>
<div class="d-flex justify-content-center">
<TodoList/>
</div>

</div>
</t>

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

export class TodoItem extends Component {
static template = "awesome_owl.todo_item";

static props = {
todo: Object,
toggleState: Function,
removeTodo: Function,
};
}
32 changes: 32 additions & 0 deletions awesome_owl/static/src/todo_item/todo_item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-name="awesome_owl.todo_item">
<div class="p-2 my-1 border-bottom d-flex align-items-center justify-content-between bg-white rounded shadow-sm px-3"
t-att-class="props.todo.isCompleted ? 'text-muted text-decoration-line-through font-italic' : ''">

<div class="d-flex align-items-center flex-grow-1 text-start">
<input type="checkbox"
class="form-check-input me-3"
t-att-checked="props.todo.isCompleted"
t-on-change="() => props.toggleState(props.todo.id)" />

<span class="text-secondary fw-bold me-3">#<t t-esc="props.todo.id"/></span>
<span class="text-dark"><t t-esc="props.todo.description"/></span>
</div>

<div class="d-flex align-items-center gap-2">
<t t-if="props.todo.isCompleted">
<span class="badge bg-success rounded-pill px-2 py-1">Done</span>
</t>
<t t-else="">
<span class="badge bg-warning text-dark rounded-pill px-2 py-1">Pending</span>
</t>

<span class="fa fa-remove text-danger cp ms-2"
t-on-click="() => props.removeTodo(props.todo.id)" />
</div>
</div>
</t>

</templates>
51 changes: 51 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,51 @@
import { Component, useState, useRef, onMounted } from "@odoo/owl";
import { TodoItem } from "../todo_item/todo_item";

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

setup() {
this.todos = useState([{ id: 1, description: "Buy milk", isCompleted: true }]);
this.nextId = 2;
this.inputRef = useRef("input");

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

addTodo(ev) {
if (ev.keyCode === 13) {
const description = ev.target.value.trim();

if (!description) {
return;
}

this.todos.push({
id: this.nextId++,
description: description,
isCompleted: false
});

ev.target.value = "";
}
}

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

deleteTodo(todoId) {
const index = this.todos.findIndex((t) => t.id === todoId);
if (index >= 0) {
this.todos.splice(index, 1);
}
}
}
29 changes: 29 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,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">

<t t-name="awesome_owl.todo_list">
<div class="w-100 p-3 bg-white border rounded shadow-sm text-center" style="max-width: 500px; margin: 0 auto;">

<div class="mb-3">
<input type="text"
t-ref="input"
class="form-control form-control-lg border-primary shadow-sm"
placeholder="Add a new task.."
t-on-keyup="addTodo" />
</div>

<t t-if="todos.length > 0">
<t t-foreach="todos" t-as="todo" t-key="todo.id">
<TodoItem todo="todo"
toggleState="toggleTodo.bind(this)"
removeTodo="deleteTodo.bind(this)"/>
</t>
</t>
<t t-else="">
<p class="text-muted my-4 small font-italic">No tasks. Add one!</p>
</t>

</div>
</t>

</templates>