SlideShare una empresa de Scribd logo
1 de 80
Descargar para leer sin conexión
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

Más contenido relacionado

Más de 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
 

Más de 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
 

Último

Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
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
 
[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
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 

Último (20)

Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
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
 
[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
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 

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