Web components ch 1 sect 1-7

This commit is contained in:
Matt Marcha 2024-08-10 10:48:19 -10:00
parent c45910d24e
commit 1210735566
16 changed files with 263 additions and 0 deletions

3
awesome_owl/__init__.py Normal file
View file

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import controllers

View file

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
{
'name': "Awesome Owl",
'summary': """
Starting module for "Discover the JS framework, chapter 1: Owl components"
""",
'description': """
Starting module for "Discover the JS framework, chapter 1: Owl components"
""",
'author': "Odoo",
'website': "https://www.odoo.com",
# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/15.0/odoo/addons/base/data/ir_module_category_data.xml
# for the full list
'category': 'Tutorials/AwesomeOwl',
'version': '0.1',
# any module necessary for this one to work correctly
'depends': ['base', 'web'],
'application': True,
'installable': True,
'data': [
'views/templates.xml',
],
'assets': {
'awesome_owl.assets_playground': [
# bootstrap
('include', 'web._assets_helpers'),
'web/static/src/scss/pre_variables.scss',
'web/static/lib/bootstrap/scss/_variables.scss',
('include', 'web._assets_bootstrap_backend'),
# required for fa icons
'web/static/src/libs/fontawesome/css/font-awesome.css',
# include base files from framework
('include', 'web._assets_core'),
'web/static/src/core/utils/functions.js',
'web/static/src/core/browser/browser.js',
'web/static/src/core/registry.js',
'web/static/src/core/assets.js',
'awesome_owl/static/src/**/*',
],
},
'license': 'AGPL-3'
}

View file

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import controllers

View file

@ -0,0 +1,10 @@
from odoo import http
from odoo.http import request, route
class OwlPlayground(http.Controller):
@http.route(['/awesome_owl'], type='http', auth='public')
def show_playground(self):
"""
Renders the owl playground page
"""
return request.render('awesome_owl.playground')

View file

@ -0,0 +1,8 @@
/** @odoo-module **/
import { Component, useState } from "@odoo/owl";
export class Card extends Component {
static template = "awesome_owl.card";
static props = ['title', 'content'];
}

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="awesome_owl.card">
<section>
<div class="card d-inline-block m-2" style="width: 18rem;">
<div class="card-body">
<h3 class="card-title"><t t-esc="props.title"/></h3>
<p class="card-text">
<t t-esc="props.content"/>
</p>
</div>
</div>
</section>
</t>
</templates>

View file

@ -0,0 +1,21 @@
/** @odoo-module **/
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();
}
}
}

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="awesome_owl.counter">
<section>
<h2>Counter</h2>
<p>Counter: <t t-esc="state.value"/></p>
<button class="btn btn-primary" t-on-click="increment">Increment</button>
</section>
</t>
</templates>

View file

@ -0,0 +1,41 @@
/** @odoo-module **/
import { browser } from "@web/core/browser/browser";
import { mount, whenReady } from "@odoo/owl";
import { Playground } from "./playground";
import { templates } from "@web/core/assets";
// Mount the Playground component when the document.body is ready
whenReady( () => {
mount(Playground, document.body, { templates, dev: true, name: "Owl Tutorial" });
});
/**
* This code is iterating over the cause property of an error object to console.error a string
* containing the stack trace of the error and any errors that caused it.
* @param {Event} ev
*/
function logError(ev) {
ev.preventDefault();
let error = ev ?.error || ev.reason;
if (error.seen) {
// If an error causes the mount to crash, Owl will reject the mount promise and throw the
// error. Therefore, this if statement prevents the same error from appearing twice.
return;
}
error.seen = true;
let errorMessage = error.stack;
while (error.cause) {
errorMessage += "\nCaused by: "
errorMessage += error.cause.stack;
error = error.cause;
}
console.error(errorMessage);
}
browser.addEventListener("error", (ev) => {logError(ev)});
browser.addEventListener("unhandledrejection", (ev) => {logError(ev)});

View file

@ -0,0 +1,19 @@
/** @odoo-module **/
import { Component, 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.sum = useState({value: 0});
}
incrementSum(){
this.sum.value++;
}
}

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="awesome_owl.playground">
<Counter onChange.bind="incrementSum"/>
<Counter onChange.bind="incrementSum"/>
<p>The sum is <t t-esc="sum.value"/></p>
<hr />
<Card title="'Card 1'" content="'This is the awesome content of the card 1'" />
<Card title="'Card, the 2nd'" content="'Here is another card content. It is the second one.'" />
<hr/>
<TodoList />
</t>
</templates>

View file

@ -0,0 +1,13 @@
/** @odoo-module **/
import { Component } from "@odoo/owl";
export class TodoItem extends Component {
static template = "awesome_owl.TodoItem";
static props = {
todo: {
type: Object,
shape: { id: Number, description: String, isCompleted: Boolean }
}
};
}

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="awesome_owl.TodoItem">
<div>
<t t-esc="props.todo.id" />. <t t-esc="props.todo.description" />
</div>
</t>
</templates>

View file

@ -0,0 +1,17 @@
/** @odoo-module **/
import { Component, useState } from "@odoo/owl";
import { TodoItem } from "./todo_item";
export class TodoList extends Component {
static template = "awesome_owl.todo_list";
static components = { TodoItem };
setup() {
this.todos = useState([
{id: 3, description: "buy milk", isCompleted: false },
{ id: 1, description: "have a shower", isCompleted: true },
{ id: 2, description: "sing loudly", isCompleted: false }
]);
}
}

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="awesome_owl.todo_list">
<div class="d-inline-block border p-2 m-2">
<t t-foreach="todos" t-as="todo" t-key="todo.id">
<TodoItem todo="todo" />
</t>
</div>
</t>
</templates>

View file

@ -0,0 +1,15 @@
<odoo>
<data>
<template id="awesome_owl.playground" name="Awesome T-Shirt thank you">
<html>
<head>
<link type="image/x-icon" rel="shortcut icon" href="/web/static/img/favicon.ico"/>
<t t-call-assets="awesome_owl.assets_playground"/>
</head>
<body>
</body>
</html>
</template>
</data>
</odoo>