SlideShare a Scribd company logo
1 of 80
Download to read offline
Upgrade Training
  Web Client
Migrating 6.0 web
 addons to 6.1
Migrating 6.0 web
 addons to 6.1
Rewriting 6.0 web
  addons to 6.1
There is no migration
                 Everything has been rewritten from scratch




Been at the community days, probably seen it. Not been and looked at OpenERP Web (6.1),
probably noticed.

I doubt there’s a line left from the 6.0 codebase (we even split the project itself out), meaning
there isn’t a single API left either, meaning you’ll have to rewrite everything as well.
Technological changes
                         6.0                                     6.1
             Python (+ javascript)                          Javascript

                        Mako                                  QWeb

                     CherryPy                               Werkzeug

                        Pages                        Single Page Interface

                  Page requests                            JSON-RPC



Client used to be mostly Python and HTML-ish templates, bulk of logic moved to javascript.
* Template language QWeb, reminiscent of Kid/Genshi (though not inspired by them), XML-
based

More applicative interaction, more stateful, no page requests and full reloads.
cloc: 6.0

 Python               16059


Javascript            9782


Templates             5905
cloc: 6.1
Javascript            16925

Templates             3693

  CSS                 3064

 Python               1874
Deployment changes

          • Embedded mode, primary M.O.
          • Stand-alone mode for dev/testing
          • Official OpenERP bundle embeds


* Web Client has become “just another” OpenERP addon, though remains a different project
* Standalone mostly to avoid full server reload when writing Python code
** Or to put proxy inbetween
Architecture
Network


                                                    HTTP
                    XML-RPC                 JSON-RPC
    OpenERP                             Web Client                             Browser

                                                            HTML




6.0’s network arch: typical web frontend, communicates with server via XML-RPC, with client
via regular HTTP requests (e.g. link clicks) and HTML pages

    * Most client logic in the Web Client layer, not really a good fit as OpenERP has lots of
client state

    * Tentative to migrate to more stateful browser-side (iframe then ~pjax), half-hearted
and unsuccesful
6.1 merges server and web’s python: web’s python becomes a JSON-RPC interface to
OpenERP (+ some specific services), vast majority of logic moves to browser
Network


                                                  HTTP
                                          XML-RPC
                                          JSON-RPC
             OpenERP     Web Client                                            Browser

                                                            HTML




6.0’s network arch: typical web frontend, communicates with server via XML-RPC, with client
via regular HTTP requests (e.g. link clicks) and HTML pages

    * Most client logic in the Web Client layer, not really a good fit as OpenERP has lots of
client state

    * Tentative to migrate to more stateful browser-side (iframe then ~pjax), half-hearted
and unsuccesful
6.1 merges server and web’s python: web’s python becomes a JSON-RPC interface to
OpenERP (+ some specific services), vast majority of logic moves to browser
Layout
Layout


Web Client
Layout
                Header
                 Menu




   Menu
(secondary)
Layout



                                        Action Manager




OpenERP’s actions (ir.actions) -> primary drivers of everything (pretty much)
No visuals, dispatches to various children based on action executed (window, client) or does
work itself and handles result (act_url, server, report_xml)
Layout



                                         View Manager




That slide was hard work

Actual handling of window actions: parses view descriptions, initializes views and handles
inter-view communications, view switching, ...
Layout



View (form)
Layout
  View (not form)




View (not form either)
Layout: summary
•   WebClient

    •   Action Manager

        •   View Manager (?)

            •     Views (n)

        •   Client Action (?)

        •   ...
Reusable pieces



   Dashboard (form view)
Reusable pieces

                   action manager
                           &
 action manager     view manager
 & client action      & list view
Widgets



Base unit of (visual) work. All the blue boxes are “widgets” (a class of openerp web)

Widget ~ MVC view

~   Backbone.View
~   NSView
~   QAbstractItemView
~   Spine.Controller

Couldn’t use “View” due to confusion potential with OpenERP views (list, form, ...)
Widget Responsibilities

• Drawing on-screen (template rendering)
• User events handling (DOM events)
• Delegation
Widgets: templates

• Built-in handling
• Only trivial information
• Widget DOM root set up during rendering
Widgets: events


• No special provisions
• Use regular DOM events handling
Widgets: delegation

• Create children widgets to manage sub-
  sections
• Implementation detail of the widget
• Cooperative behavior between parent and
  children
Widgets lifecycle
           • Synchronous initialization (construction)
           • Template rendering
           • DOM insertion
           • Asynchronous initialization (secondary)
           • [life]
           • Cooperative destruction
See code (and detail of APIs) later

* Difficulty of parent/child relationships is not leaving “dangling” events or children
** Recursively stops children widgets
** Removes widget from DOM
** Removes widget from parent
** Must explicitly stop children when “killing” them during normal parent life (e.g.
ActionManager)
JavaScript



Your new frienemy.
$   var   a;
        $   a =   3.42;
        $   a =   "42";
        $   a =   true;

        $ var array = [];
        $ var obj = {};

        $ "foo".indexOf('o');
        1
        $ (3).toString();
        "3"
        $ [1, 2, 3, 4, 5].slice(1, 3);
        [2, 3]




Base language has Python similarities:
* Dynamic typing
* Literal booleans, strings, numbers, arrays, ~hashmap
* Object-oriented, methods on a lot of things
> if (condition) {
         >     // action
         > }

         > while (condition) {
         >     // body
         > }

         > for(init; end; each) {
         >     // stuff
         > }




