Thursday 11 June 2015

Standalone Application With Odoo Framework

Hello Everybody, Here I am going to explain how one can develop a standalone application using Odoo web framework, which can communicate to Odoo server(May be you can have your own WSGI Server which handles HTTP and JSON request) and can call controller, application can do request type of HTTP or JSON.

As you are going to develop a standalone application using Odoo web framework so there are some minimum requirements which should be fulfilled, like to develop a standalone application using Odoo framework you should have Qweb Engine available because Odoo framework having dependency with qweb engine(consider default template engine)

Difference between old framework design and New modular framework

Prior to new design of Web framewrok(prior to concept of require and odoo.define, the concept of modular web-client framework), there is only one file needed to use all concepts like class, class extension, include, core widget, support Translations, datetime operation like(string to datetime and datetime to string), Mutex, Model Proxy to directly create an instance of some Odoo Model and call method of it, Session management for making RPC call, Event and EventDispatcherMixin and etc, and more file for template engine that is qweb2.js


 Now WebClient framework is more modular, for each functionality there is separate module(registered module using odoo.define method)


Now to develop a standalone application you needs following JS files, Well I would say modules here, because now in new design everything is modular so each feature defined using odoo.define will be called a JS module which provides some functionality.

boot.js
    The file where the concept of define module and require wrapper method is defined

class.js
    The file where class and related terms like extend, includes, _super are defined.

ajax.js
    This file  defines genericJsonRpc, jsonRpc, jsonpRpc, loadJS, loadCSS, and get_file function, basically this file will be used for generic AJAX call, this file having dependency over time.js, so to support ajax feature you should have time.js atleast, wherever I say this file having dependency on another file means to support that module you need that another file.

time.js
    All datetime operation related stuff resides in this file(like strtodatetime, datetimetostr, datetostr, strtodate etc), this file having dependency over translation.js and utils.js, translation.js is used to translate some static messages defined in this file time.js, and utils.js is used for lpad and rpad functions.

utils.js
    This file having dependency over class.js and translation.js, which we already having right, this file will contain all generic utility functions, lpad, rpad, xml_to_json, json_node_to_xml, xml_to_str, Mutex, DropMisordered, set_cookie, get_cookie and many more.

translation.js
    The file having dependency over qweb(It is default requirement of the framework to have a qweb template engine, object of qweb is created in boot.js itself while generating module services of odoo).
This translation.js having TranslationDatabase, where all translation are stored, one call is done by translation.js to fetch all translations from the server and the call is to controller and controller is: /web/webclient/translations.

mixin.js
    This module contains all mixin related stuff, like EventDispatcherMixin, PropertiesMixin, ParentedMixin are defined over here.

EventDispatcherMixin: to on event(Bind event), trigger event(to trigger binded event), off(to detach event), destroy.


session.js
    This module is specifically created to maintain client session object, through this object all RPC methods are called, this having core rpc method, it also having load_modules logic, its having some core methods like user_has_group, load_qweb, etc methods, basically this module is specifically to maintain session over client.

rigistry.js
    This module provides generically developed Registry class which stores details, like it is used for widget registry, it is also used for view registry, its having some generic methods like add, get, any, contains, extend etc


widget.js
    The module depends on web.core and web.sesssion, the module is meant for core widget development, here core Odoo Widget is developed which going to base class of all Odoo widgets, Its having all logic related widget rendering, like when widget should be rendered, how start method of widget will be called(start method will be called once widget is inserted into DOM, appendTo, prependTo, insertAfter, insertBefore), also this base widget maintains event hash, you can write event = {'eventType elementSelector', 'BoundedFunction', ...}
Here core is used for qweb and mixins(Well we can directly require mixin and qweb)


core.js
    As the name suggest, module having some reference of core functionalities
, like Bus(Reference of EventDispatcherMixin because Bus object is created by extending EventDispatcherMixin), bus which is instance of Bus object, Class which is instance of web.Class, _t and _lt for translation, view_registry, form_widget_registry, form_tag_registry, form_custom_registry, list_widget_registry, search_widgets_registry, search_filters_registry etc

