27
A Single Page App Using the Odoo JS Framework a.k.a “Odoo JS Development for Dummies” Damien BOUVY R&D Developper EXPERIENCE 2017

A Single Page App Using the Odoo JS Framework

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: A Single Page App Using the Odoo JS Framework

A Single Page App Using the Odoo JS Frameworka.k.a “Odoo JS Development for Dummies”

Damien BOUVY • R&D Developper

EXPERIENCE

2017

Page 2: A Single Page App Using the Odoo JS Framework

Introduction1

Odoo JS 101

Odoo JS Utils (usable outside of the web client)

Live Coding Demo

Now what?

2

3

4

5

Page 3: A Single Page App Using the Odoo JS Framework

I’ll go make my own web client!1

Page 4: A Single Page App Using the Odoo JS Framework

— Some manager to one of his backend team

We need a JS app for this particular project and no one from the JS team is available.

Page 5: A Single Page App Using the Odoo JS Framework

Odoo JS Framework

Models Views* (* and more)

Class(.js)

require(‘web.Class’)

Qweb(.js)

require(‘web.core’).qweb

Widget(.js)

require(‘web.Widget’)

Can we build a small MV* Web App using the Odoo Framework?

=> Yes!

Page 6: A Single Page App Using the Odoo JS Framework

Wait a minute!

Page 7: A Single Page App Using the Odoo JS Framework

Odoo JS FrameworkModern JS libs/frameworks

MV*-like ✅ ✅

Templating ✅ ✅

Community modules /web, OCA? npm

Two-way binding“Reactive” Nope ✅ (often)

Packaging tools Not reallyManual bundles \o/

Webpack, babel, etc.

Perks Odoo-compatible OoB Light, Trendy, etc.

Odoo JS != VueJS, React, etc.

Page 8: A Single Page App Using the Odoo JS Framework

Odoo JS 1012Base JS classes, architecture

Page 9: A Single Page App Using the Odoo JS Framework

Odoo JS ModuleBaby steps

odoo.define('demo.module', function (require) { // <== define here

'use strict';

var Class = require('web.Class'); // <== import here

var AbstractThingy = Class.extend({

// do abstract stuff

});

var RealThingy = BaseThingy.extend({

//do real stuff

});

return RealThingy; // <== export here

});

Page 10: A Single Page App Using the Odoo JS Framework

Class.jsHey kids, want some OOP?

var Class = require('web.Class');

var Ticket = Class.extend({

init: function (values) {

Object.assign(this, values);

},

});

var MagicTicket = Ticket.extend({

init: function (values) {

this._super.apply(this, arguments);

this.magic = this.init_magic();

},

init_magic: function () {

// do stuff

},

});

Page 11: A Single Page App Using the Odoo JS Framework

Widget.jsIf you mess your lifecycle, you’re gonna have a bad time

var Widget = require('web.Widget');

var Component = Widget.extend({

template: 'demo.template',

events: {},

init: function () { // synchronous

this._super.apply(this, arguments);

},

willStart: function () { // asynchronous, pre-render

return this._super.apply(this, arguments).then(function () {

})

}

start: function () {} // asynchronous, post-render - use super as well!

});

Page 12: A Single Page App Using the Odoo JS Framework

QWeb(.js)Javascriptify ALL the things!

var Widget = require('web.Widget');

var qweb = core.qweb;

var Component = Widget.extend({

template: 'demo.thingies_list',

thingies: [],

});

// ... or ...

var template = 'demo.thingies_lit';

var eval_context = {thingies: thingies};

var content = qweb.render(template,

eval_context);

<t t-name="demo.thingies_list">

<t t-if="(widget.)thingies.length">

<ul>

<t t-foreach="(widget).thingies"

t-as="thingy">

<t t-call="demo.thingy"/>

</t>

</ul>

</t>

<p t-else="">No tickets to see</p>

</t>

Page 13: A Single Page App Using the Odoo JS Framework

Parent Widget

Child Widget

Init with all necessary data

Main Widget

Child WidgetChild Widget

(custom) events public functionsCommunication flow

- Events for upward communication

- Direct calls for downward communication

Components hierarchy

- Parent-unaware children- Children-aware parents

Architecture in a nutshell

Page 14: A Single Page App Using the Odoo JS Framework

Odoo JS Utils3Usable outside the web client

Page 15: A Single Page App Using the Odoo JS Framework

Backend Communication (1)rpc = require('web.rpc');

fetchTicket: function (id) {

var self = this;

return rpc.query({

model: 'demo.ticket',

method: 'search_read',

args: [[['id', '=', id]]],

kwargs: {fields: ['id', 'name', 'description']}

}).then(function (ticket_values) {

if (ticket_values.length) {

var ticket = new Ticket(ticket_values[0]);

self.tickets.push(ticket);

}

return ticket;

});

},