Statements-heavy, close to C in its core syntax: if, while, for, return (explicit), ...
$ function f1 () {
        >     // things
        > }
        $ b = f1;

        $ var anon = function () {
        >     // body
        > };

        $ [1, 2, 3].forEach(function (item) {
        >    console.log(item);
        > });

        $   var a = 4;
        $   var fn = function () {
        >       a = 5;
        >   };
        $   a;
        4
        $   fn();
        $   a;
        5


* First-class functions (& higher-order functions)
* Anonymous functions
* Full closure (read/write)
$ var r = /foo/;
        $ r.test("a foo");
        true
        $ r.exec("a foo");
        ["foo"]




Additional stuff:
* Regex literals (~Perl)
** RegExp#test(String) -> Boolean
** RegExp#exec(String) -> MatchArray
** String#match(RegExp) -> MatchArray
** String#search(RegExp) -> IndexNumber
** String#replace(RegExp|String, String|Function) -> String
** String#split([String|RexExp], [Number]) -> Array<String>
Not Python



* Empty array, object is true (empty string is false)
* objects only have string keys, few methods (and no map-like methods)
* “for (i in array)” does not work “correctly”, “for (o in object)” is tricky, only iterates on key
* ‘key in object’?
* “weak” types (+/-; ==; ?)
* objects v primitives; typeof v instanceof
* Very small “standard library”: 10 global functions, 8 global constructors and the Math and
JSON namespaces... and the DOM (in browsers)
DOM



