Search 1.9 billion lines of Odoo code on GitHub

web_unleashed

Author: Trobz
License: no license
Branch: 7.0-web-unleashed-195542
Repository: trobz/web
Dependencies: web
Languages: CSS (10, 0.2%), JavaScript (5154, 91.9%), Markdown (334, 6.0%), Python (78, 1.4%), and XML (33, 0.6%)
Other repositories: IlyasRakhimkulov/openerp-web-unleashed, Nucleoos/openerp-web-unleashed, OdooBulgaria/openerp-web-unleashed, OpenStone/openerp-web-unleashed, Shebak/openerp-web-unleashed, VbossEkat/openerp-web-unleashed, alhashash/openerp-web-unleashed, anhvu-sg/openerp-web-unleashed, ashnur/openerp-web-unleashed, dw250100785/openerp-web-unleashed, gitlabuser/openerp-web-unleashed, gsunjka/openerp-web-unleashed, jeffery9/openerp-web-unleashed, judaa11/openerp-web-unleashed, lmcclanahan/openerp-web-unleashed, trobz/openerp-web-unleashed, williamcastrillon/openerp-web-unleashed, yelizariev/openerp-web-unleashed, and zuloloxi/openerp-web-unleashed

<p><a href="https://travis-ci.org/trobz/openerp-web-unleashed"><img src="https://travis-ci.org/trobz/openerp-web-unleashed.png?branch=master" alt="Build Status"></a></p> <p>By default, the web part of OpenERP is not easy, the documentation is minimalist and the architecture is hard to understand.</p> <p>This is a pure web module with one objective: providing good bases to build rich web application in OpenERP.</p> <h2>Features</h2> <ul> <li>clear MVC pattern, based on Backbone and Marionnette... with all their documentations ! </li> <li>new namespace to organize and get access to your objects</li> <li>full-featured Backbone Models with OpenERP JSON-RPC API support</li> <li>QWeb rendering for Marionette views</li> <li>base objects to build custom views (Pager, Grouped Collection, Extended OpenERP View, State manager...)</li> <li>unit tests for basic functionalities</li> <li>load/configuration commonly used libraries (momentjs, numeraljs, awesome-font,...) </li> </ul> <h2>Exemple</h2> <p>Checkout the <a href="https://github.com/trobz/openerp-web-unleashed/tree/master/demo_todo">demo_todo module</a>, it&#39;s a full featured example with comments. </p> <h3>Features</h3> <ul> <li>module initialization</li> <li>Backbone data access with JSON-RPC API</li> <li>layout definition based on Marionette</li> <li>native OpenERP search widget support</li> <li>pagination support</li> <li>custom &#39;todo&#39; view type</li> </ul> <h1>Architecture</h1> <h2>Files organization</h2> <p>A good architecture start with a good file organization. A common practice is to separate each object in one fileand organize objects in logical folder.</p> <p>A module build with Web Unleashed will look like:</p> <p><code> - static - lib/ // all external lib dependencies - src/ - js/ - models/ - collections/ - views/ - utils/ // any useful lib - my_module.js // the web module entry point - templates/ // QWeb templates - tests/ // jsunit tests - images/ - css/ - ... </code></p> <p>Note: - this is a basic organization, <code>js</code> subfolder can have specific folders to organize your module code logically.</p> <h2>Unleashed namespace</h2> <p><code>openerp.unleashed</code></p> <p>This namespace is a Marionette Application, each web OpenERP module that uses Unleashed are submodules of this Application.</p> <p>A module object has few helpers to set/get object in his namespace:</p> <p><code>js // basic getter/setter openerp.unleashed.module(&#39;my_module&#39;).set(namespace, name, object) openerp.unleashed.module(&#39;my_module&#39;).get(namespace, name) // helpers openerp.unleashed.module(&#39;my_module&#39;).views(view_name, object) openerp.unleashed.module(&#39;my_module&#39;).collections(collection_name, object) openerp.unleashed.module(&#39;my_module&#39;).models(model_name, object) openerp.unleashed.module(&#39;my_module&#39;).utils(name, object) </code></p> <p>Notes: </p> <ul> <li>you never have to call the full namespace path, the module object is always passed to your module scope when you have declare a new object, see <a href="#object-declaration">object declaration</a> for details </li> <li>the module name has to be the technical name of your OpenERP module</li> </ul> <h3>Module initialization</h3> <p>In OpenERP web, you need to define a method on openerp namespace to know when OpenERP is ready to process your code, like this:</p> <p><code>js openerp.my_module = function(instance){ //openerp is ready to do stuff for your module ! }; </code></p> <p>With Unleashed, you can declare a ready method as many time as you want, and from anywhere, Unleashed will ensure that OpenERP is ready to execute your code.</p> <p>In addition to ensure that OpenERP is fully loaded, some useful arguments are passed to the function, like the base module object, the latest Backbone and Underscore version, and the current module object.</p> <p><code>js openerp.unleashed.module(&#39;my_module&#39;).ready(function(instance, my_module, _, Backbone, base_module) { // openerp is ready and you can benefit from // the lastest Backbone and Underscore version here ! }); </code></p> <p>Notes:</p> <ul> <li>Backbone and Underscore are already included in OpenERP, but they are using old version. Unleashed include the latest version of these libraries in noConflict mode.</li> </ul> <h3>Object declaration</h3> <p>To be able to split object in different files, and keep the code organization in the global scope, you have to use the module scope.</p> <p>In this scope, you have access to the module object, the base module object, the latest Underscore and Backbone version.</p> <p><strong>create a new object</strong></p> <p>```js openerp.unleashed.module(&#39;my<em>module&#39;, function(my</em>module, _, Backbone, base){ var _super = Backbone.View.prototype; var GreatView = Backbone.View.extend({</p> <pre><code> initialize: function(){ } }); my_module.views(&#39;GreatView&#39;, GreatView); </code></pre> <p>}); ```</p> <p>In this example, a new view extend the basic Backbone View and is added to <code>my_module</code> namespace with the name &quot;GreatView&quot;.</p> <p>Now you have access to this object from anywhere by simply using the name you used to declare it:</p> <p><code>js ... var GreatView = my_module.views(&#39;GreatView&#39;), view = new GreatView(); ... </code></p> <p>Note: - because OpenERP is not using an AMD/module loader system like RequireJS, you have to ensure that your files are loaded in the correct order in <code>__openerp__.py</code> file.<br> We are working on requirejs support for OpenERP, it&#39;s planned for the next release of unleashed.</p> <h2>Base module</h2> <p>Unleash provide some useful Backbone extension:</p> <h3>JSON-RPC API Model support</h3> <p>By using the <code>BaseModel</code> and <code>BaseCollection</code> from the base module, the JSON-RPC API is automatically implemented.</p> <p><strong>create a new &quot;JSON-RPC API ready&quot; collection</strong></p> <p>```js openerp.unleashed.module(&#39;my<em>module&#39;, function(my</em>module, _, Backbone, base){</p> <pre><code>var BaseCollection = base.collections(&#39;BaseCollection&#39;), _super = BaseCollection.prototype; var Employees = BaseCollection.extend({ model_name: &#39;hr.employee&#39;, // your classic backbone code here ! }); my_module.collections(&#39;Employees&#39;, Employees); </code></pre> <p>}); ```</p> <p>Now, you are ready to use this model, somewhere else, you can do:</p> <p>```js openerp.unleashed.module(&#39;my<em>module&#39;, function(my</em>module, _, Backbone, base){</p> <pre><code>var Employees = my_module.collections(&#39;Employees&#39;), employees = new Employees(); employees.fetch({ filter: [[&#39;name&#39;, &#39;like&#39;, &#39;toto&#39;]] }); employees.done(function(){ //employees.length = nb employee in db with like &#39;%toto%&#39; }); </code></pre> <p>}); ```</p> <ul> <li><code>employees</code> is a Backbone Collection, populated with Backbone Model, with all what it imply !</li> <li>you can pass to <code>fetch</code> method all JSON-RPC API js client options:<br> <code>filter</code>, <code>order</code>, <code>limit</code>, <code>offset</code>, <code>context</code>, <code>fields</code></li> </ul> <h3>Collection with <code>group_by</code> lazy loading support</h3> <p>When you fetch your collection with a <code>group_by</code> option, the collection is populated with special <code>GroupQuery</code> models.</p> <p>These special Models are able to get the result of each groups, allowing to list the group first in the interface and lazy load each of them after an action.</p> <p>To get the result of each of them, you simply have to call <code>fetch</code> on them, the <code>GroupQuery</code> will make an instance of the Collection his coming from and populate it with the groupment result.</p> <p>Notes: - if a grouped collection is fetched without a <code>group_by</code> query later, the collection will be populated with &quot;normal&quot; model again. - the Pager collection support <code>group_by</code> queries too, the pagination is simply disabled during grouping queries.</p> <p><strong>example</strong></p> <p>```js var BaseCollection = base.collections(&#39;BaseCollection&#39;), BaseModel = base.models(&#39;BaseModel&#39;), GroupQuery = base.models(&#39;GroupQuery&#39;);</p> <p>var CustomGroupQuery = GroupQuery.extend({ some_method: function(){...} });</p> <p>var CustomModel = BaseModel.extend({ model_name: &#39;your.model&#39; });</p> <p>var CustomCollection = BaseCollection.extend({ model_name: &#39;your.model&#39;, model: CustomModel,</p> <pre><code>/* you can define the GroupQuery to use when a collection is * fetched with a group_by query, useful to add specific methods * on group themself, */ otherwise GroupQuery Model is used instead group_model: CustomGroupQuery </code></pre> <p>});</p> <p>// create a new instance of collection var collection = new CustomCollection();</p> <p>var promise = collection.fetch({ group_by: [&#39;type&#39;] });</p> <p>promise.done(function(){ /* * the collection is populated with GroupQuery model */</p> <pre><code>// collection.length == your.model grouped by type // collection.grouped() == true var group_query = collection.at(0); // group_query instanceof CustomGroupQuery // group_query.get(&#39;value&#39;) == type group name // group_query.get(&#39;length&#39;) == number of element in the group // collection where will be set group results var list = group_query.group; // list instanceof CustomCollection // get all grouped items var group_promise = group_query.fetch(): group_promise.done(function(){ /* * the group is populated with Model */ // list.length == group_query.get(&#39;length&#39;) var model = list.at(0); // model instanceof CustomModel }); </code></pre> <p>}); ```</p> <h3>Unleashed View</h3> <p>OpenERP View has been extended to add some default behavior/features.</p> <p><strong>instanciation</strong></p> <p>```js openerp.unleashed.module(&#39;my<em>module&#39;).ready(function(instance, my</em>module, _, Backbone, base) {</p> <pre><code>var UnleashedView = base.views(&#39;Unleashed&#39;); instance.web.views.add(&#39;foo&#39;, &#39;instance.my_module.FooView&#39;); instance.booking_chart.FooView = UnleashedView.extend({ display_name: base._lt(&#39;Foo&#39;), template: &quot;Foo&quot;, view_type: &#39;foo&#39;, /* * You can redefine views and models used by UnleashedView, * specially for the State, usually each view has his own way * to keep the view state persistent. * * Check comment on State and Panel objects for more details. */ Panel: base.views(&#39;Panel&#39;), State: base.models(&#39;State&#39;), /* * Configure the state before processing it * the state is processed after &quot;start&quot; and before &quot;ready&quot; execution. * * Depending of your state model, you will certainly have to configure it * before his processing, usually by linking some objects and listening * events to update the state. * * An example is available in &quot;demo_todo&quot; module. */ stateConfig: function(){ }, /* * Executed by OpenERP before view loading, usual place to instanciate * your views and models. */ start: function(){ }, /* * Pre configure the view before state processing * * @param {Object} data * View configuration object: * - arch: Object * - field_parent: Boolean * - fields: Object * - model: String * - name: String * - toolbar: Object * - type: String * - view_id: Integer */ configure: function(data){ }, /* * The view is ready to be used, called by a listener on * OpenERP View &quot;view_loaded&quot; event * * @param {Object} data * View configuration object: * - arch: Object * - field_parent: Boolean * - fields: Object * - model: String * - name: String * - toolbar: Object * - type: String * - view_id: Integer */ ready: function(data){ /* * A Marionette Panel is available, * with all OpenERP part defined as Region: * - this.panel.buttons * - this.panel.pager * - this.panel.sidebar * - this.panel.body */ } }); </code></pre> <p>}); ```</p> <p>Features automatically handled by the Unleashed View:</p> <ul> <li>the State of the view is managed by a Model, automatically pushed into the URL at state modification, you can extend the state model to had your own state logic.</li> <li>add a Marionette Panel to manage all elements available in an OpenERP view:<br> <code>buttons</code>, <code>sidebar</code>, <code>pager</code>, <code>body</code> regions. </li> </ul> <p>Checkout the <a href="https://github.com/trobz/openerp-web-unleashed/tree/master/demo_todo">demo_todo module</a> for more details.</p> <p><strong>custom view type</strong></p> <p>To support custom <code>view_type</code> in <code>ir.ui.view</code> model and to have specific view description (use <code>arch</code> config,...), you have to extend the python <code>irUiView</code> model and specify your new view.</p> <p>You can add <code>arch</code> validation and build highly configurable view in the same way than standard OpenERP views.</p> <p>A simple example of a custom type declaration is available here:<br> https://github.com/trobz/openerp-web-unleashed/blob/master/demo_todo/view/todo.py</p> <h3>Pager</h3> <p>Provide everything to have a pagination on your collection, similar than the OpenERP one but without dependencies.</p> <ul> <li>Paginated collection</li> <li>A pager view, with the same layout than the native OpenERP pager</li> </ul> <p>Checkout the <a href="https://github.com/trobz/openerp-web-unleashed/tree/master/demo_todo">demo_todo module</a> for more details.</p> <h3>Iterator</h3> <p>A Backbone collection with selectable model, this collection implement several methods like:<br> <code>next</code>, <code>previous</code>, <code>first</code>, <code>last</code>, <code>select</code>,... </p> <h2>Extra module</h2> <p><code>web_unleashed_extra</code> module contain all libraries and widget not necessary useful for all modules that uses unleashed.</p> <ul> <li>momentjs / numeraljs libraries</li> <li>fontawesome library</li> <li>twitter bootstrap, scoped with &#39;bootstrap-scoped&#39; css class</li> <li>extra base model <ul> <li>period model: used to manage a period of time as a Backbone Model</li> </ul></li> </ul> <h1>Libraries</h1> <ul> <li><a href="http://backbonejs.org">Backbone 1.1.0</a></li> <li><a href="http://underscorejs.org">Underscore 1.5.2</a></li> <li><a href="https://github.com/marionettejs/backbone.marionette/">Marionnette 1.1.0</a></li> </ul> <p><strong>Libraries in extra module</strong></p> <ul> <li><a href="http://momentjs.com">MomentJS 2.0.0</a></li> <li><a href="https://github.com/icambron/twix.js">MomentJS Twix Plugin 0.3</a></li> <li><a href="http://adamwdraper.github.com/Numeral-js/">NumeralJS 1.4.9</a></li> <li><a href="http://fontawesome.io">Font Awesome 3.2.1</a></li> <li><a href="http://getbootstrap.com">Bootstrap 3.0.0</a><br> note: all css selector are scoped with the class <code>.bootstrap_scope</code> to avoid css conflict.</li> </ul>