This core module basically returns instance/reference of some core classes defined in framework like Class, Bus, qweb etc.



Now We learn How old web framework and new web framework differs in implementation we can proceed, how to develop standalone application.

Develop Standalone Application

To develop standalone application using Odoo framework you either need openerpframwork.js if you are implementing your application using old style else above listed JS module files and qweb2.js where qweb engine is defined.

Once you having this files you can proceed to develop your application using Odoo web framework which will provide you Core Widget, Session management, Inheritance feature, Class concept, _super feature, include mechanism where you can include you code in some JS object(keep old functionality but include your logic in that method or completely rewrite method), Odoo framework provides powerfull templating i.e. qweb template, rpc method to interact with your Odoo server(or your own Server if it can handle request sent through Odoo web framework), jsonRpc method to do jsonRpc call to server and lot more features.

So you can create your large standalone app with Odoo framework with more readable code and OOP concepts in Javascript, with Odoo framework your code can maintainable as your app is going to be developed with some standard like creation of widget, maintaining of session etc.


Development of application depends on you, how your application will be designed and all etc stuff will depend on you but let me give you small example where I developed chrome extension which adapts Odoo framework and uses standard qweb template for creating/designing screens.

As it is standalone application and its a chrome extension so its having one manifest file and manifest file will define which is landing page when extension is started, following link will give brief introduction about how to create any chrome extension.
https://developer.chrome.com/extensions/getstarted

Now say for example in my manifest.json I defined that my landing page is index.html
"browser_action": {
        "default_icon": "static/src/img/logo.png",
        "default_popup": "index.html"
    },

So I am telling chrome to open index.html file when my extension logo is clicked, now this index.html file will imports all JS files needed i.e. all JS files qweb2.js, boot.js, class.js, time.js, ajax.js, utils.js, translation.js, session.js, core.js, widget.js, registry.js and your other JS files where you defined your widget, screens and one JS(yourApplicationName.js) file which will have anonymous function which will be called on document ready.

This yourApplicationName.js file which will instantiate Your core widget which is developed using Odoo Framework by extending web.Widget.

Something like: 

Your Core widget may look like:

function odoo_chrome_core_widget(website_forum_chrome) {
odoo.define('my_app.core', function (require) {
    var Widget = require('web.Widget');
    my_app_chrome.my_app_core_widget = Widget.extend({
        init: function() {
             //Initialization stuff
        },
        start: function() {
             //Start method stuff, may have some event binding and etc stuff
        },
        //Some other methods, may be create some other widgets and instantiate    here in this core widget
    });
};

yourApplicationName.js may look like:

my_app_chrome = _.clone(openerp);
(function() {
    'use strict';

    odoo_chrome_core_widget(website_forum_chrome); //Import widget.js

    odoo_chrome_core_widget.App = (function() {
        function App($element) {
            this.initialize($element);
        };
        App.prototype.initialize = function($element) {
            this.my_core_widget = new my_app_chrome.my_app_core_widget(null, {});
           this.my_core_widget.appendTo($element);
        };
    })();

    jQuery(document).ready(function() {
        var app = new  odoo_chrome_core_widget.App($(".YourElementClass"));
    });
})();


Let me explain above code, here we defined one anonymous function which will be triggered when this JS file is loaded, this will create one App prototype and define document.ready function, now when our DOM is ready this ready function will create instance of odoo_chrome_core_widget with Element(Class Selector) defined in index.html where we want to push core widget, this odoo_chrome_core_widget.App will create an instance of our core widget i.e. my_app_chrome.my_app_core_widget which developed using Odoo framework(by extending web.Widget), see coreWidget.js code.

So this way whole application can be designed where one anonymous function will starts the initialization and then we will have control over our core widget, and rest of the things will be rendered through our widget, our core widget will have template to render and logic to handle some events, our core widget may create some other widgets and those widget may pushed to the DOM.


Feel free to raise your queries in comment box, your inputs are welcomed and will enrich me to improve this blog.