* Nodes & Elements
$ var root = document.getElementById('root');
        $ root
        [object HTMLDivElement]
        $ var p = document.createElement('p');
        $ p.setAttribute('title', "This is a paragraph");
        $ root.appendChild(p);
        $ p.appendChild(document.createTextNode("Text
        Content"));
        $ p.textContent = "text content";

        $ root.childNodes[0];
        [object Text]
        $ root.childNodes[1] === p;
        true
        $ root.childNodes[0].nodeType;
        3
        $ root.childNodes[1].nodeType;
        1
        $ p.textContent;
        "text content"
        $ p.childNodes[0].data;
        "text content"


* Very verbose creation and query API [insert node/JSDOM examples
** HTML5 APIs/modest improvements (querySelector, querySelectorAll)
$ p.onclick = function () {
        >     writeln("clicked paragraph");
        > };
        $ click(p);;
        clicked paragraph

        $ p.onclick = function () {
        >     writeln("clicked paragraph 2");
        > };
        $ click(p);
        clicked paragraph 2

        $ p.addEventListener('click', function () {
        >     writeln("clicked paragraph");
        > });
        $ click(p);
        clicked paragraph
        $ p.addEventListener('click', function () {
        >     writeln("clicked paragraph 2");
        > });
        $ click(p);
        clicked paragraph
        clicked paragraph 2


* Events
** “DOM0” simple but broken
** DOM level 2 meh (add) to horrible (trigger)
** MSIE < 9 incompatible (global event object, element.fireEvent(name[, options]))
$ var $root = $('#root').empty();
$ $root;
[[object HTMLDivElement]]
$ var $p = $("<p>", {'title': "This is a paragraph"});
$ $p;
[[object HTMLParagraphElement]]
$ $root.append($p);
$ $p.text("text content");
$ $root.children("p");
$ $root.find("p");
$ $p.text();
"text content"

$ $p.click(function () { writeln("clicked
paragraph"); });
$ $p.click();
clicked paragraph
[[object HTMLParagraphElement]]
$ $p.click(function () { writeln("clicked paragraph
2"); });
$ $p.click();
clicked paragraph
clicked paragraph 2
[[object HTMLParagraphElement]]
Pitfalls
http://bonsaiden.github.com/JavaScript-Garden/
$ {
>    var glob = 3;
> }
$ glob;
3                                                     $ var undef;
$ (function () {                                      $ writeln(undef);
>     var loc = 42;                                   undefined
> })();
$ loc;
Error: Can't find variable: loc
$ var shadow = 3;
$ (function () {
>     var shadow = 4;
>     writeln(shadow);
> })();                                 $ does_not_exist;
4                                       Error: Can't find variable: does_not_exist
$ shadow;                               $ (function () {
3                                       >     does_not_exist = 42;
$ (function () {                        > })();
>     writeln(local);                   $ does_not_exist;
>     var local = 3;                    42
>     writeln(local);
> })();
undefined
3
Declared but not defined -> undefined (oddly makes sense)
Function scope (!C, !java)
* Python has UnboundLocalError v NameError, JS has undefined v Error
Implicit declaration -> global
$ var somevar = 3;
 $ somevar;
 3
 $ somevar = 4;
 $ somevar;                              $ var fns = [];
 4                                       $ for (var i=0; i != 10; ++i) {
 $ (function () {                        >     fns.push(function () { writeln(i); });
 >     somevar = 5;                      > }
 > })();                                 $ fns.forEach(function (f) { f(); });
 $ somevar;                              10
 5                                       10
 $ (function () {                        10
 >     var somevar = 42;                 10
 >     (function () {                    10
 >         somevar = 36;                 10
 >         writeln(somevar);             10
 >     })();                             10
 >     writeln(somevar);                 10
 > })();                                 10
 36
 36
 $ somevar;
 5


* Writable closures (not possible in Python 2)
* Danger! closures in loops
$ writeln(null);
null
$ typeof null;
"object"
$ null instanceof Object;                                   $ NaN;
false                                                       NaN
                                                            $ typeof NaN;
$ writeln(undefined);
                                                            "number"
undefined
                                                            $ NaN === NaN;
$ typeof undefined;
                                                            false
"undefined"
                                                            $ NaN == NaN;
$ undefined === null;
                                                            false
false
                                                            $ isNaN(NaN);
$ undefined == null;
                                                            true
true
                                                            $ parseInt("foo");
$ writeln((function () {})());
                                                            NaN
undefined
                                                            $ parseInt("1foo");
$ writeln((function () { return; })());
                                                            1
undefined
                                                            $ 1 - "foo";
$ (function (a) { writeln(a); })();
                                                            NaN
undefined
                                                            $ +"foo";
$ writeln(({}).does_not_exist);
                                                            NaN
undefined
$ var no_such_variable;
$ writeln(no_such_variable);
undefined
Python -> None and exceptions (errors)
JS -> null (None), undefined, NaN and exceptions.

* null !== undefined, but null == undefined
* typeof null === “object”
* Access undefined property -> undefined
** Access property set to undefined -> also undefined
* NaN exists in Python but very rare, more common in JS due to weak typing e.g. +”foo”
** NaN != NaN, use isNaN
** typeof NaN === ‘number’
$ function Foo() {};
        $ var foo = new Foo();
        $ foo instanceof Foo;
        true
        $ var bar = Foo();
        $ writeln(bar);
        undefined
        $ var a = function () { this.b = "b"; };
        $ a.b = function () { this.c = "c"; };
        $ a.b.c = function () {};
        $ new a.b.c instanceof (a.b.c);
        true
        $ new a.b().c instanceof (a.b.c);
        false
        $ (new (function () { this.ok = true; })).ok;
        true
        $ var baz = new Foo;




JavaScript OO is “interesting” (mostly bad kind)
Not going to dwelve far into it, but knowledge of *constructors* useful as object layers are
generally sugar over JS OO.
* Constructors are functions used in special context
** Any function can be used as a constructor (!= is useful a constructor)
* new $type() vs $type()
* $type an expression, ends at first parens by default (kinda weird)
** new a.b.c -> new (a.b.c); new a.b().c -> (new a.b()).c
** parens optional
$ this;
[object DOMWindow]
Actual output:                                   $ var fn = function (f) { f(this); }
[]                                               $ var a = {b: fn};
$ this === window;                               $ fn(function (t) {
true                                             >     writeln(t === window);
                                                 > });
                                                 true
                                                 $ a.b(function (t) {
                                                 >     writeln(t === a);
                                                 > });
                                                 true
                                                 $ new fn(function (t) {
                                                 >     writeln(t instanceof fn);
                                                 > });
                                                 true
    $ var o = {};
                                                 {}
    $ fn.call(o, function (t) {
                                                 $ var c = {};
    >     writeln(t === o);
                                                 $ c.b = a.b;
    > });
                                                 $ c.b(function (t) {
    true
                                                 >     writeln(t === c);
    $ fn.apply(o, [function (t) {
                                                 > });
    >     writeln(t === o);
                                                 true
    > }]);
    true

* Call site decides of `this` in callee
* default (global, function): “global object” (browsers: window)
* Not transitive
** b() -> `this` is window
** a.b() -> `this` is a
** new a.b -> `this` is instance of `a.b`
** c.b = a.b; c.b() -> `this` is c
** Function#call, Function#apply -> `this` is arg0
$ var a = {                                    $   a = {
>     attr: 1,                                 >       attr: 1,
>     b: function () {                         >       b: function () {
>         writeln(this.attr);                  >           var self = this;
>         return function () {                 >           return function () {
>             writeln(this.attr);              >               writeln(self.attr);
>         };                                   >           };
>     }                                        >       }
> };                                           >   };
$ var f = a.b();                               $   var f = a.b();
1                                              $   f();
$ f();                                         1
undefined
                                               $   a = {
                                               >       attr: 1,
                                               >       b: function () {
                                               >           var fn = function () {
                                               >               writeln(this.attr);
                                               >           };
                                               >           return fn.bind(this);
                                               >       }
                                               >   };
                                               $   var f = a.b();
                                               $   f();
                                               1

* In closures, use alias (`var self = this`)
** Function#bind, _.bind
** Widget#proxy
JavaScript concurrency
• JS runtime is a reactor (pattern)
 • Event loop
 • Single threaded
 • Blocking (synchronous)
Actually not what you’ll have with network requests: page (or even browser) frozen, no dialog
no nothing.
• Continuation Passing Style (CPS)
 • Call long-running operation
 • Pass “continuation” callback
 • Called whenever operation completes
Callback Mess

           1. Forwarding (all methods must take 1/2
              callbacks)
           2. Composition (waiting on multiple events)
           3. Post-hoc decisions (act on an event which
              may or may not have happened)




* Lower evolutivity
** Many methods need extra 2 params, harder to read &use
** Harder to add new params (callback @end)
** Params post-callbacks hard to read/unreadable
** Costlier for methods which may become async
*** sync -> async transformation horrible so want to have API correct early
* Ad-hoc mess of flags &stuff
* Need to complement with flags as well
Deferred
• AKA Futures, promises
            • (Success, Error)
            • Pipelining
            • Composition
           • Promises/A
           • jQuery.Deferred, #pipe, jQuery.when
* Stateful, tri-state (pending, resolved, rejected)
* Callback queues
** Deferred#then
** Deferred#done/Deferred#fail/Deferred#always
* Single state change
* $.Deferred#pipe: pipelining (async chains)
* $.when: composition
** Original: wrap value in deferred
Tooling
• Webkit Developer Tools / CDT
            • Firebug
            • Dragonfly
            • IE Developer Tools


Actual capabilities vary, some things might work better in some tools than in other

1.   WDT/CDT ~ Firebug
2.   Dragonfly
3.   IE9 DevTools
4.   IE8 DevTools
Console




* Can actually get CLI JS console (à la `python`): spidermonkey or nodejs
* Access to page content (and libraries)
* Test code snippets
** jsfiddle
** jsbin
** tinker.io
** ...
* Interactively inspect objects
Console API




``console`` object, functions for programmatic printing of information
* Basic logging (log, debug, info, warn, error, exception)
* Formatting (group/groupEnd)
* Timers (time/timeEnd)
* Profiling (profile/profileEnd)
* trace
* dir
* count
Visual Debugger




* Breakpoints (visual or programmatic)
* Conditional breakpoints
* call stack
* Locals
** CONSOLE
DOM Inspector




* “Inspect Element” entry point
* Edit DOM (as HTML text, add/remove/change attributes)
* Visualize margin/padding/borders
* CSS adjustments
** Metrics section (overview)
** enable/disable rules
* DOM breakpoints (flaky?)
Network




*   List requests, time, latency, payload size
*   Request & response header
*   Request payload
*   Response payload (formatted JSON)
Profiler




Nothing much to say, usual visual profiler, have to learn on your own
Console (again)




command-line API http://getfirebug.com/wiki/index.php/Command_Line_API
OpenERP Web APIs
6.1 Caveat


• API stability (and the lack thereof)
• Python controller   • form.Widget
• RPC (connection,    • Client actions
  dataset)
                      • Translations
• QWeb                • underscore.js
• Widget              • Dialog
• View                • CrashManager
Classes & subclassing



* JS OO somewhat similar to Python’s
* Single-inheritance
* No sugar for classes, plumbing a bit hard to get your head around and verbose
** Helper: Class & Class.extend
** this._super, doesn’t play well with async
QWeb
Usage

• openerp.web.qweb
• QWeb.render(template, context) => String
• t-name
• t-call
Logic

• t-set t-value
• t-if
• t-foreach t-as
Output
•   t-esc        •   t-att

•   t-escf       •   t-att-*

•   t-raw        •   t-attf-*

•   t-rawf
API: Widget



Client actions
registries (instance.web.client_actions)
<iframe class="youtube-player" type="text/html" width="640" height="385"
     t-attf-src="http://youtube.com/embed/#{widget.params.id}" frameborder="0">
</iframe>
* sn2l2_v6Ur8
 * pOA9PGYeP3E
* oHg5SJYRHA0
 * wmkoJGm6y6k
* ZZ5LpwO-An4
 * eQemvyyJ--g
* qWkUFxItWmU
 * hXlzci1rKNM
• Web-oriented keys: css, js, qweb
• ‘static’ folder
• module pattern: private namespace,
  initialization code
• Widget#init :: * => ()
• Widget#render :: () => String
• Widget#start :: () => Deferred
• Widget#stop :: () => ()
API: Search Fields



meetings
• Field
            • non-standard cycle
            • get_context, get_domain


{instance.web.search.fields}
* Weird cycle
** Render everything (recursive, defaults)
** Bind (element_id, in template context)
** Start
* dygraphs.com
** dygraphs.com/dygraph-combined.js
** new Dygraph(element, CSV_string)
API: Form Fields



hr -> email field
{instance.web.form.widgets}
Also weird cycle/management
* $element set to parent (table cell), in start() (_super() call required)
• Field#value :: *
          • Field#set_value :: * => Deferred
          • Field#on_ui_change :: () => ()
          • Field#update_dom :: () => ()
          • Field#validate :: () => ()

#value -> current value for the widget
#set_value -> form sets value on widget
#on_ui_change -> signal value change via UI to form
* Should have set #value
# update_dom -> resync non-value DOM (readonly, invalid, required)
# validate -> set/unset “invalid”
Debugging
Debugging with
OpenERP Web
Debugging OpenERP
       Web
Third-party Embedding



Install “share”
Share button “link or embed”
Put in HTML file on disk
python -mSimpleHTTPServer

More Related Content

More from Odoo

Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityExtending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityOdoo
 
Managing Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooManaging Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooOdoo
 
Product Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseProduct Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseOdoo
 
Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Odoo
 
Rock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsRock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsOdoo
 
Transition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationTransition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationOdoo
 
Synchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisSynchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisOdoo
 
Running a University with Odoo
Running a University with OdooRunning a University with Odoo
Running a University with OdooOdoo
 
Down Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooDown Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooOdoo
 
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo
 
Migration from Salesforce to Odoo
Migration from Salesforce to OdooMigration from Salesforce to Odoo
Migration from Salesforce to OdooOdoo
 
Preventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningPreventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningOdoo
 
Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Odoo
 
Instant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelInstant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelOdoo
 
How Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldHow Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldOdoo
 
From Shopify to Odoo
From Shopify to OdooFrom Shopify to Odoo
From Shopify to OdooOdoo
 
Digital Transformation at Old MacDonald Farms: A Personal Story
Digital Transformation at Old MacDonald Farms: A Personal StoryDigital Transformation at Old MacDonald Farms: A Personal Story
Digital Transformation at Old MacDonald Farms: A Personal StoryOdoo
 
An all in-one Engineer-to-Order (ETO) Solution with Odoo
An all in-one Engineer-to-Order (ETO) Solution with OdooAn all in-one Engineer-to-Order (ETO) Solution with Odoo
An all in-one Engineer-to-Order (ETO) Solution with OdooOdoo
 
Advanced Integrated HRMS and Appraisal System
Advanced Integrated HRMS and Appraisal SystemAdvanced Integrated HRMS and Appraisal System
Advanced Integrated HRMS and Appraisal SystemOdoo
 
Accounting using the Odoo Enterprise Swsiss Localization
Accounting using the Odoo Enterprise Swsiss LocalizationAccounting using the Odoo Enterprise Swsiss Localization
Accounting using the Odoo Enterprise Swsiss LocalizationOdoo
 

More from Odoo (20)

Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting CapabilityExtending Odoo with a Comprehensive Budgeting and Forecasting Capability
Extending Odoo with a Comprehensive Budgeting and Forecasting Capability
 
Managing Multi-channel Selling with Odoo
Managing Multi-channel Selling with OdooManaging Multi-channel Selling with Odoo
Managing Multi-channel Selling with Odoo
 
Product Configurator: Advanced Use Case
Product Configurator: Advanced Use CaseProduct Configurator: Advanced Use Case
Product Configurator: Advanced Use Case
 
Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?Accounting Automation: How Much Money We Saved and How?
Accounting Automation: How Much Money We Saved and How?
 
Rock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced OperationsRock Your Logistics with Advanced Operations
Rock Your Logistics with Advanced Operations
 
Transition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organizationTransition from a cost to a flow-centric organization
Transition from a cost to a flow-centric organization
 
Synchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the CrisisSynchronization: The Supply Chain Response to Overcome the Crisis
Synchronization: The Supply Chain Response to Overcome the Crisis
 
Running a University with Odoo
Running a University with OdooRunning a University with Odoo
Running a University with Odoo
 
Down Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in OdooDown Payments on Purchase Orders in Odoo
Down Payments on Purchase Orders in Odoo
 
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach foodOdoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
Odoo Implementation in Phases - Success Story of a Retail Chain 3Sach food
 
Migration from Salesforce to Odoo
Migration from Salesforce to OdooMigration from Salesforce to Odoo
Migration from Salesforce to Odoo
 
Preventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine LearningPreventing User Mistakes by Using Machine Learning
Preventing User Mistakes by Using Machine Learning
 
Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification Becoming an Odoo Expert: How to Prepare for the Certification
Becoming an Odoo Expert: How to Prepare for the Certification
 
Instant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping LabelInstant Printing of any Odoo Report or Shipping Label
Instant Printing of any Odoo Report or Shipping Label
 
How Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 FoldHow Odoo helped an Organization Grow 3 Fold
How Odoo helped an Organization Grow 3 Fold
 
From Shopify to Odoo
From Shopify to OdooFrom Shopify to Odoo
From Shopify to Odoo
 
Digital Transformation at Old MacDonald Farms: A Personal Story
Digital Transformation at Old MacDonald Farms: A Personal StoryDigital Transformation at Old MacDonald Farms: A Personal Story
Digital Transformation at Old MacDonald Farms: A Personal Story
 
An all in-one Engineer-to-Order (ETO) Solution with Odoo
An all in-one Engineer-to-Order (ETO) Solution with OdooAn all in-one Engineer-to-Order (ETO) Solution with Odoo
An all in-one Engineer-to-Order (ETO) Solution with Odoo
 
Advanced Integrated HRMS and Appraisal System
Advanced Integrated HRMS and Appraisal SystemAdvanced Integrated HRMS and Appraisal System
Advanced Integrated HRMS and Appraisal System
 
Accounting using the Odoo Enterprise Swsiss Localization
Accounting using the Odoo Enterprise Swsiss LocalizationAccounting using the Odoo Enterprise Swsiss Localization
Accounting using the Odoo Enterprise Swsiss Localization
 

Recently uploaded

Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 

Recently uploaded (20)

Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 

OpenERP 6.1 - Web Framework Tutorial

  • 1. Upgrade Training Web Client
  • 2. Migrating 6.0 web addons to 6.1
  • 3. Migrating 6.0 web addons to 6.1
  • 4. Rewriting 6.0 web addons to 6.1
  • 5. There is no migration Everything has been rewritten from scratch Been at the community days, probably seen it. Not been and looked at OpenERP Web (6.1), probably noticed. I doubt there’s a line left from the 6.0 codebase (we even split the project itself out), meaning there isn’t a single API left either, meaning you’ll have to rewrite everything as well.
  • 6. Technological changes 6.0 6.1 Python (+ javascript) Javascript Mako QWeb CherryPy Werkzeug Pages Single Page Interface Page requests JSON-RPC Client used to be mostly Python and HTML-ish templates, bulk of logic moved to javascript. * Template language QWeb, reminiscent of Kid/Genshi (though not inspired by them), XML- based More applicative interaction, more stateful, no page requests and full reloads.
  • 7. cloc: 6.0 Python 16059 Javascript 9782 Templates 5905
  • 8. cloc: 6.1 Javascript 16925 Templates 3693 CSS 3064 Python 1874
  • 9. Deployment changes • Embedded mode, primary M.O. • Stand-alone mode for dev/testing • Official OpenERP bundle embeds * Web Client has become “just another” OpenERP addon, though remains a different project * Standalone mostly to avoid full server reload when writing Python code ** Or to put proxy inbetween
  • 11. Network HTTP XML-RPC JSON-RPC OpenERP Web Client Browser HTML 6.0’s network arch: typical web frontend, communicates with server via XML-RPC, with client via regular HTTP requests (e.g. link clicks) and HTML pages * Most client logic in the Web Client layer, not really a good fit as OpenERP has lots of client state * Tentative to migrate to more stateful browser-side (iframe then ~pjax), half-hearted and unsuccesful 6.1 merges server and web’s python: web’s python becomes a JSON-RPC interface to OpenERP (+ some specific services), vast majority of logic moves to browser
  • 12. Network HTTP XML-RPC JSON-RPC OpenERP Web Client Browser HTML 6.0’s network arch: typical web frontend, communicates with server via XML-RPC, with client via regular HTTP requests (e.g. link clicks) and HTML pages * Most client logic in the Web Client layer, not really a good fit as OpenERP has lots of client state * Tentative to migrate to more stateful browser-side (iframe then ~pjax), half-hearted and unsuccesful 6.1 merges server and web’s python: web’s python becomes a JSON-RPC interface to OpenERP (+ some specific services), vast majority of logic moves to browser
  • 15. Layout Header Menu Menu (secondary)
  • 16. Layout Action Manager OpenERP’s actions (ir.actions) -> primary drivers of everything (pretty much) No visuals, dispatches to various children based on action executed (window, client) or does work itself and handles result (act_url, server, report_xml)
  • 17. Layout View Manager That slide was hard work Actual handling of window actions: parses view descriptions, initializes views and handles inter-view communications, view switching, ...
  • 19. Layout View (not form) View (not form either)
  • 20. Layout: summary • WebClient • Action Manager • View Manager (?) • Views (n) • Client Action (?) • ...
  • 21. Reusable pieces Dashboard (form view)
  • 22. Reusable pieces action manager & action manager view manager & client action & list view
  • 23. Widgets Base unit of (visual) work. All the blue boxes are “widgets” (a class of openerp web) Widget ~ MVC view ~ Backbone.View ~ NSView ~ QAbstractItemView ~ Spine.Controller Couldn’t use “View” due to confusion potential with OpenERP views (list, form, ...)
  • 24. Widget Responsibilities • Drawing on-screen (template rendering) • User events handling (DOM events) • Delegation
  • 25. Widgets: templates • Built-in handling • Only trivial information • Widget DOM root set up during rendering
  • 26. Widgets: events • No special provisions • Use regular DOM events handling
  • 27. Widgets: delegation • Create children widgets to manage sub- sections • Implementation detail of the widget • Cooperative behavior between parent and children
  • 28. Widgets lifecycle • Synchronous initialization (construction) • Template rendering • DOM insertion • Asynchronous initialization (secondary) • [life] • Cooperative destruction See code (and detail of APIs) later * Difficulty of parent/child relationships is not leaving “dangling” events or children ** Recursively stops children widgets ** Removes widget from DOM ** Removes widget from parent ** Must explicitly stop children when “killing” them during normal parent life (e.g. ActionManager)
  • 30. $ var a; $ a = 3.42; $ a = "42"; $ a = true; $ var array = []; $ var obj = {}; $ "foo".indexOf('o'); 1 $ (3).toString(); "3" $ [1, 2, 3, 4, 5].slice(1, 3); [2, 3] Base language has Python similarities: * Dynamic typing * Literal booleans, strings, numbers, arrays, ~hashmap * Object-oriented, methods on a lot of things
  • 31. > if (condition) { > // action > } > while (condition) { > // body > } > for(init; end; each) { > // stuff > } Statements-heavy, close to C in its core syntax: if, while, for, return (explicit), ...
  • 32. $ function f1 () { > // things > } $ b = f1; $ var anon = function () { > // body > }; $ [1, 2, 3].forEach(function (item) { > console.log(item); > }); $ var a = 4; $ var fn = function () { > a = 5; > }; $ a; 4 $ fn(); $ a; 5 * First-class functions (& higher-order functions) * Anonymous functions * Full closure (read/write)
  • 33. $ var r = /foo/; $ r.test("a foo"); true $ r.exec("a foo"); ["foo"] Additional stuff: * Regex literals (~Perl) ** RegExp#test(String) -> Boolean ** RegExp#exec(String) -> MatchArray ** String#match(RegExp) -> MatchArray ** String#search(RegExp) -> IndexNumber ** String#replace(RegExp|String, String|Function) -> String ** String#split([String|RexExp], [Number]) -> Array<String>
  • 34. Not Python * Empty array, object is true (empty string is false) * objects only have string keys, few methods (and no map-like methods) * “for (i in array)” does not work “correctly”, “for (o in object)” is tricky, only iterates on key * ‘key in object’? * “weak” types (+/-; ==; ?) * objects v primitives; typeof v instanceof * Very small “standard library”: 10 global functions, 8 global constructors and the Math and JSON namespaces... and the DOM (in browsers)
  • 35. DOM * Nodes & Elements
  • 36. $ var root = document.getElementById('root'); $ root [object HTMLDivElement] $ var p = document.createElement('p'); $ p.setAttribute('title', "This is a paragraph"); $ root.appendChild(p); $ p.appendChild(document.createTextNode("Text Content")); $ p.textContent = "text content"; $ root.childNodes[0]; [object Text] $ root.childNodes[1] === p; true $ root.childNodes[0].nodeType; 3 $ root.childNodes[1].nodeType; 1 $ p.textContent; "text content" $ p.childNodes[0].data; "text content" * Very verbose creation and query API [insert node/JSDOM examples ** HTML5 APIs/modest improvements (querySelector, querySelectorAll)
  • 37. $ p.onclick = function () { > writeln("clicked paragraph"); > }; $ click(p);; clicked paragraph $ p.onclick = function () { > writeln("clicked paragraph 2"); > }; $ click(p); clicked paragraph 2 $ p.addEventListener('click', function () { > writeln("clicked paragraph"); > }); $ click(p); clicked paragraph $ p.addEventListener('click', function () { > writeln("clicked paragraph 2"); > }); $ click(p); clicked paragraph clicked paragraph 2 * Events ** “DOM0” simple but broken ** DOM level 2 meh (add) to horrible (trigger) ** MSIE < 9 incompatible (global event object, element.fireEvent(name[, options]))
  • 38. $ var $root = $('#root').empty(); $ $root; [[object HTMLDivElement]] $ var $p = $("<p>", {'title': "This is a paragraph"}); $ $p; [[object HTMLParagraphElement]] $ $root.append($p); $ $p.text("text content"); $ $root.children("p"); $ $root.find("p"); $ $p.text(); "text content" $ $p.click(function () { writeln("clicked paragraph"); }); $ $p.click(); clicked paragraph [[object HTMLParagraphElement]] $ $p.click(function () { writeln("clicked paragraph 2"); }); $ $p.click(); clicked paragraph clicked paragraph 2 [[object HTMLParagraphElement]]
  • 40. $ { > var glob = 3; > } $ glob; 3 $ var undef; $ (function () { $ writeln(undef); > var loc = 42; undefined > })(); $ loc; Error: Can't find variable: loc $ var shadow = 3; $ (function () { > var shadow = 4; > writeln(shadow); > })(); $ does_not_exist; 4 Error: Can't find variable: does_not_exist $ shadow; $ (function () { 3 > does_not_exist = 42; $ (function () { > })(); > writeln(local); $ does_not_exist; > var local = 3; 42 > writeln(local); > })(); undefined 3 Declared but not defined -> undefined (oddly makes sense) Function scope (!C, !java) * Python has UnboundLocalError v NameError, JS has undefined v Error Implicit declaration -> global
  • 41. $ var somevar = 3; $ somevar; 3 $ somevar = 4; $ somevar; $ var fns = []; 4 $ for (var i=0; i != 10; ++i) { $ (function () { > fns.push(function () { writeln(i); }); > somevar = 5; > } > })(); $ fns.forEach(function (f) { f(); }); $ somevar; 10 5 10 $ (function () { 10 > var somevar = 42; 10 > (function () { 10 > somevar = 36; 10 > writeln(somevar); 10 > })(); 10 > writeln(somevar); 10 > })(); 10 36 36 $ somevar; 5 * Writable closures (not possible in Python 2) * Danger! closures in loops
  • 42. $ writeln(null); null $ typeof null; "object" $ null instanceof Object; $ NaN; false NaN $ typeof NaN; $ writeln(undefined); "number" undefined $ NaN === NaN; $ typeof undefined; false "undefined" $ NaN == NaN; $ undefined === null; false false $ isNaN(NaN); $ undefined == null; true true $ parseInt("foo"); $ writeln((function () {})()); NaN undefined $ parseInt("1foo"); $ writeln((function () { return; })()); 1 undefined $ 1 - "foo"; $ (function (a) { writeln(a); })(); NaN undefined $ +"foo"; $ writeln(({}).does_not_exist); NaN undefined $ var no_such_variable; $ writeln(no_such_variable); undefined Python -> None and exceptions (errors) JS -> null (None), undefined, NaN and exceptions. * null !== undefined, but null == undefined * typeof null === “object” * Access undefined property -> undefined ** Access property set to undefined -> also undefined * NaN exists in Python but very rare, more common in JS due to weak typing e.g. +”foo” ** NaN != NaN, use isNaN ** typeof NaN === ‘number’
  • 43. $ function Foo() {}; $ var foo = new Foo(); $ foo instanceof Foo; true $ var bar = Foo(); $ writeln(bar); undefined $ var a = function () { this.b = "b"; }; $ a.b = function () { this.c = "c"; }; $ a.b.c = function () {}; $ new a.b.c instanceof (a.b.c); true $ new a.b().c instanceof (a.b.c); false $ (new (function () { this.ok = true; })).ok; true $ var baz = new Foo; JavaScript OO is “interesting” (mostly bad kind) Not going to dwelve far into it, but knowledge of *constructors* useful as object layers are generally sugar over JS OO. * Constructors are functions used in special context ** Any function can be used as a constructor (!= is useful a constructor) * new $type() vs $type() * $type an expression, ends at first parens by default (kinda weird) ** new a.b.c -> new (a.b.c); new a.b().c -> (new a.b()).c ** parens optional
  • 44. $ this; [object DOMWindow] Actual output: $ var fn = function (f) { f(this); } [] $ var a = {b: fn}; $ this === window; $ fn(function (t) { true > writeln(t === window); > }); true $ a.b(function (t) { > writeln(t === a); > }); true $ new fn(function (t) { > writeln(t instanceof fn); > }); true $ var o = {}; {} $ fn.call(o, function (t) { $ var c = {}; > writeln(t === o); $ c.b = a.b; > }); $ c.b(function (t) { true > writeln(t === c); $ fn.apply(o, [function (t) { > }); > writeln(t === o); true > }]); true * Call site decides of `this` in callee * default (global, function): “global object” (browsers: window) * Not transitive ** b() -> `this` is window ** a.b() -> `this` is a ** new a.b -> `this` is instance of `a.b` ** c.b = a.b; c.b() -> `this` is c ** Function#call, Function#apply -> `this` is arg0
  • 45. $ var a = { $ a = { > attr: 1, > attr: 1, > b: function () { > b: function () { > writeln(this.attr); > var self = this; > return function () { > return function () { > writeln(this.attr); > writeln(self.attr); > }; > }; > } > } > }; > }; $ var f = a.b(); $ var f = a.b(); 1 $ f(); $ f(); 1 undefined $ a = { > attr: 1, > b: function () { > var fn = function () { > writeln(this.attr); > }; > return fn.bind(this); > } > }; $ var f = a.b(); $ f(); 1 * In closures, use alias (`var self = this`) ** Function#bind, _.bind ** Widget#proxy
  • 47. • JS runtime is a reactor (pattern) • Event loop • Single threaded • Blocking (synchronous)
  • 48. Actually not what you’ll have with network requests: page (or even browser) frozen, no dialog no nothing.
  • 49. • Continuation Passing Style (CPS) • Call long-running operation • Pass “continuation” callback • Called whenever operation completes
  • 50. Callback Mess 1. Forwarding (all methods must take 1/2 callbacks) 2. Composition (waiting on multiple events) 3. Post-hoc decisions (act on an event which may or may not have happened) * Lower evolutivity ** Many methods need extra 2 params, harder to read &use ** Harder to add new params (callback @end) ** Params post-callbacks hard to read/unreadable ** Costlier for methods which may become async *** sync -> async transformation horrible so want to have API correct early * Ad-hoc mess of flags &stuff * Need to complement with flags as well
  • 52. • AKA Futures, promises • (Success, Error) • Pipelining • Composition • Promises/A • jQuery.Deferred, #pipe, jQuery.when * Stateful, tri-state (pending, resolved, rejected) * Callback queues ** Deferred#then ** Deferred#done/Deferred#fail/Deferred#always * Single state change * $.Deferred#pipe: pipelining (async chains) * $.when: composition ** Original: wrap value in deferred
  • 54. • Webkit Developer Tools / CDT • Firebug • Dragonfly • IE Developer Tools Actual capabilities vary, some things might work better in some tools than in other 1. WDT/CDT ~ Firebug 2. Dragonfly 3. IE9 DevTools 4. IE8 DevTools
  • 55. Console * Can actually get CLI JS console (à la `python`): spidermonkey or nodejs * Access to page content (and libraries) * Test code snippets ** jsfiddle ** jsbin ** tinker.io ** ... * Interactively inspect objects
  • 56. Console API ``console`` object, functions for programmatic printing of information * Basic logging (log, debug, info, warn, error, exception) * Formatting (group/groupEnd) * Timers (time/timeEnd) * Profiling (profile/profileEnd) * trace * dir * count
  • 57. Visual Debugger * Breakpoints (visual or programmatic) * Conditional breakpoints * call stack * Locals ** CONSOLE
  • 58. DOM Inspector * “Inspect Element” entry point * Edit DOM (as HTML text, add/remove/change attributes) * Visualize margin/padding/borders * CSS adjustments ** Metrics section (overview) ** enable/disable rules * DOM breakpoints (flaky?)
  • 59. Network * List requests, time, latency, payload size * Request & response header * Request payload * Response payload (formatted JSON)
  • 60. Profiler Nothing much to say, usual visual profiler, have to learn on your own
  • 61. Console (again) command-line API http://getfirebug.com/wiki/index.php/Command_Line_API
  • 63. 6.1 Caveat • API stability (and the lack thereof)
  • 64. • Python controller • form.Widget • RPC (connection, • Client actions dataset) • Translations • QWeb • underscore.js • Widget • Dialog • View • CrashManager
  • 65. Classes & subclassing * JS OO somewhat similar to Python’s * Single-inheritance * No sugar for classes, plumbing a bit hard to get your head around and verbose ** Helper: Class & Class.extend ** this._super, doesn’t play well with async
  • 66. QWeb
  • 67. Usage • openerp.web.qweb • QWeb.render(template, context) => String • t-name • t-call
  • 68. Logic • t-set t-value • t-if • t-foreach t-as
  • 69. Output • t-esc • t-att • t-escf • t-att-* • t-raw • t-attf-* • t-rawf
  • 70. API: Widget Client actions registries (instance.web.client_actions) <iframe class="youtube-player" type="text/html" width="640" height="385" t-attf-src="http://youtube.com/embed/#{widget.params.id}" frameborder="0"> </iframe> * sn2l2_v6Ur8 * pOA9PGYeP3E * oHg5SJYRHA0 * wmkoJGm6y6k * ZZ5LpwO-An4 * eQemvyyJ--g * qWkUFxItWmU * hXlzci1rKNM
  • 71. • Web-oriented keys: css, js, qweb • ‘static’ folder • module pattern: private namespace, initialization code
  • 72. • Widget#init :: * => () • Widget#render :: () => String • Widget#start :: () => Deferred • Widget#stop :: () => ()
  • 74. • Field • non-standard cycle • get_context, get_domain {instance.web.search.fields} * Weird cycle ** Render everything (recursive, defaults) ** Bind (element_id, in template context) ** Start * dygraphs.com ** dygraphs.com/dygraph-combined.js ** new Dygraph(element, CSV_string)
  • 75. API: Form Fields hr -> email field {instance.web.form.widgets} Also weird cycle/management * $element set to parent (table cell), in start() (_super() call required)
  • 76. • Field#value :: * • Field#set_value :: * => Deferred • Field#on_ui_change :: () => () • Field#update_dom :: () => () • Field#validate :: () => () #value -> current value for the widget #set_value -> form sets value on widget #on_ui_change -> signal value change via UI to form * Should have set #value # update_dom -> resync non-value DOM (readonly, invalid, required) # validate -> set/unset “invalid”
  • 80. Third-party Embedding Install “share” Share button “link or embed” Put in HTML file on disk python -mSimpleHTTPServer