Antony Lesuisse (OpenERP) has proposed merging lp:~openerp-dev/openerp-web/trunk-remove-fvg-from-controllers-fme into lp:openerp-web.
Requested reviews: OpenERP R&D Web Team (openerp-dev-web) For more details, see: https://code.launchpad.net/~openerp-dev/openerp-web/trunk-remove-fvg-from-controllers-fme/+merge/138364 -- https://code.launchpad.net/~openerp-dev/openerp-web/trunk-remove-fvg-from-controllers-fme/+merge/138364 Your team OpenERP R&D Team is subscribed to branch lp:~openerp-dev/openerp-web/trunk-remove-fvg-from-controllers-fme.
=== modified file 'addons/web/controllers/main.py' --- addons/web/controllers/main.py 2012-11-29 11:41:32 +0000 +++ addons/web/controllers/main.py 2012-12-06 02:35:27 +0000 @@ -1121,41 +1121,6 @@ class View(openerpweb.Controller): _cp_path = "/web/view" - def fields_view_get(self, req, model, view_id, view_type, - transform=True, toolbar=False, submenu=False): - Model = req.session.model(model) - fvg = Model.fields_view_get(view_id, view_type, req.context, toolbar, submenu) - # todo fme?: check that we should pass the evaluated context here - self.process_view(req.session, fvg, req.context, transform, (view_type == 'kanban')) - return fvg - - def process_view(self, session, fvg, context, transform, preserve_whitespaces=False): - # depending on how it feels, xmlrpclib.ServerProxy can translate - # XML-RPC strings to ``str`` or ``unicode``. ElementTree does not - # enjoy unicode strings which can not be trivially converted to - # strings, and it blows up during parsing. - - # So ensure we fix this retardation by converting view xml back to - # bit strings. - if isinstance(fvg['arch'], unicode): - arch = fvg['arch'].encode('utf-8') - else: - arch = fvg['arch'] - fvg['arch_string'] = arch - - fvg['arch'] = xml2json_from_elementtree( - ElementTree.fromstring(arch), preserve_whitespaces) - - if 'id' in fvg['fields']: - # Special case for id's - id_field = fvg['fields']['id'] - id_field['original_type'] = id_field['type'] - id_field['type'] = 'id' - - for field in fvg['fields'].itervalues(): - for view in field.get("views", {}).itervalues(): - self.process_view(session, view, None, transform) - @openerpweb.jsonrequest def add_custom(self, req, view_id, arch): CustomView = req.session.model('ir.ui.view.custom') @@ -1179,10 +1144,6 @@ return {'result': True} return {'result': False} - @openerpweb.jsonrequest - def load(self, req, model, view_id, view_type, toolbar=False): - return self.fields_view_get(req, model, view_id, view_type, toolbar=toolbar) - class TreeView(View): _cp_path = "/web/treeview" === modified file 'addons/web/static/src/js/search.js' --- addons/web/static/src/js/search.js 2012-11-29 11:24:13 +0000 +++ addons/web/static/src/js/search.js 2012-12-06 02:35:27 +0000 @@ -341,12 +341,10 @@ if (this.headless) { this.ready.resolve(); } else { - var load_view = this.rpc("/web/view/load", { - model: this.model, + var load_view = instance.web.fields_view_get({ + model: this.dataset._model, view_id: this.view_id, view_type: 'search', - context: instance.web.pyeval.eval( - 'context', this.dataset.get_context()) }); $.when(load_view).then(function (r) { === modified file 'addons/web/static/src/js/testing.js' --- addons/web/static/src/js/testing.js 2012-11-30 17:52:49 +0000 +++ addons/web/static/src/js/testing.js 2012-12-06 02:35:27 +0000 @@ -10,7 +10,7 @@ formats: ['coresetup', 'dates'], chrome: ['corelib', 'coresetup'], views: ['corelib', 'coresetup', 'data', 'chrome'], - search: ['data', 'coresetup', 'formats'], + search: ['views', 'formats'], list: ['views', 'data'], form: ['data', 'views', 'list', 'formats'], list_editable: ['list', 'form', 'data'], === modified file 'addons/web/static/src/js/view_form.js' --- addons/web/static/src/js/view_form.js 2012-12-03 18:42:14 +0000 +++ addons/web/static/src/js/view_form.js 2012-12-06 02:35:27 +0000 @@ -1189,36 +1189,19 @@ }); } }, - view_arch_to_dom_node: function(arch) { - // Historic mess for views arch - // - // server: - // -> got xml as string - // -> parse to xml and manipulate domains and contexts - // -> convert to json - // client: - // -> got view as json - // -> convert back to xml as string - // -> parse it as xml doc (manipulate button@type for IE) - // -> convert back to string - // -> parse it as dom element with jquery - // -> for each widget, convert node to json - // - // Wow !!! - var xml = instance.web.json_node_to_xml(arch); - - var doc = $.parseXML('<div class="oe_form">' + xml + '</div>'); + get_arch_fragment: function() { + var doc = $.parseXML(instance.web.json_node_to_xml(this.fvg.arch)).documentElement; + // IE won't allow custom button@type and will revert it to spec default : 'submit' $('button', doc).each(function() { $(this).attr('data-button-type', $(this).attr('type')).attr('type', 'button'); }); - xml = instance.web.xml_to_str(doc); - return $(xml); + return $('<div class="oe_form"/>').append(instance.web.xml_to_str(doc)); }, render_to: function($target) { var self = this; this.$target = $target; - this.$form = this.view_arch_to_dom_node(this.fvg.arch); + this.$form = this.get_arch_fragment(); this.process_version(); === modified file 'addons/web/static/src/js/view_tree.js' --- addons/web/static/src/js/view_tree.js 2012-11-26 14:05:25 +0000 +++ addons/web/static/src/js/view_tree.js 2012-12-06 02:35:27 +0000 @@ -9,6 +9,7 @@ instance.web.views.add('tree', 'instance.web.TreeView'); instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeView# */{ display_name: _lt('Tree'), + view_type: 'tree', /** * Indicates that this view is not searchable, and thus that no search * view should be displayed (if there is one active). @@ -36,18 +37,9 @@ this.options = _.extend({}, this.defaults, options || {}); _.bindAll(this, 'color_for'); + this.on('view_loaded', self, self.load_tree); }, - start: function () { - return this.rpc("/web/treeview/load", { - model: this.model, - view_id: this.view_id, - view_type: "tree", - toolbar: this.view_manager ? !!this.view_manager.sidebar : false, - context: instance.web.pyeval.eval( - 'context', this.dataset.get_context()) - }).done(this.on_loaded); - }, /** * Returns the list of fields needed to correctly read objects. * @@ -64,7 +56,7 @@ } return fields; }, - on_loaded: function (fields_view) { + load_tree: function (fields_view) { var self = this; var has_toolbar = !!fields_view.arch.attrs.toolbar; // field name in OpenERP is kinda stupid: this is the name of the field === modified file 'addons/web/static/src/js/views.js' --- addons/web/static/src/js/views.js 2012-12-06 01:43:34 +0000 +++ addons/web/static/src/js/views.js 2012-12-06 02:35:27 +0000 @@ -1198,13 +1198,11 @@ } else { if (! this.view_type) console.warn("view_type is not defined", this); - view_loaded = this.rpc("/web/view/load", { - "model": this.dataset.model, + view_loaded = instance.web.fields_view_get({ + "model": this.dataset._model, "view_id": this.view_id, "view_type": this.view_type, - toolbar: !!this.options.$sidebar, - context: instance.web.pyeval.eval( - 'context', this.dataset.get_context(context)) + "toolbar": !!this.options.$sidebar, }); } return view_loaded.then(function(r) { @@ -1379,12 +1377,53 @@ } }); -instance.web.xml_to_json = function(node) { +/** + * Performs a fields_view_get and apply postprocessing. + * return a {$.Deferred} resolved with the fvg + * + * @param {Object} [args] + * @param {String|Object} args.model instance.web.Model instance or string repr of the model + * @param {null|Object} args.context context if args.model is a string + * @param {null|Number} args.view_id id of the view to be loaded, default view if null + * @param {null|String} args.view_type type of view to be loaded if view_id is null + * @param {Boolean} [args.toolbar=false] get the toolbar definition + */ +instance.web.fields_view_get = function(args) { + function postprocess(fvg) { + var doc = $.parseXML(fvg.arch).documentElement; + fvg.arch = instance.web.xml_to_json(doc, (doc.nodeName.toLowerCase() !== 'kanban')); + if ('id' in fvg.fields) { + // Special case for id's + var id_field = fvg.fields['id']; + id_field.original_type = id_field.type; + id_field.type = 'id'; + } + _.each(fvg.fields, function(field) { + _.each(field.views || {}, function(view) { + postprocess(view); + }); + }); + return fvg; + } + args = _.defaults(args, { + toolbar: false, + }); + var model = args.model; + if (typeof(model) === 'string') { + model = new instance.web.Model(args.model, args.context); + } + return args.model.call('fields_view_get', [args.view_id, args.view_type, model.context(), args.toolbar]).then(function(fvg) { + return postprocess(fvg); + }); +}; + +instance.web.xml_to_json = function(node, strip_whitespace) { switch (node.nodeType) { + case 9: + return instance.web.xml_to_json(node.documentElement, strip_whitespace); case 3: case 4: - return node.data; - break; + return (strip_whitespace && node.data.trim() === '') ? undefined : node.data; case 1: var attrs = $(node).getAttributes(); _.each(['domain', 'filter_domain', 'context', 'default_get'], function(key) { @@ -1397,7 +1436,9 @@ return { tag: node.tagName.toLowerCase(), attrs: attrs, - children: _.map(node.childNodes, instance.web.xml_to_json) + children: _.compact(_.map(node.childNodes, function(node) { + return instance.web.xml_to_json(node, strip_whitespace); + })), } } } @@ -1449,26 +1490,6 @@ throw new Error(_t("Could not serialize XML")); } }; -instance.web.str_to_xml = function(s) { - if (window.DOMParser) { - var dp = new DOMParser(); - var r = dp.parseFromString(s, "text/xml"); - if (r.body && r.body.firstChild && r.body.firstChild.nodeName == 'parsererror') { - throw new Error(_t("Could not parse string to xml")); - } - return r; - } - var xDoc; - try { - xDoc = new ActiveXObject("MSXML2.DOMDocument"); - } catch (e) { - throw new Error(_.str.sprintf( _t("Could not find a DOM Parser: %s"), e.message)); - } - xDoc.async = false; - xDoc.preserveWhiteSpace = true; - xDoc.loadXML(s); - return xDoc; -} /** * Registry for all the main views === modified file 'addons/web/static/test/list-editable.js' --- addons/web/static/test/list-editable.js 2012-11-16 11:55:44 +0000 +++ addons/web/static/test/list-editable.js 2012-12-06 02:35:27 +0000 @@ -183,7 +183,7 @@ } return []; }); - mock('/web/view/load', function () { + mock('demo:fields_view_get', function () { return { type: 'tree', fields: { @@ -191,15 +191,7 @@ b: {type: 'char', string: "B"}, c: {type: 'char', string: "C"} }, - arch: { - tag: 'tree', - attrs: {}, - children: [ - {tag: 'field', attrs: {name: 'a'}}, - {tag: 'field', attrs: {name: 'b'}}, - {tag: 'field', attrs: {name: 'c'}} - ] - } + arch: '<tree><field name="a"/><field name="b"/><field name="c"/></tree>', }; }); } @@ -247,7 +239,7 @@ mock('demo:read', function () { return [{ id: 1, a: 'foo', b: 'bar', c: 'baz' }]; }); - mock('/web/view/load', function () { + mock('demo:fields_view_get', function () { return { type: 'tree', fields: { @@ -255,15 +247,7 @@ b: {type: 'char', string: "B"}, c: {type: 'char', string: "C"} }, - arch: { - tag: 'tree', - attrs: {}, - children: [ - {tag: 'field', attrs: {name: 'a'}}, - {tag: 'field', attrs: {name: 'b'}}, - {tag: 'field', attrs: {name: 'c'}} - ] - } + arch: '<tree><field name="a"/><field name="b"/><field name="c"/></tree>', }; }); } @@ -320,19 +304,13 @@ templates: true, }, function (test) { test('record-to-read', {asserts: 4}, function (instance, $fix, mock) { - mock('/web/view/load', function () { + mock('demo:fields_view_get', function () { return { type: 'tree', fields: { a: {type: 'char', string: "A"} }, - arch: { - tag: 'tree', - attrs: { on_write: 'on_write', colors: 'red:a == "foo"' }, - children: [ - {tag: 'field', attrs: {name: 'a'}} - ] - } + arch: '<tree on_write="on_write" colors="red:a == \'foo\'"><field name="a"/></tree>', }; }); mock('demo:read', function (args, kwargs) { === modified file 'addons/web/static/test/list.js' --- addons/web/static/test/list.js 2012-11-16 11:55:44 +0000 +++ addons/web/static/test/list.js 2012-12-06 02:35:27 +0000 @@ -4,20 +4,13 @@ templates: true }, function (test) { test('record-deletion', {asserts: 2}, function (instance, $fix, mock) { - mock('/web/view/load', function () { + mock('demo:fields_view_get', function () { return { type: 'tree', fields: { a: {type: 'char', string: "A"} }, - arch: { - tag: 'tree', - attrs: { }, - children: [ - {tag: 'field', attrs: {name: 'a'}}, - {tag: 'button', attrs: {type: 'object', name: 'foo'}} - ] - } + arch: '<tree><field name="a"/><button type="object" name="foo"/></tree>', }; }); mock('demo:read', function (args, kwargs) { === modified file 'addons/web/static/test/search.js' --- addons/web/static/test/search.js 2012-11-29 11:24:13 +0000 +++ addons/web/static/test/search.js 2012-12-06 02:35:27 +0000 @@ -152,25 +152,14 @@ instance.dummy = {}; instance.dummy.DummyWidget = instance.web.search.Field.extend( dummy_widget_attributes || {}); - if (!('/web/view/load' in instance.session.responses)) { - instance.session.responses['/web/view/load'] = function () { + if (!('dummy.model:fields_view_get' in instance.session.responses)) { + instance.session.responses['dummy.model:fields_view_get'] = function () { return { type: 'search', fields: { dummy: {type: 'char', string: "Dummy"} }, - arch: { - tag: 'search', - attrs: {}, - children: [{ - tag: 'field', - attrs: { - name: 'dummy', - widget: 'dummy' - }, - children: [] - }] - } + arch: '<search><field name="dummy" widget="dummy"/></search>' }; }; } @@ -183,7 +172,7 @@ }; }; - var dataset = {model: 'dummy.model', get_context: function () { return {}; }}; + var dataset = new instance.web.DataSet(null, 'dummy.model'); var view = new instance.web.SearchView(null, dataset, false, defaults); var self = this; view.on('invalid_search', self, function () { @@ -926,31 +915,16 @@ rpc: 'mock', templates: true, setup: function (instance, $s, mock) { - mock('/web/view/load', function () { + mock('dummy.model:fields_view_get', function () { // view with a single group of filters return { type: 'search', fields: {}, - arch: { - tag: 'search', - attrs: {}, - children: [{ - tag: 'filter', - attrs: { string: "Foo1", domain: [ ['foo', '=', '1'] ] }, - children: [] - }, { - tag: 'filter', - attrs: { - name: 'foo2', - string: "Foo2", - domain: [ ['foo', '=', '2'] ] }, - children: [] - }, { - tag: 'filter', - attrs: { string: "Foo3", domain: [ ['foo', '=', '3'] ] }, - children: [] - }] - } + arch: '<search>' + + '<filter string="Foo1" domain="[ [\'foo\', \'=\', \'1\'] ]"/>' + + '<filter name="foo2" string="Foo2" domain="[ [\'foo\', \'=\', \'2\'] ]"/>' + + '<filter string="Foo3" domain="[ [\'foo\', \'=\', \'3\'] ]"/>' + + '</search>', }; }); }
_______________________________________________ Mailing list: https://launchpad.net/~openerp-dev-gtk Post to : openerp-dev-gtk@lists.launchpad.net Unsubscribe : https://launchpad.net/~openerp-dev-gtk More help : https://help.launchpad.net/ListHelp