Page 16: A Single Page App Using the Odoo JS Framework

Backend Communicationrpc = require('web.rpc');

fetchRouteThingy: function (some_info) {

var self = this;

return rpc.query({

route: '/thingies/custom_route',

params: {foo: some_info}

}).then(function (result) {

var foo = self.do_something(result);

return foo;

});

},

Page 17: A Single Page App Using the Odoo JS Framework

Dialogsvar Dialog = require(‘web.Dialog’)

new Dialog(this, {

title: _t('New Ticket'),

$content: qweb.render('ticket_viewer.ticket_form'),

buttons: [{

text: _t('Submit Ticket'),

close: true,

click: function () {

self._onFormSubmit();

},

}],

}).open();

Page 18: A Single Page App Using the Odoo JS Framework

Notification Centervar notification = require('web.notification');

// In Main widget

custom_events: {

'ticket-submit': '_onTicketSubmit',

'warning': function (ev) {this.notification_manager.warn(ev.data.msg);},

'notify': function (ev) {this.notification_manager.notify(ev.data.msg);},

},

// In start() override:

self.notification_manager = new notification.NotificationManager(self);

self.notification_manager.appendTo(self.$el);

// In any child

this.trigger_up('warning', {msg: _t('All fields are mandatory')});

Page 19: A Single Page App Using the Odoo JS Framework

Longpolling (1)from odoo.addons.bus.controllers.main import BusController

from odoo.addons.bus.controllers.main import BusController

class TicketController(BusController): def _poll(self, dbname, channels, last, options): """ Add the relevant channels to the BusController polling. """ if options.get('demo.ticket'): channels = list(channels) ticket_channel = ( request.db, 'demo.ticket', options.get('demo.ticket') ) channels.append(ticket_channel) return super(TicketController, self)._poll(dbname, channels, last, options)

Python code required!

Page 20: A Single Page App Using the Odoo JS Framework

Longpolling (2)var bus = require('bus.bus').bus;

// In start() override:

bus.on('notification', self, self._onNotification);

// Handler

_onNotification: function (notifications) {

for (var notif of notifications) {

var channel = notif[0], message = notif[1];

if (channel[1] !== 'demo.ticket' || channel[2] !== this.user.partner_id) {

return; }

if (message[0] === 'unlink_ticket') {

this.user.removeTicket(message[1]);

this.list.removeTicket(message[1]);

}

}

},

// After starting the main widget

bus.start_polling();

Page 21: A Single Page App Using the Odoo JS Framework

Live Coding Demo4Bus IntegrationNotification Manager

Page 22: A Single Page App Using the Odoo JS Framework

Frontend Routing

Bonus

The age of # is behind us

Page 23: A Single Page App Using the Odoo JS Framework

Frontend [email protected]('/app/<path:route>')

@route('/tickets/<path:route>', auth='user')def view_tickets(self, **kwargs): tickets = request.env['demo.ticket'].search([]) return request.render('ticket_viewer.ticket_list', {'tickets': tickets})

Python code required!

Routing library required :-)

Page 24: A Single Page App Using the Odoo JS Framework

Now What?5

Page 25: A Single Page App Using the Odoo JS Framework

Some resources

General Javascript● jQuery Promises (e.g. https://www.sitepoint.com/introduction-jquery-deferred-objects/)● Standard JS: Mozillla Developper Network https://developer.mozilla.org �● Know you DevTools: https://developer.chrome.com/devtools (Source, Network tabs are a

must - don’t forget debug=assets)● Like, a ton of good blogs/websites:

○ David Walsh - https://davidwalsh.name/ �○ Sitepoint - https://www.sitepoint.com/javascript/○ PonyFoo - https://ponyfoo.com/○ Medium.com (although currently more about VueJS, React, etc.)○ Just Google It :)

Odoo Specific● /addons/web/static/src/js/core (commented, dosctringed, etc.)

○ class.js○ dialog.js○ rpc.js○ widget.js○ … explore.○ Use this as your main resource!

● Online Documentation: not at the moment● “The Odoo JS Framework” - Gery Debongnie (Odoo Framework team leader)

○ Today at 4.30pm in this very room● Code from this demo: https://github.com/dbo-odoo/odoo-js-demo

Repo for this talk: [email protected]/dbo-odoo/odoo-js-demo.git

Page 26: A Single Page App Using the Odoo JS Framework

Start coding!It’s easy

JS can be fun

Quick results

Nice for beginners

Page 27: A Single Page App Using the Odoo JS Framework

Thank you.

#odooexperience

EXPERIENCE

2017