From 4ce473b8dc0dc53467fcd0520bc593866018f34e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 17 Aug 2011 10:55:32 +0200 Subject: [PATCH 01/60] [ADD] basics for smarter collections to back the listview and its components bzr revid: xmo@openerp.com-20110817085532-4chvix1odshuebvc --- addons/base/static/src/js/core.js | 3 + addons/base/static/src/js/list.js | 159 +++++++++++++++++++++++++- addons/base/static/test/list-utils.js | 155 +++++++++++++++++++++++++ addons/base/static/test/test.html | 1 + 4 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 addons/base/static/test/list-utils.js diff --git a/addons/base/static/src/js/core.js b/addons/base/static/src/js/core.js index 96c6cb1372a..5c2e6554785 100644 --- a/addons/base/static/src/js/core.js +++ b/addons/base/static/src/js/core.js @@ -10,6 +10,9 @@ openerp.base.core = function(openerp) { var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; // The base Class implementation (does nothing) + /** + * @class + */ openerp.base.Class = function(){}; // Create a new Class that inherits from this class diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index a0440221520..7fe995f533f 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -1179,7 +1179,164 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas }); } }); + +/** + * @class + * @extends openerp.base.Class + */ +var Events = { + /** + * @param {String} event event to listen to on the current object, null for all events + * @param {Function} handler event handler to bind to the relevant event + * @returns this + */ + bind: function (event, handler) { + var calls = this['_callbacks'] || (this._callbacks = {}); + + if (event in calls) { + calls[event].push(handler); + } else { + calls[event] = [handler]; + } + return this; + }, + /** + * @param {String} event + * @returns this + */ + trigger: function (event) { + var calls; + if (!(calls = this._callbacks)) { return this; } + var callbacks = (calls[event] || []).concat(calls[null] || []); + for(var i=0, length=callbacks.length; i + From 2f8e6e62e57898168fd67bfb904ec158b34efbe1 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 17 Aug 2011 14:55:41 +0200 Subject: [PATCH 02/60] [FIX] qweb2: incorrect tail call when using foreach() with a number (to iterate over a range) bzr revid: xmo@openerp.com-20110817125541-wh95qu7jjwa7ojef --- addons/base/static/lib/qweb/qweb2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/base/static/lib/qweb/qweb2.js b/addons/base/static/lib/qweb/qweb2.js index 89a77bf1b85..8987f1dc40e 100644 --- a/addons/base/static/lib/qweb/qweb2.js +++ b/addons/base/static/lib/qweb/qweb2.js @@ -169,7 +169,7 @@ var QWeb2 = { for (var i = 0; i < enu; i++) { _enu.push(i); } - this.foreach(context, enu, as, old_dict, callback); + this.foreach(context, _enu, as, old_dict, callback); } else { var index = 0; for (var k in enu) { From bd497353714b3d7b05af941815f649c44a3b394c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 17 Aug 2011 15:16:35 +0200 Subject: [PATCH 03/60] [IMP] convert listviews (non-editable anyway) to collections bzr revid: xmo@openerp.com-20110817131635-cv3qcbiarmlk5o3o --- addons/base/static/src/js/list.js | 197 +++++++++++++++----------- addons/base/static/src/xml/base.xml | 10 +- addons/base/static/test/list-utils.js | 48 +++++++ 3 files changed, 170 insertions(+), 85 deletions(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 7fe995f533f..810f5c4d7d5 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -50,6 +50,8 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi this.columns = []; + this.records = new Collection(); + this.set_groups(new openerp.base.ListView.Groups(this)); if (this.dataset instanceof openerp.base.DataSetStatic) { @@ -535,7 +537,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi count += record.count || 1; _(columns).each(function (column) { var field = column.id, - value = record.values[field]; + value = record.values.get(field); switch (column['function']) { case 'sum': sums[field] += value; @@ -621,7 +623,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. this.options = opts.options; this.columns = opts.columns; this.dataset = opts.dataset; - this.rows = opts.rows; + this.records = opts.records; this.$_element = $('') .appendTo(document.body) @@ -657,7 +659,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. row_clicked: function () { $(this).trigger( 'row_link', - [this.rows[this.dataset.index].data.id.value, + [this.records.at(this.dataset.index).get('id'), this.dataset]); }, render: function () { @@ -677,15 +679,12 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. if (!this.options.selectable) { return []; } - var rows = this.rows; + var records = this.records; var result = {ids: [], records: []}; this.$current.find('th.oe-record-selector input:checked') .closest('tr').each(function () { - var record = {}; - _(rows[$(this).data('index')].data).each(function (obj, key) { - record[key] = obj.value; - }); - result.ids.push(record.id); + var record = records.at($(this).data('index')); + result.ids.push(record.get('id')); result.records.push(record); }); return result; @@ -707,7 +706,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. * @returns {Number|String} the identifier of the row's object */ row_id: function (row) { - return this.rows[this.row_position(row)].data.id.value; + return this.records.at(this.row_position(row)).get('id'); }, /** * Death signal, cleans up list @@ -719,41 +718,14 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. this.$_element.remove(); }, get_records: function () { - return _(this.rows).map(function (row) { - var record = {}; - _(row.data).each(function (obj, key) { - record[key] = obj.value; - }); - return {count: 1, values: record}; - }); - }, - /** - * Transforms a record from what is returned by a dataset read (a simple - * mapping of ``$fieldname: $value``) to the format expected by list rows - * and form views: - * - * data: { - * $fieldname: { - * value: $value - * } - * } - * - * This format allows for the insertion of a bunch of metadata (names, - * colors, etc...) - * - * @param {Object} record original record, in dataset format - * @returns {Object} record displayable in a form or list view - */ - transform_record: function (record) { - // TODO: colors handling - var form_data = {}, - form_record = {data: form_data}; - - _(record).each(function (value, key) { - form_data[key] = {value: value}; - }); - - return form_record; + var records = []; + for(var i=0, length=this.records.length; i=0; --i) { + this.records.remove(this.records.get(ids[i])); + } } // drag and drop }); @@ -829,11 +795,20 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas * * Provides events similar to those of * :js:class:`~openerp.base.ListView.List` + * + * @constructs + * @param {openerp.base.ListView} view + * @param {Object} [options] + * @param {Collection} [options.records] + * @param {Object} [options.options] + * @param {Array} [options.columns] */ - init: function (view) { + init: function (view, options) { + options = options || {}; this.view = view; - this.options = view.options; - this.columns = view.columns; + this.records = options.records || view.records; + this.options = options.options || view.options; + this.columns = options.columns || view.columns; this.datagroup = null; this.$row = null; @@ -925,6 +900,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas delete self.children[group.value]; } var child = self.children[group.value] = new openerp.base.ListView.Groups(self.view, { + records: self.records.proxy(group.value), options: self.options, columns: self.columns }); @@ -1019,13 +995,12 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas }); }, render_dataset: function (dataset) { - var rows = [], - self = this, + var self = this, list = new openerp.base.ListView.List(this, { options: this.options, columns: this.columns, dataset: dataset, - rows: rows + records: this.records }); this.bind_child_events(list); @@ -1054,11 +1029,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas .attr('disabled', page === pages - 1); } - var form_records = _(records).map( - $.proxy(list, 'transform_record')); - - rows.splice(0, rows.length); - rows.push.apply(rows, form_records); + self.records.reset(records); list.render(); d.resolve(list); }); @@ -1078,7 +1049,9 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas var from = ui.item.data('index'), to = ui.item.prev().data('index') || 0; if (from === to) { return; } - list.rows.splice(to, 0, list.rows.splice(from, 1)[0]); + var to_move = list.records.at(from); + list.records.remove(to_move); + list.records.add(to_move, {at: to}); ui.item.parent().children().each(function (i, e) { // reset record-index accelerators on rows and even/odd @@ -1089,17 +1062,16 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas }); // resequencing time! - var data, index = to, + var record, index = to, // if drag to 1st row (to = 0), start sequencing from 0 // (exclusive lower bound) - seq = to ? list.rows[to - 1].data.sequence.value : 0; - while (++seq, list.rows[index]) { - data = list.rows[index].data; - data.sequence.value = seq; + seq = to ? list.records.at(to - 1).get('sequence') : 0; + while (++seq, record = list.records.at(index)) { + record.set('sequence', seq); // write are independent from one another, so we can just // launch them all at the same time and we don't really // give a fig about when they're done - dataset.write(data.id.value, {sequence: seq}); + dataset.write(record.get('id'), {sequence: seq}); list.reload_record(index++); } } @@ -1223,14 +1195,14 @@ var Record = openerp.base.Class.extend(/** @lends Record# */{ * @param {Object} [data] */ init: function (data) { - this.data = data || {}; + this.attributes = data || {}; }, /** * @param {String} key * @returns {Object} */ get: function (key) { - return this.data[key]; + return this.attributes[key]; }, /** * @param key @@ -1238,10 +1210,32 @@ var Record = openerp.base.Class.extend(/** @lends Record# */{ * @returns {Record} */ set: function (key, value) { - this.data[key] = value; + this.attributes[key] = value; this.trigger('change:' + key, this, value); this.trigger('change', this); return this; + }, + /** + * Converts the current record to the format expected by form views: + * + * .. code-block:: javascript + * + * data: { + * $fieldname: { + * value: $value + * } + * } + * + * + * @returns {Object} record displayable in a form view + */ + toForm: function () { + var form_data = {}; + _(this.attributes).each(function (value, key) { + form_data[key] = {value: value}; + }); + + return {data: form_data}; } }); Record.include(Events); @@ -1257,6 +1251,7 @@ var Collection = openerp.base.Class.extend(/** @lends Collection# */{ init: function (records, options) { options = options || {}; _.bindAll(this, '_onRecordEvent'); + this.length = 0; this.records = []; this._byId = {}; this._proxies = {}; @@ -1269,16 +1264,24 @@ var Collection = openerp.base.Class.extend(/** @lends Collection# */{ }, /** * @param {Object|Array} record + * @param {Object} [options] + * @param {Number} [options.at] * @returns this */ - add: function (record) { + add: function (record, options) { + options = options || {}; var records = record instanceof Array ? record : [record]; for(var i=0, length=records.length; i - - + + + + + + @@ -573,7 +577,7 @@ - + diff --git a/addons/base/static/test/list-utils.js b/addons/base/static/test/list-utils.js index 97431acb597..a04ae963932 100644 --- a/addons/base/static/test/list-utils.js +++ b/addons/base/static/test/list-utils.js @@ -107,10 +107,12 @@ $(document).ready(function () { }); test('Fetch from collection', function () { var c = new openerp.base.list.Collection(); + strictEqual(c.length, 0); c.add({id: 1, value: 2}); c.add({id: 2, value: 3}); c.add({id: 3, value: 5}); c.add({id: 4, value: 7}); + strictEqual(c.length, 4); var r = c.at(2), r2 = c.get(1); ok(r instanceof openerp.base.list.Record); @@ -121,6 +123,52 @@ $(document).ready(function () { strictEqual(r2.get('id'), 1); strictEqual(r2.get('value'), 2); }); + test('Add at index', function () { + var c = new openerp.base.list.Collection([ + {id: 1, value: 5}, + {id: 2, value: 10}, + {id: 3, value: 20} + ]); + strictEqual(c.at(1).get('value'), 10); + equal(c.at(3), undefined); + c.add({id:4, value: 55}, {at: 1}); + strictEqual(c.at(1).get('value'), 55); + strictEqual(c.at(3).get('value'), 20); + }); + test('Remove record', function () { + var c = new openerp.base.list.Collection([ + {id: 1, value: 5}, + {id: 2, value: 10}, + {id: 3, value: 20} + ]); + var record = c.get(2); + strictEqual(c.length, 3); + c.remove(record); + strictEqual(c.length, 2); + equal(c.get(2), undefined); + strictEqual(c.at(1).get('value'), 20); + }); + test('Reset', function () { + var event, obj, c = new openerp.base.list.Collection([ + {id: 1, value: 5}, + {id: 2, value: 10}, + {id: 3, value: 20} + ]); + c.bind(null, function (e, instance) { event = e; obj = instance; }); + c.reset(); + strictEqual(c.length, 0); + strictEqual(event, 'reset'); + strictEqual(obj, c); + c.add([ + {id: 1, value: 5}, + {id: 2, value: 10}, + {id: 3, value: 20} + ]); + c.reset([{id: 42, value: 55}]); + strictEqual(c.length, 1); + strictEqual(c.get(42).get('value'), 55); + }); + test('Events propagation', function () { var values = []; var c = new openerp.base.list.Collection([ From d433eada00cbbe3ac3a387b831e4b957b135cbb6 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 17 Aug 2011 15:36:00 +0200 Subject: [PATCH 04/60] [ADD] acknowledgement that the listview backing collections are quite strongly inspired by backbone's bzr revid: xmo@openerp.com-20110817133600-hl93utj2eh7pr5cd --- addons/base/static/src/js/list.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 810f5c4d7d5..e6514de6a24 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -1241,6 +1241,11 @@ var Record = openerp.base.Class.extend(/** @lends Record# */{ Record.include(Events); var Collection = openerp.base.Class.extend(/** @lends Collection# */{ /** + * Smarter collections, with events, very strongly inspired by Backbone's. + * + * Using a "dumb" array of records makes synchronization between the + * various serious + * * @constructs * @extends openerp.base.Class * @borrows Events#bind as this.bind From 29cb20313e795693f33e932151907fad05b1f8e2 Mon Sep 17 00:00:00 2001 From: "Mayur Maheshwari (OpenERP)" Date: Thu, 18 Aug 2011 14:24:34 +0530 Subject: [PATCH 05/60] [IMP]base:Added field Company registry after TaxID bzr revid: mma@tinyerp.com-20110818085434-2upimzqd2ty1nysa --- openerp/addons/base/base_update.xml | 1 + openerp/addons/base/res/res_company.py | 1 + 2 files changed, 2 insertions(+) diff --git a/openerp/addons/base/base_update.xml b/openerp/addons/base/base_update.xml index 6f4dbf6a1f9..b2e941b28bd 100644 --- a/openerp/addons/base/base_update.xml +++ b/openerp/addons/base/base_update.xml @@ -229,6 +229,7 @@ + diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py index b0ebeb8ac27..1aa6eb9597e 100644 --- a/openerp/addons/base/res/res_company.py +++ b/openerp/addons/base/res/res_company.py @@ -143,6 +143,7 @@ class res_company(osv.osv): 'fax': fields.function(_get_address_data, fnct_inv=_set_address_data, size=64, type='char', string="Fax", multi='address'), 'website': fields.related('partner_id', 'website', string="Website", type="char", size=64), 'vat': fields.related('partner_id', 'vat', string="Tax ID", type="char", size=32), + 'company_registry': fields.char('Company Registry', size=64), } def on_change_header(self, cr, uid, ids, phone, email, fax, website, vat, context={}): val = [] From 10117faf2c466b02488d6017654dc3405ff1ed66 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 18 Aug 2011 12:19:36 +0200 Subject: [PATCH 06/60] [FIX] edit event in editable list: use records collection bzr revid: xmo@openerp.com-20110818101936-4jbnt8rhlsjkxxyt --- addons/base/static/src/js/list-editable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/base/static/src/js/list-editable.js b/addons/base/static/src/js/list-editable.js index e56a807bf08..468e043d9a9 100644 --- a/addons/base/static/src/js/list-editable.js +++ b/addons/base/static/src/js/list-editable.js @@ -241,7 +241,7 @@ openerp.base.list.editable = function (openerp) { this.dataset.index))); $(this).trigger( 'edit', - [this.rows[this.dataset.index].data.id.value, this.dataset]); + [this.records.at(this.dataset.index).get('id'), this.dataset]); }, new_record: function () { this.dataset.index = null; From 92e06c997b181cf3f7f3724c3253d70fb981255b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 18 Aug 2011 14:21:06 +0200 Subject: [PATCH 07/60] [ADD] basic implementation of each and map on collections bzr revid: xmo@openerp.com-20110818122106-lt23fl3smbxg4f82 --- addons/base/static/src/js/list.js | 38 ++++++++++---- addons/base/static/test/list-utils.js | 72 +++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 10 deletions(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index e6514de6a24..2024b1c9881 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -376,6 +376,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi * re-renders the content of the list view */ reload_content: function () { + this.records.reset(); this.$element.find('.oe-listview-content').append( this.groups.apoptosis().render( $.proxy(this, 'compute_aggregates'))); @@ -537,7 +538,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi count += record.count || 1; _(columns).each(function (column) { var field = column.id, - value = record.values.get(field); + value = record.values[field]; switch (column['function']) { case 'sum': sums[field] += value; @@ -685,7 +686,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. .closest('tr').each(function () { var record = records.at($(this).data('index')); result.ids.push(record.get('id')); - result.records.push(record); + result.records.push(record.attributes); }); return result; }, @@ -718,14 +719,9 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. this.$_element.remove(); }, get_records: function () { - var records = []; - for(var i=0, length=this.records.length; i Date: Thu, 18 Aug 2011 15:27:47 +0200 Subject: [PATCH 08/60] [FIX] reset records on a group apoptosis, cleanout proxies when reseting a Collection bzr revid: xmo@openerp.com-20110818132747-xnsgcugx1nohc7p8 --- addons/base/static/src/js/list.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 2024b1c9881..d6a8808a63d 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -1119,6 +1119,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas }); this.children = {}; $(this.elements).remove(); + this.records.reset(); return this; }, get_records: function () { @@ -1339,6 +1340,7 @@ var Collection = openerp.base.Class.extend(/** @lends Collection# */{ _(this._proxies).each(function (proxy) { proxy.reset(); }); + this._proxies = {}; this.length = 0; this.records = []; this._byId = {}; From d69cd3cb155373237117c4de67823028120cc41e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 19 Aug 2011 12:12:08 +0200 Subject: [PATCH 09/60] [???] try to hook some stuff into reset event bzr revid: xmo@openerp.com-20110819101208-nqoroidipedo73rs --- addons/base/static/src/js/list.js | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index d6a8808a63d..6f65b124776 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -338,9 +338,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi this.sidebar.$element.show(); } if (this.hidden) { - this.$element.find('.oe-listview-content').append( - this.groups.apoptosis().render()); - this.hidden = false; + this.reload_content(); } }, do_hide: function () { @@ -378,7 +376,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi reload_content: function () { this.records.reset(); this.$element.find('.oe-listview-content').append( - this.groups.apoptosis().render( + this.groups.render( $.proxy(this, 'compute_aggregates'))); }, /** @@ -626,6 +624,8 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. this.dataset = opts.dataset; this.records = opts.records; + this.records.bind('reset', $.proxy(this, 'on_records_reset')); + this.$_element = $('') .appendTo(document.body) .delegate('th.oe-record-selector', 'click', function (e) { @@ -710,9 +710,9 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. return this.records.at(this.row_position(row)).get('id'); }, /** - * Death signal, cleans up list + * Death signal, cleans up list display */ - apoptosis: function () { + on_records_reset: function (ev, records) { if (!this.$current) { return; } this.$current.remove(); this.$current = null; @@ -811,6 +811,8 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas this.children = {}; this.page = 0; + + this.records.bind('reset', $.proxy(this, 'on_records_reset')); }, make_fragment: function () { return document.createDocumentFragment(); @@ -871,7 +873,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas }, close: function () { this.$row.children().last().empty(); - this.apoptosis(); + this.records.reset(); }, /** * Prefixes ``$node`` with floated spaces in order to indent it relative @@ -892,7 +894,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas var placeholder = this.make_fragment(); _(datagroups).each(function (group) { if (self.children[group.value]) { - self.children[group.value].apoptosis(); + self.records.proxy(group.value).reset(); delete self.children[group.value]; } var child = self.children[group.value] = new openerp.base.ListView.Groups(self.view, { @@ -1025,7 +1027,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas .attr('disabled', page === pages - 1); } - self.records.reset(records); + self.records.add(records); list.render(); d.resolve(list); }); @@ -1113,14 +1115,9 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas return {ids: ids, records: records}; }, - apoptosis: function () { - _(this.children).each(function (child) { - child.apoptosis(); - }); + on_records_reset: function () { this.children = {}; $(this.elements).remove(); - this.records.reset(); - return this; }, get_records: function () { if (_(this.children).isEmpty()) { @@ -1368,6 +1365,8 @@ var Collection = openerp.base.Class.extend(/** @lends Collection# */{ }, _onRecordEvent: function (event, record, options) { + // don't propagate reset events + if (event === 'reset') { return; } this.trigger.apply(this, arguments); }, From 32e9a10a1e62b580d1da1e2e2c22589eccd658b9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 19 Aug 2011 12:16:44 +0200 Subject: [PATCH 10/60] [IMP] only trigger change events when a field's value was actually changed, provide more information in change event bzr revid: xmo@openerp.com-20110819101644-edovs858qrz1wb3y --- addons/base/static/src/js/list.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 6f65b124776..966f35bbdde 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -1204,9 +1204,12 @@ var Record = openerp.base.Class.extend(/** @lends Record# */{ * @returns {Record} */ set: function (key, value) { + if (this.attributes[key] === value) { + return this; + } this.attributes[key] = value; this.trigger('change:' + key, this, value); - this.trigger('change', this); + this.trigger('change', this, key, value); return this; }, /** From ec9a40c8f53e02db554abdf0bbf012488d0466e9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 19 Aug 2011 12:17:23 +0200 Subject: [PATCH 11/60] [IMP] add previous field value to change events bzr revid: xmo@openerp.com-20110819101723-p73bts37knut34c8 --- addons/base/static/src/js/list.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 966f35bbdde..cee1adbdb69 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -1204,12 +1204,13 @@ var Record = openerp.base.Class.extend(/** @lends Record# */{ * @returns {Record} */ set: function (key, value) { - if (this.attributes[key] === value) { + var old_value = this.attributes[key]; + if (old_value === value) { return this; } this.attributes[key] = value; - this.trigger('change:' + key, this, value); - this.trigger('change', this, key, value); + this.trigger('change:' + key, this, value, old_value); + this.trigger('change', this, key, value, old_value); return this; }, /** From 71b057aa3402346ccfc4364d20a81a96b5e632f8 Mon Sep 17 00:00:00 2001 From: "Vidhin Mehta (OpenERP)" Date: Fri, 19 Aug 2011 16:03:22 +0530 Subject: [PATCH 12/60] [FIX]Fix add remove shortcut problem on switch view and update session. bzr revid: vme@tinyerp.com-20110819103322-7cph3n3ey7z39gkj --- addons/base/static/src/js/chrome.js | 16 ++++++++++++---- addons/base/static/src/js/views.js | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/addons/base/static/src/js/chrome.js b/addons/base/static/src/js/chrome.js index 3aff7b5e402..ec666cf8c8a 100644 --- a/addons/base/static/src/js/chrome.js +++ b/addons/base/static/src/js/chrome.js @@ -584,13 +584,17 @@ openerp.base.Header = openerp.base.Widget.extend({ sc.binding = {}; $(sc.binding).bind({ 'add': function (e, attrs) { - var $shortcut = $('
  • ', { - 'data-id': attrs.res_id + shortcuts_ds.create(attrs, function (out) { + var $shortcut = $('
  • ', { + 'data-shortcut-id':out.result, + 'data-id': attrs.res_id }).text(attrs.name) .appendTo(self.$element.find('.oe-shortcuts ul')); - shortcuts_ds.create(attrs, function (out) { - $shortcut.data('shortcut-id', out.result); + attrs.id = out.result; + sc.splice(sc.lenght,0,attrs); + sc.push.apply(sc); }); + }, 'remove-current': function () { var menu_id = self.session.active_id; @@ -599,6 +603,9 @@ openerp.base.Header = openerp.base.Widget.extend({ var shortcut_id = $shortcut.data('shortcut-id'); $shortcut.remove(); shortcuts_ds.unlink([shortcut_id]); + sc1 = _.reject(sc, function(shortcut){ return shortcut_id === shortcut.id}); + sc.splice(0, sc.length); + sc.push.apply(sc ,sc1); } }); } @@ -609,6 +616,7 @@ openerp.base.Header = openerp.base.Widget.extend({ self.$element.find('.oe-shortcuts') .html(QWeb.render('Shortcuts', {'shortcuts': shortcuts})) .undelegate('li', 'click') + .delegate('li', 'click', function(e) { e.stopPropagation(); var id = $(this).data('id'); diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js index ad75268156f..7a15f9a37ad 100644 --- a/addons/base/static/src/js/views.js +++ b/addons/base/static/src/js/views.js @@ -342,6 +342,7 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ shortcut_add_remove: function() { var self = this; var $shortcut_toggle = this.$element.find('.oe-shortcut-toggle'); + $shortcut_toggle.unbind("click").click(); $shortcut_toggle.click(function() { if ($shortcut_toggle.hasClass("oe-shortcut-remove")) { $(self.session.shortcuts.binding).trigger('remove-current'); From 1209b60a4268d47acbf84a22b4ff4c91fe8ca21e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 19 Aug 2011 12:39:55 +0200 Subject: [PATCH 13/60] [IMP] bind row and aggregate display refreshes on changes in the underlying model(s) bzr revid: xmo@openerp.com-20110819103955-gx0j7t3kxl8pjy56 --- addons/base/static/src/js/list-editable.js | 2 +- addons/base/static/src/js/list.js | 62 +++++++++++----------- addons/base/static/src/xml/base.xml | 2 +- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/addons/base/static/src/js/list-editable.js b/addons/base/static/src/js/list-editable.js index 468e043d9a9..c89227a05cb 100644 --- a/addons/base/static/src/js/list-editable.js +++ b/addons/base/static/src/js/list-editable.js @@ -105,7 +105,7 @@ openerp.base.list.editable = function (openerp) { } if (this.edition_index !== null) { - this.reload_record(this.edition_index, true).then(function () { + this.reload_record(this.edition_index).then(function () { cancelled.resolve(); }); } else { diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index cee1adbdb69..c4fd56fa3a6 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -42,6 +42,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi * @borrows openerp.base.ActionExecutor#execute_action as #execute_action */ init: function(parent, element_id, dataset, view_id, options) { + var self = this; this._super(parent, element_id); this.set_default_options(_.extend({}, this.defaults, options || {})); this.dataset = dataset; @@ -59,6 +60,13 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi } this.page = 0; + this.records.bind('change', function (event, record, key) { + if (!_(self.aggregate_columns).chain() + .pluck('name').contains(key).value()) { + return; + } + self.compute_aggregates(); + }); }, /** * Retrieves the view's number of records per page (|| section) @@ -457,16 +465,11 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi * @param {Function} callback should be called after the action is executed, if non-null */ do_button_action: function (name, id, callback) { - var self = this, - action = _.detect(this.columns, function (field) { + var action = _.detect(this.columns, function (field) { return field.name === name; }); if (!action) { return; } - this.execute_action(action, this.dataset, id, function () { - $.when(callback.apply(this, arguments).then(function () { - self.compute_aggregates(); - })); - }); + this.execute_action(action, this.dataset, id, callback); }, /** * Handles the activation of a record (clicking on it) @@ -625,6 +628,10 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. this.records = opts.records; this.records.bind('reset', $.proxy(this, 'on_records_reset')); + this.records.bind('change', function (event, record) { + var $row = self.$current.find('[data-id=' + record.get('id') + ']'); + $row.replaceWith(self.render_record($row.data('index'))); + }); this.$_element = $('') .appendTo(document.body) @@ -648,7 +655,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. index = self.row_position($row); $(self).trigger('action', [field, record_id, function () { - return self.reload_record(index, true); + return self.reload_record(index); }]); }) .delegate('tr', 'click', function (e) { @@ -707,7 +714,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. * @returns {Number|String} the identifier of the row's object */ row_id: function (row) { - return this.records.at(this.row_position(row)).get('id'); + return $(row).data('id'); }, /** * Death signal, cleans up list display @@ -732,28 +739,20 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. * @param {Number} record_index index of the record to reload * @param {Boolean} fetch fetches the record from remote before reloading it */ - reload_record: function (record_index, fetch) { - var self = this; - var read_p = null; - if (fetch) { - // save index to restore it later, if already set - var old_index = this.dataset.index; - this.dataset.index = record_index; - read_p = this.dataset.read_index( - _.pluck(_(this.columns).filter(function (r) {return r.tag === 'field';}), 'name'), - function (record) { - var r = self.records.get(record.id); - _(record).each(function (value, key) { - r.set(key, value); - }); - self.dataset.index = old_index; - } - ) - } + reload_record: function (record_index) { + var r = this.records.at(record_index); - return $.when(read_p).then(function () { - self.$current.children().eq(record_index) - .replaceWith(self.render_record(record_index)); }); + return this.dataset.read_ids( + [r.get('id')], + _.pluck(_(this.columns).filter(function (r) { + return r.tag === 'field'; + }), 'name'), + function (record) { + _(record[0]).each(function (value, key) { + r.set(key, value); + }); + } + ); }, /** * Renders a list record to HTML @@ -1065,12 +1064,11 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas // (exclusive lower bound) seq = to ? list.records.at(to - 1).get('sequence') : 0; while (++seq, record = list.records.at(index)) { - record.set('sequence', seq); // write are independent from one another, so we can just // launch them all at the same time and we don't really // give a fig about when they're done dataset.write(record.get('id'), {sequence: seq}); - list.reload_record(index++); + record.set('sequence', seq); } } }); diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index 37994228705..d67699ac145 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -563,7 +563,7 @@ + t-att-data-index="row_index" t-att-data-id="record.get('id')"> From 88dfe802fa8965114902e867cef2fead76126446 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 19 Aug 2011 13:59:07 +0200 Subject: [PATCH 14/60] [IMP] use Collection signals to handle record removal bzr revid: xmo@openerp.com-20110819115907-s7sk4n9qd00hz6d0 --- addons/base/static/src/js/list.js | 44 +++++++++++++------------------ 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index c4fd56fa3a6..9294f264588 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -435,7 +435,9 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi } var self = this; return $.when(this.dataset.unlink(ids)).then(function () { - self.groups.drop_records(ids); + _(ids).each(function (id) { + self.records.remove(self.records.get(id)); + }); self.compute_aggregates(); }); }, @@ -627,6 +629,14 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. this.dataset = opts.dataset; this.records = opts.records; + this.records.bind('remove', function (event, record) { + var $row = self.$current.find('[data-id=' + record.get('id') + ']'); + var index = $row.data('index'); + $row.nextAll().each(function (row) { + $(row).data('index', index++); + }); + $row.remove(); + }); this.records.bind('reset', $.proxy(this, 'on_records_reset')); this.records.bind('change', function (event, record) { var $row = self.$current.find('[data-id=' + record.get('id') + ']'); @@ -769,18 +779,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. row_index: record_index, render_cell: openerp.base.format_cell }); - }, - /** - * Stops displaying the records matching the provided ids. - * - * @param {Array} ids identifiers of the records to remove - */ - drop_records: function (ids) { - for(var i=ids.length-1; i>=0; --i) { - this.records.remove(this.records.get(ids[i])); - } } - // drag and drop }); openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.base.ListView.Groups# */{ passtrough_events: 'action deleted row_link', @@ -1129,19 +1128,6 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas return child.get_records(); }).flatten().value(); }, - /** - * Stops displaying the records with the linked ids, assumes these records - * were deleted from the DB. - * - * This is the up-signal from the `deleted` event on groups and lists. - * - * @param {Array} ids list of identifier of the records to remove. - */ - drop_records: function (ids) { - _.each(this.children, function (child) { - child.drop_records(ids); - }); - } }); /** @@ -1356,8 +1342,14 @@ var Collection = openerp.base.Class.extend(/** @lends Collection# */{ * @returns this */ remove: function (record) { + var self = this; var index = _(this.records).indexOf(record); - if (index === -1) { return this; } + if (index === -1) { + _(this._proxies).each(function (proxy) { + proxy.remove(record); + }); + return this; + } this.records.splice(index, 1); delete this._byId[record.get('id')]; From 2d024453a97133609a653cdc1060d65a68913f2d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 19 Aug 2011 15:21:12 +0200 Subject: [PATCH 15/60] [ADD] Collection.indexOf, fix fetching of selected records (use record id, not record index) bzr revid: xmo@openerp.com-20110819132112-y635uaukfrx2s5ii --- addons/base/static/src/js/list.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 9294f264588..996822c4a21 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -701,7 +701,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. var result = {ids: [], records: []}; this.$current.find('th.oe-record-selector input:checked') .closest('tr').each(function () { - var record = records.at($(this).data('index')); + var record = records.get($(this).data('id')); result.ids.push(record.get('id')); result.records.push(record.attributes); }); @@ -1381,6 +1381,9 @@ var Collection = openerp.base.Class.extend(/** @lends Collection# */{ results.push(callback(record)); }); return results; + }, + indexOf: function (record) { + return _(this.records).indexOf(record); } }); Collection.include(Events); From c18eff8665d913aaf07c417543c0fb0c611a7cae Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 19 Aug 2011 17:15:10 +0200 Subject: [PATCH 16/60] [IMP] add events unbinging to events mixin, fix Collection.reload() handling by List bzr revid: xmo@openerp.com-20110819151510-7posqx7mznldurd2 --- addons/base/static/src/js/list.js | 56 ++++++++++++++++++++------- addons/base/static/test/list-utils.js | 22 +++++++++++ 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 996822c4a21..642a0743e9a 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -629,19 +629,24 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. this.dataset = opts.dataset; this.records = opts.records; - this.records.bind('remove', function (event, record) { - var $row = self.$current.find('[data-id=' + record.get('id') + ']'); - var index = $row.data('index'); - $row.nextAll().each(function (row) { - $(row).data('index', index++); - }); - $row.remove(); - }); - this.records.bind('reset', $.proxy(this, 'on_records_reset')); - this.records.bind('change', function (event, record) { - var $row = self.$current.find('[data-id=' + record.get('id') + ']'); - $row.replaceWith(self.render_record($row.data('index'))); - }); + this.record_callbacks = { + 'remove': function (event, record) { + var $row = self.$current.find('[data-id=' + record.get('id') + ']'); + var index = $row.data('index'); + $row.nextAll().each(function (row) { + $(row).data('index', index++); + }); + $row.remove(); + }, + 'reset': $.proxy(this, 'on_records_reset'), + 'change': function (event, record) { + var $row = self.$current.find('[data-id=' + record.get('id') + ']'); + $row.replaceWith(self.render_record($row.data('index'))); + } + }; + _(this.record_callbacks).each(function (callback, event) { + this.records.bind(event, callback); + }, this); this.$_element = $('') .appendTo(document.body) @@ -729,7 +734,10 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. /** * Death signal, cleans up list display */ - on_records_reset: function (ev, records) { + on_records_reset: function () { + _(this.record_callbacks).each(function (callback, event) { + this.records.unbind(event, callback); + }, this); if (!this.$current) { return; } this.$current.remove(); this.$current = null; @@ -1127,7 +1135,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas .map(function (child) { return child.get_records(); }).flatten().value(); - }, + } }); /** @@ -1150,6 +1158,24 @@ var Events = { } return this; }, + /** + * @param {String} event event to unbind on the current object + * @param {function} [handler] specific event handler to remove (otherwise unbind all handlers for the event) + * @returns this + */ + unbind: function (event, handler) { + var calls = this._callbacks || {}; + if (!(event in calls)) { return this; } + if (!handler) { + delete calls[event]; + } else { + var handlers = calls[event]; + handlers.splice( + _(handlers).indexOf(handler), + 1); + } + return this; + }, /** * @param {String} event * @returns this diff --git a/addons/base/static/test/list-utils.js b/addons/base/static/test/list-utils.js index ffdc3b66b49..0b15b81f544 100644 --- a/addons/base/static/test/list-utils.js +++ b/addons/base/static/test/list-utils.js @@ -65,6 +65,28 @@ $(document).ready(function () { ok(triggered); }); + test('Unbind all handlers', function () { + var e = create(openerp.base.list.Events), passed = 0; + e.bind('foo', function () { passed++; }); + e.trigger('foo'); + strictEqual(passed, 1); + e.unbind('foo'); + e.trigger('foo'); + strictEqual(passed, 1); + }); + test('Unbind one handler', function () { + var e = create(openerp.base.list.Events), p1 = 0, p2 = 0, + h1 = function () { p1++; }, h2 = function () { p2++; }; + e.bind('foo', h1); + e.bind('foo', h2); + e.trigger('foo'); + strictEqual(p1, 1); + strictEqual(p2, 1); + e.unbind('foo', h1); + e.trigger('foo'); + strictEqual(p1, 1); + strictEqual(p2, 2); + }); module('list-records', { setup: function () { From 885fa0ded0b7417be2fe2aad28a51f2a53ef92a8 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 22 Aug 2011 11:04:58 +0200 Subject: [PATCH 17/60] [ADD] handling of adding new records to an existing collection, silent option on a bunch of record events bzr revid: xmo@openerp.com-20110822090458-3wdroe4cxyh30k91 --- addons/base/static/src/js/formats.js | 3 ++ addons/base/static/src/js/list-editable.js | 2 ++ addons/base/static/src/js/list.js | 40 ++++++++++++++++++---- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/addons/base/static/src/js/formats.js b/addons/base/static/src/js/formats.js index 074cabe5eee..abb05ec9dc4 100644 --- a/addons/base/static/src/js/formats.js +++ b/addons/base/static/src/js/formats.js @@ -201,6 +201,9 @@ openerp.base.format_cell = function (row_data, column, value_if_empty) { ].join('') } + if (!row_data[column.id]) { + return value_if_empty === undefined ? '' : value_if_empty; + } return openerp.base.format_value( row_data[column.id].value, column, value_if_empty); } diff --git a/addons/base/static/src/js/list-editable.js b/addons/base/static/src/js/list-editable.js index c89227a05cb..744f3c9a09b 100644 --- a/addons/base/static/src/js/list-editable.js +++ b/addons/base/static/src/js/list-editable.js @@ -209,6 +209,8 @@ openerp.base.list.editable = function (openerp) { var self = this; this.edition_form.do_save(function (result) { if (result.created && !self.edition_index) { + self.records.add({id: result.result}, + {at: self.options.editable === 'top' ? 0 : null}); self.edition_index = self.dataset.index; } self.cancel_pending_edition().then(function () { diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 642a0743e9a..f35d5318cdc 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -642,6 +642,20 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. 'change': function (event, record) { var $row = self.$current.find('[data-id=' + record.get('id') + ']'); $row.replaceWith(self.render_record($row.data('index'))); + }, + 'add': function (ev, records, record, index) { + var $row = $('').attr({ + 'data-id': record.get('id'), + 'data-index': index + }); + if (index === 0) { + $row.prependTo(self.$current); + } else { + $row.insertAfter(self.$current.children().eq(index)); + } + $row.nextAll().each(function (row) { + $(row).data('index', ++index); + }); } }; _(this.record_callbacks).each(function (callback, event) { @@ -767,8 +781,9 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. }), 'name'), function (record) { _(record[0]).each(function (value, key) { - r.set(key, value); + r.set(key, value, {silent: true}); }); + r.trigger('change', r); } ); }, @@ -1033,7 +1048,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas .attr('disabled', page === pages - 1); } - self.records.add(records); + self.records.add(records, {silent: true}); list.render(); d.resolve(list); }); @@ -1211,16 +1226,21 @@ var Record = openerp.base.Class.extend(/** @lends Record# */{ /** * @param key * @param value + * @param {Object} [options] + * @param {Boolean} [options.silent=false] * @returns {Record} */ - set: function (key, value) { + set: function (key, value, options) { + options = options || {}; var old_value = this.attributes[key]; if (old_value === value) { return this; } this.attributes[key] = value; - this.trigger('change:' + key, this, value, old_value); - this.trigger('change', this, key, value, old_value); + if (!options.silent) { + this.trigger('change:' + key, this, value, old_value); + this.trigger('change', this, key, value, old_value); + } return this; }, /** @@ -1279,6 +1299,7 @@ var Collection = openerp.base.Class.extend(/** @lends Collection# */{ * @param {Object|Array} record * @param {Object} [options] * @param {Number} [options.at] + * @param {Boolean} [options.silent=false] * @returns this */ add: function (record, options) { @@ -1291,8 +1312,15 @@ var Collection = openerp.base.Class.extend(/** @lends Collection# */{ this._byId[instance.get('id')] = instance; if (options.at === undefined) { this.records.push(instance); + if (!options.silent) { + this.trigger('add', this, instance, this.records.length-1); + } } else { - this.records.splice(options.at + i, 0, instance); + var insertion_index = options.at + i; + this.records.splice(insertion_index, 0, instance); + if (!options.silent) { + this.trigger('add', this, instance, insertion_index); + } } this.length++; } From f4a745e3f779f9a1e18c8a17f10fc03d2b29722e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 22 Aug 2011 12:13:08 +0200 Subject: [PATCH 18/60] [FIX] forgot to increment index in resequencer bzr revid: xmo@openerp.com-20110822101308-2td5peezvg6snmk7 --- addons/base/static/src/js/list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index f35d5318cdc..d0ee0275c6b 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -1075,7 +1075,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas ui.item.parent().children().each(function (i, e) { // reset record-index accelerators on rows and even/odd var even = i%2 === 0; - $(e).data('index', i) + $(e).attr('data-index', i) .toggleClass('even', even) .toggleClass('odd', !even); }); @@ -1085,7 +1085,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas // if drag to 1st row (to = 0), start sequencing from 0 // (exclusive lower bound) seq = to ? list.records.at(to - 1).get('sequence') : 0; - while (++seq, record = list.records.at(index)) { + while (++seq, record = list.records.at(index++)) { // write are independent from one another, so we can just // launch them all at the same time and we don't really // give a fig about when they're done From 63d2dcce401521e5cb9a696026f1530579e287bc Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 22 Aug 2011 12:50:28 +0200 Subject: [PATCH 19/60] [IMP] unify refreshing rows striping (and @data-index resetting) bzr revid: xmo@openerp.com-20110822105028-vvzty9jx6nlupq0f --- addons/base/static/src/js/list.js | 51 +++++++++++++++++-------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index d0ee0275c6b..689c65b492f 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -631,12 +631,11 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. this.record_callbacks = { 'remove': function (event, record) { - var $row = self.$current.find('[data-id=' + record.get('id') + ']'); + var $row = self.$current.find( + '[data-id=' + record.get('id') + ']'); var index = $row.data('index'); - $row.nextAll().each(function (row) { - $(row).data('index', index++); - }); $row.remove(); + self.refresh_zebra(index); }, 'reset': $.proxy(this, 'on_records_reset'), 'change': function (event, record) { @@ -644,18 +643,10 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. $row.replaceWith(self.render_record($row.data('index'))); }, 'add': function (ev, records, record, index) { - var $row = $('').attr({ - 'data-id': record.get('id'), - 'data-index': index - }); - if (index === 0) { - $row.prependTo(self.$current); - } else { - $row.insertAfter(self.$current.children().eq(index)); - } - $row.nextAll().each(function (row) { - $(row).data('index', ++index); - }); + $('').attr({ + 'data-id': record.get('id') + }).insertAfter(self.$current.children(':eq(' + index + ')')); + self.refresh_zebra(index, 1); } }; _(this.record_callbacks).each(function (callback, event) { @@ -802,6 +793,26 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base. row_index: record_index, render_cell: openerp.base.format_cell }); + }, + /** + * Fixes @data-index on all table rows, and fixes the even/odd classes + * + * @param {Number} [from_index] index from which to resequence + * @param {Number} [offset = 0] selection offset for DOM, in case there are rows to ignore in the table + */ + refresh_zebra: function (from_index, offset) { + offset = offset || 0; + from_index = from_index || 0; + var dom_offset = offset + from_index; + var sel = dom_offset ? ':gt(' + (dom_offset - 1) + ')' : null; + this.$current.children(sel).each(function (i, e) { + var index = from_index + i; + // reset record-index accelerators on rows and even/odd + var even = index%2 === 0; + $(e).attr('data-index', index) + .toggleClass('even', even) + .toggleClass('odd', !even); + }); } }); openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.base.ListView.Groups# */{ @@ -1072,13 +1083,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas list.records.remove(to_move); list.records.add(to_move, {at: to}); - ui.item.parent().children().each(function (i, e) { - // reset record-index accelerators on rows and even/odd - var even = i%2 === 0; - $(e).attr('data-index', i) - .toggleClass('even', even) - .toggleClass('odd', !even); - }); + list.refresh_zebra(); // resequencing time! var record, index = to, From 6ccc41fe2bba7c485955e9ea9a3a470cfc6edff4 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 22 Aug 2011 12:56:56 +0200 Subject: [PATCH 20/60] [FIX] insertion at end: 'null' index should be same as 'undefined' for 'at' kwarg to Collection.add bzr revid: xmo@openerp.com-20110822105656-f0x1iweoxbh8hcgu --- addons/base/static/src/js/list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 689c65b492f..c6e50de85ec 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -1315,7 +1315,7 @@ var Collection = openerp.base.Class.extend(/** @lends Collection# */{ var instance = (records[i] instanceof Record) ? records[i] : new Record(records[i]); instance.bind(null, this._onRecordEvent); this._byId[instance.get('id')] = instance; - if (options.at === undefined) { + if (options.at == undefined) { this.records.push(instance); if (!options.silent) { this.trigger('add', this, instance, this.records.length-1); From c76bb492f20f00de2a05b10f7b1c30b1dca57c49 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 22 Aug 2011 13:10:01 +0200 Subject: [PATCH 21/60] [FIX] row edition bzr revid: xmo@openerp.com-20110822111001-mnyyvfund3b3j9bm --- addons/base/static/src/js/list-editable.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/base/static/src/js/list-editable.js b/addons/base/static/src/js/list-editable.js index 744f3c9a09b..a8a4e9d78c6 100644 --- a/addons/base/static/src/js/list-editable.js +++ b/addons/base/static/src/js/list-editable.js @@ -142,6 +142,8 @@ openerp.base.list.editable = function (openerp) { this.cancel_pending_edition().then(function () { var $new_row = $('', { id: _.uniqueId('oe-editable-row-'), + 'data-id': $(row).data('id'), + 'data-index': $(row).data('index'), 'class': $(row).attr('class') + ' oe_forms', click: function (e) {e.stopPropagation();} }) @@ -238,9 +240,7 @@ openerp.base.list.editable = function (openerp) { */ edit_record: function () { this.render_row_as_form( - this.$current.children( - _.sprintf('[data-index=%d]', - this.dataset.index))); + this.$current.children(':eq(' + this.dataset.index + ')')); $(this).trigger( 'edit', [this.records.at(this.dataset.index).get('id'), this.dataset]); From 26b7801355cf0879edb32ac143c82af1e26fb08e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 22 Aug 2011 15:12:48 +0200 Subject: [PATCH 22/60] [IMP] keep query parameters around (at least debug) when clicking on logo or redirecting from HTTP root to 'correct' root URL bzr revid: xmo@openerp.com-20110822131248-tl9j6flsw38r7p9e --- addons/base/static/src/js/chrome.js | 5 +++++ addons/base/static/src/xml/base.xml | 2 +- openerpweb/openerpweb.py | 7 ++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/addons/base/static/src/js/chrome.js b/addons/base/static/src/js/chrome.js index 665efa0e3e3..3a8af0a754c 100644 --- a/addons/base/static/src/js/chrome.js +++ b/addons/base/static/src/js/chrome.js @@ -566,6 +566,11 @@ openerp.base.Login = openerp.base.Widget.extend({ openerp.base.Header = openerp.base.Widget.extend({ init: function(parent, element_id) { this._super(parent, element_id); + if (jQuery.deparam(jQuery.param.querystring()).debug !== undefined) { + this.qs = '?debug' + } else { + this.qs = '' + } }, start: function() { return this.do_update(); diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index c4396793f95..343e7a1a7c1 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -326,7 +326,7 @@ - + + + +
    + + + + + + + + + +
    +
    Field
    +
    +
    +
    + + + + +
    +
    +
    + Translate view +
    +
    + Translate sidebar +
    +

    +
    @@ -734,11 +770,13 @@
    - + Date: Wed, 24 Aug 2011 17:57:23 +0200 Subject: [PATCH 35/60] [IMP] res_company/res_user: removed unused methods _get_child_ids/company_get. bzr revid: vmt@openerp.com-20110824155723-6wk2v8rb1gekbavv --- openerp/addons/base/res/res_company.py | 5 ----- openerp/addons/base/res/res_user.py | 5 ----- 2 files changed, 10 deletions(-) diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py index b0ebeb8ac27..fc63ac42dd9 100644 --- a/openerp/addons/base/res/res_company.py +++ b/openerp/addons/base/res/res_company.py @@ -189,11 +189,6 @@ class res_company(osv.osv): return rule.company_dest_id.id return user.company_id.id - def _get_child_ids(self, cr, uid, uid2, context={}): - company = self.pool.get('res.users').company_get(cr, uid, uid2) - ids = self._get_company_children(cr, uid, company) - return ids - @tools.cache() def _get_company_children(self, cr, uid=None, company=None): if not company: diff --git a/openerp/addons/base/res/res_user.py b/openerp/addons/base/res/res_user.py index a2bf9721e42..09360996396 100644 --- a/openerp/addons/base/res/res_user.py +++ b/openerp/addons/base/res/res_user.py @@ -346,10 +346,6 @@ class users(osv.osv): 'menu_tips':True } - @tools.cache() - def company_get(self, cr, uid, uid2, context=None): - return self._get_company(cr, uid, context=context, uid2=uid2) - # User can write to a few of her own fields (but not her groups for example) SELF_WRITEABLE_FIELDS = ['menu_tips','view', 'password', 'signature', 'action_id', 'company_id', 'user_email'] @@ -369,7 +365,6 @@ class users(osv.osv): res = super(users, self).write(cr, uid, ids, values, context=context) # clear caches linked to the users - self.company_get.clear_cache(cr.dbname) self.pool.get('ir.model.access').call_cache_clearing_methods(cr) clear = partial(self.pool.get('ir.rule').clear_cache, cr) map(clear, ids) From de955d098388688206f10c4858b178ad054acd88 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 25 Aug 2011 10:18:33 +0200 Subject: [PATCH 36/60] [REV] xmo@openerp.com-20110824131606-yokgoe3dz9ltaz2l, has nothing to do with the issue and does not actually fix it (just fudges some timing so it happens slightly less often) bzr revid: xmo@openerp.com-20110825081833-a1vbcdm59mrzf2d0 --- addons/base/static/src/js/list.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 47c04537ddc..9797b5dff99 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -120,7 +120,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi */ start: function() { this.$element.addClass('oe-listview'); - return this.reload_view(); + return this.reload_view(null, null, true); }, /** * Called after loading the list view's description, sets up such things @@ -362,22 +362,22 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi * @param {Boolean} [grouped] Should the list be displayed grouped * @param {Object} [context] context to send the server while loading the view */ - reload_view: function (grouped, context) { - var self = this, d = $.Deferred(); - d.then(function (field_view_get) { + reload_view: function (grouped, context, initial) { + var self = this; + var callback = function (field_view_get) { + console.log('loaded', initial ? 'initial' : 'subsequent'); self.on_loaded(field_view_get, grouped); - }); + }; if (this.embedded_view) { - d.resolve({fields_view: this.embedded_view}); + return $.Deferred().then(callback).resolve({fields_view: this.embedded_view}); } else { - this.rpc('/base/listview/load', { + return this.rpc('/base/listview/load', { model: this.model, view_id: this.view_id, context: this.dataset.get_context(context), toolbar: this.options.sidebar - }, function () { d.resolve.apply(this, arguments); }); + }, callback); } - return d.promise(); }, /** * re-renders the content of the list view From d2da68ad8b66e2c93c4552cb47bde7a34378c635 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 25 Aug 2011 10:22:21 +0200 Subject: [PATCH 37/60] [FIX] actually fix race condition on listview init: incorrect on_mode_switch override in xmo@openerp.com-20110816123510-gcx0dk8b2sgox5oi did not propagate primise from ViewManager's on_mode_switch bzr revid: xmo@openerp.com-20110825082221-tasmo3je0wu4iw6h --- addons/base/static/src/js/views.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js index c6782150297..7f6d78d9495 100644 --- a/addons/base/static/src/js/views.js +++ b/addons/base/static/src/js/views.js @@ -325,8 +325,9 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ } }, on_mode_switch: function (view_type) { - this._super(view_type); - this.shortcut_check(this.views[view_type]); + return $.when( + this._super(view_type), + this.shortcut_check(this.views[view_type])); }, shortcut_check : function(view) { var self = this; From 6e7a9a1a3c7e00e7aa24fcfb37b22c815e0c257c Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 25 Aug 2011 11:42:12 +0200 Subject: [PATCH 38/60] [IMP] Form fields now uses niv's parse/format methods bzr revid: fme@openerp.com-20110825094212-31l90vq66riiabl4 --- addons/base/static/src/js/form.js | 94 ++++++------------------------- 1 file changed, 17 insertions(+), 77 deletions(-) diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index 7a4d3c92d89..3280b7e0d81 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -949,7 +949,7 @@ openerp.base.form.FieldChar = openerp.base.form.Field.extend({ }, set_value: function(value) { this._super.apply(this, arguments); - var show_value = (value != null && value !== false) ? value : ''; + var show_value = openerp.base.format_value(value, this, ''); this.$element.find('input').val(show_value); }, update_dom: function() { @@ -957,16 +957,16 @@ openerp.base.form.FieldChar = openerp.base.form.Field.extend({ this.$element.find('input').attr('disabled', this.readonly); }, set_value_from_ui: function() { - this.value = this.$element.find('input').val(); + this.value = openerp.base.parse_value(this.$element.find('input').val(), this); this._super(); }, validate: function() { this.invalid = false; - var value = this.$element.find('input').val(); - if (value === "") { - this.invalid = this.required; - } else if (this.validation_regex) { - this.invalid = !this.validation_regex.test(value); + try { + var value = openerp.base.parse_value(this.$element.find('input').val(), this, ''); + this.invalid = this.required && value === ''; + } catch(e) { + this.invalid = true; } }, focus: function() { @@ -978,7 +978,6 @@ openerp.base.form.FieldEmail = openerp.base.form.FieldChar.extend({ init: function(view, node) { this._super(view, node); this.template = "FieldEmail"; - this.validation_regex = /@/; }, start: function() { this._super.apply(this, arguments); @@ -993,8 +992,7 @@ openerp.base.form.FieldEmail = openerp.base.form.FieldChar.extend({ }, set_value: function(value) { this._super.apply(this, arguments); - var show_value = (value != null && value !== false) ? value : ''; - this.$element.find('a').attr('href', 'mailto:' + show_value); + this.$element.find('a').attr('href', 'mailto:' + this.$element.find('input').val()); } }); @@ -1017,44 +1015,13 @@ openerp.base.form.FieldUrl = openerp.base.form.FieldChar.extend({ }); openerp.base.form.FieldFloat = openerp.base.form.FieldChar.extend({ - init: function(view, node) { - this._super(view, node); - this.validation_regex = /^-?\d+(\.\d+)?$/; - }, set_value: function(value) { - this._super.apply(this, [value]); if (value === false || value === undefined) { // As in GTK client, floats default to 0 value = 0; this.dirty = true; } - var show_value = value.toFixed(2); - this.$element.find('input').val(show_value); - }, - set_value_from_ui: function() { - this.value = Number(this.$element.find('input').val().replace(/,/g, '.')); - this._super(); - } -}); - -openerp.base.form.FieldInteger = openerp.base.form.FieldFloat.extend({ - init: function(view, node) { - this._super(view, node); - this.validation_regex = /^-?\d+$/; - }, - set_value: function(value) { this._super.apply(this, [value]); - if (value === false || value === undefined) { - // TODO fme: check if GTK client default integers to 0 (like it does with floats) - value = 0; - this.dirty = true; - } - var show_value = parseInt(value, 10); - this.$element.find('input').val(show_value); - }, - set_value_from_ui: function() { - this.value = Number(this.$element.find('input').val()); - this._super(); } }); @@ -1063,7 +1030,6 @@ openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({ this._super(view, node); this.template = "FieldDate"; this.jqueryui_object = 'datetimepicker'; - this.validation_regex = /^\d+-\d+-\d+( \d+:\d+(:\d+)?)?$/; }, start: function() { this._super.apply(this, arguments); @@ -1103,8 +1069,6 @@ openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({ var value = this.$element.find('input').val(); if (value === "") { this.invalid = this.required; - } else if (this.validation_regex) { - this.invalid = !this.validation_regex.test(value); } else { this.invalid = !this.$element.find('input')[this.jqueryui_object]('getDate'); } @@ -1120,39 +1084,15 @@ openerp.base.form.FieldDate = openerp.base.form.FieldDatetime.extend({ init: function(view, node) { this._super(view, node); this.jqueryui_object = 'datepicker'; - this.validation_regex = /^\d+-\d+-\d+$/; }, parse: openerp.base.str_to_date, format: openerp.base.date_to_str }); -openerp.base.form.FieldFloatTime = openerp.base.form.FieldChar.extend({ - init: function(view, node) { - this._super(view, node); - this.validation_regex = /^\d+:\d+$/; - }, - set_value: function(value) { - this._super.apply(this, [value]); - if (value === false || value === undefined) { - // As in GTK client, floats default to 0 - value = 0; - this.dirty = true; - } - var show_value = _.sprintf("%02d:%02d", Math.floor(value), Math.round((value % 1) * 60)); - this.$element.find('input').val(show_value); - }, - set_value_from_ui: function() { - var time = this.$element.find('input').val().split(':'); - this.set_value(parseInt(time[0], 10) + parseInt(time[1], 10) / 60); - this._super(); - } -}); - openerp.base.form.FieldText = openerp.base.form.Field.extend({ init: function(view, node) { this._super(view, node); this.template = "FieldText"; - this.validation_regex = null; }, start: function() { this._super.apply(this, arguments); @@ -1160,7 +1100,7 @@ openerp.base.form.FieldText = openerp.base.form.Field.extend({ }, set_value: function(value) { this._super.apply(this, arguments); - var show_value = (value != null && value !== false) ? value : ''; + var show_value = openerp.base.format_value(value, this, ''); this.$element.find('textarea').val(show_value); }, update_dom: function() { @@ -1168,16 +1108,16 @@ openerp.base.form.FieldText = openerp.base.form.Field.extend({ this.$element.find('textarea').attr('disabled', this.readonly); }, set_value_from_ui: function() { - this.value = this.$element.find('textarea').val(); + this.value = openerp.base.parse_value(this.$element.find('textarea').val(), this); this._super(); }, validate: function() { this.invalid = false; - var value = this.$element.find('textarea').val(); - if (value === "") { - this.invalid = this.required; - } else if (this.validation_regex) { - this.invalid = !this.validation_regex.test(value); + try { + var value = openerp.base.parse_value(this.$element.find('textarea').val(), this, ''); + this.invalid = this.required && value === ''; + } catch(e) { + this.invalid = true; } }, focus: function() { @@ -2440,9 +2380,9 @@ openerp.base.form.widgets = new openerp.base.Registry({ 'reference' : 'openerp.base.form.FieldReference', 'boolean' : 'openerp.base.form.FieldBoolean', 'float' : 'openerp.base.form.FieldFloat', - 'integer': 'openerp.base.form.FieldInteger', + 'integer': 'openerp.base.form.FieldFloat', + 'float_time': 'openerp.base.form.FieldFloat', 'progressbar': 'openerp.base.form.FieldProgressBar', - 'float_time': 'openerp.base.form.FieldFloatTime', 'image': 'openerp.base.form.FieldBinaryImage', 'binary': 'openerp.base.form.FieldBinaryFile' }); From 3da1145220c86e8e2b52c883ce34078fa4fde2a6 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 25 Aug 2011 11:48:06 +0200 Subject: [PATCH 39/60] [IMP] Improved form's datetime widget so the content is always visible even when view size is shrinked down bzr revid: fme@openerp.com-20110825094806-hfiagqp54gf9rzha --- addons/base/static/src/css/base.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/base/static/src/css/base.css b/addons/base/static/src/css/base.css index cd420ea8c0d..46364c4fa1d 100644 --- a/addons/base/static/src/css/base.css +++ b/addons/base/static/src/css/base.css @@ -870,6 +870,9 @@ label.error { .openerp .oe_forms input[type="text"], .openerp .oe_forms input[type="password"], .openerp .oe_forms select, .openerp .oe_forms .button { height: 22px; } +.openerp .oe_forms input.field_datetime { + min-width: 11em; +} .openerp .oe_forms .button { color: #4c4c4c; white-space: nowrap; From 455928127fa2ed44a6f7fda14cab57052031c89f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 25 Aug 2011 12:06:43 +0200 Subject: [PATCH 40/60] [FIX] safari/javascriptcore blows up on 'super' because it thinks it's a keyword bzr revid: xmo@openerp.com-20110825100643-k7nbcla8h38siozr --- addons/base/static/src/js/views.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js index 7f6d78d9495..9e981e7c3e2 100644 --- a/addons/base/static/src/js/views.js +++ b/addons/base/static/src/js/views.js @@ -531,17 +531,17 @@ openerp.base.TranslateDialog = openerp.base.Dialog.extend({ }, open: function(field) { var self = this, - super = this._super; + sup = this._super; $.when(this.languages_loaded).then(function() { if (self.view.translatable_fields && self.view.translatable_fields.length) { self.do_load_fields_values(function() { - super.call(self); + sup.call(self); if (field) { // TODO: focus and scroll to field } }); } else { - super.call(self); + sup.call(self); } }); }, From 5864a23352e200eeab37b0b1e6b8c466e8261e5b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 25 Aug 2011 12:27:56 +0200 Subject: [PATCH 41/60] [REM] leftover debugging code bzr revid: xmo@openerp.com-20110825102756-b3d8jf7yud0m98ol --- addons/base/static/src/js/list.js | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 9797b5dff99..e83454deebb 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -365,7 +365,6 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi reload_view: function (grouped, context, initial) { var self = this; var callback = function (field_view_get) { - console.log('loaded', initial ? 'initial' : 'subsequent'); self.on_loaded(field_view_get, grouped); }; if (this.embedded_view) { From 259892f837588c7b47c81cfe513d245e4526226f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 25 Aug 2011 12:33:36 +0200 Subject: [PATCH 42/60] [FIX] selector for config overview widget: widget root has moved, .oe-dashboard-config-overview is now on this. so don't include it bzr revid: xmo@openerp.com-20110825103336-nwyybou1hghaudud --- addons/base_dashboard/static/src/js/dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/base_dashboard/static/src/js/dashboard.js b/addons/base_dashboard/static/src/js/dashboard.js index 8cf94a43362..e5b06a13461 100644 --- a/addons/base_dashboard/static/src/js/dashboard.js +++ b/addons/base_dashboard/static/src/js/dashboard.js @@ -321,7 +321,7 @@ openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({ $progress.progressbar({value: $progress.data('completion')}); var self = this; - this.$element.find('div.oe-dashboard-config-overview ul') + this.$element.find('dl') .delegate('input', 'click', function (e) { // switch todo status e.stopImmediatePropagation(); From a5bb1a265b2eb1c217742db34330f28aa0fb78e8 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 25 Aug 2011 14:10:51 +0200 Subject: [PATCH 43/60] [fix] small bug with dates localization bzr revid: nicolas.vanhoren@openerp.com-20110825121051-x86pjeyfnnb65ucr --- addons/base/static/src/js/core.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/base/static/src/js/core.js b/addons/base/static/src/js/core.js index fca993ffef9..57b3a8cb637 100644 --- a/addons/base/static/src/js/core.js +++ b/addons/base/static/src/js/core.js @@ -567,8 +567,8 @@ openerp.base.Session = openerp.base.CallbackEnabled.extend( /** @lends openerp.b self.do_load_js(file_list.concat(files)); }); } else { - self.do_load_css(file_list.concat(["/base/webclient/css?mods="+modules])); - self.do_load_js(["/base/webclient/js?mods="+modules]); + self.do_load_css(["/base/webclient/css?mods="+modules]); + self.do_load_js(file_list.concat(["/base/webclient/js?mods="+modules])); } openerp._modules_loaded = true; }); From 93aa853ae6c047d91e0958607fad73b1a4c5a271 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 25 Aug 2011 14:17:53 +0200 Subject: [PATCH 44/60] [imp] changed format/parse functions for dates to use date.js format instead of the openerp one bzr revid: nicolas.vanhoren@openerp.com-20110825121753-w3acs2fhbwm157a6 --- addons/base/static/src/js/formats.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/addons/base/static/src/js/formats.js b/addons/base/static/src/js/formats.js index c141aad908c..ed25b28c16d 100644 --- a/addons/base/static/src/js/formats.js +++ b/addons/base/static/src/js/formats.js @@ -45,8 +45,8 @@ openerp.base.format_value = function (value, descriptor, value_if_empty) { if (typeof(value) == "string") value = openerp.base.str_to_datetime(value); try { - return value.format(_.sprintf("%s %s", openerp.base._t.database.parameters.date_format, - openerp.base._t.database.parameters.time_format)); + return value.toString(_.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, + Date.CultureInfo.formatPatterns.longTime)); } catch (e) { return value.format("%m/%d/%Y %H:%M:%S"); } @@ -55,7 +55,7 @@ openerp.base.format_value = function (value, descriptor, value_if_empty) { if (typeof(value) == "string") value = openerp.base.str_to_date(value); try { - return value.format(openerp.base._t.database.parameters.date_format); + return value.toString(Date.CultureInfo.formatPatterns.shortDate); } catch (e) { return value.format("%m/%d/%Y"); } @@ -63,7 +63,7 @@ openerp.base.format_value = function (value, descriptor, value_if_empty) { if (typeof(value) == "string") value = openerp.base.str_to_time(value); try { - return value.format(openerp.base._t.database.parameters.time_format); + return value.toString(Date.CultureInfo.formatPatterns.longTime); } catch (e) { return value.format("%H:%M:%S"); } @@ -108,17 +108,27 @@ openerp.base.parse_value = function (value, descriptor, value_if_empty) { case 'progressbar': return openerp.base.parse_value(value, {type: "float"}); case 'datetime': - var tmp = Date.parse(value); + var tmp = Date.parseExact(value, _.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, + Date.CultureInfo.formatPatterns.longTime)); + if (tmp !== null) + return tmp; + tmp = Date.parse(value); if (tmp !== null) return tmp; throw value + " is not a valid datetime"; case 'date': - var tmp = Date.parse(value); + var tmp = Date.parseExact(Date.CultureInfo.formatPatterns.shortDate); + if (tmp !== null) + return tmp; + tmp = Date.parse(value); if (tmp !== null) return tmp; throw value + " is not a valid date"; case 'time': - var tmp = Date.parse(value); + var tmp = Date.parseExact(Date.CultureInfo.formatPatterns.longTime); + if (tmp !== null) + return tmp; + tmp = Date.parse(value); if (tmp !== null) return tmp; throw value + " is not a valid time"; From b5a429d008536f6410e82b24ee12ec481b6d6397 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 25 Aug 2011 14:30:49 +0200 Subject: [PATCH 45/60] [FIX] fnct_inv in client actions params, fix docstring for fnct_inv (fnct_inv only takes a single record id, not a sequence of ids) bzr revid: xmo@openerp.com-20110825123049-bmvebm86gqgr6w43 --- openerp/addons/base/ir/ir_actions.py | 5 ++--- openerp/osv/fields.py | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 0b60d389287..67c36b277dd 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -936,10 +936,9 @@ class act_client(osv.osv): for record in self.browse(cr, uid, ids, context=context) ]) - def _set_params(self, cr, uid, ids, field_name, field_value, arg, context): + def _set_params(self, cr, uid, id, field_name, field_value, arg, context): assert isinstance(field_value, dict), "params can only be dictionaries" - for record in self.browse(cr, uid, ids, context=context): - record.write({field_name: repr(field_value)}) + self.write(cr, uid, id, {'params_store': repr(field_value)}, context=context) _columns = { 'tag': fields.char('Client action tag', size=64, required=True, diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index 782cc8e796a..fb973d2e521 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -852,12 +852,13 @@ class function(_column): This callable implements the write operation for the function field and must have the following signature: - .. function:: fnct_inv(model, cr, uid, ids, field_name, field_value, fnct_inv_arg, context) + .. function:: fnct_inv(model, cr, uid, id, field_name, field_value, fnct_inv_arg, context) Callable that implements the ``write`` operation for the function field. :param orm_template model: model to which the field belongs (should be ``self`` for a model method) + :param int id: the identifier of the object to write on :param str field_name: name of the field to set :param fnct_inv_arg: arbitrary value passed when declaring the function field :return: True From b8cd28fb355de91b9ec736be4f42d77afef0a137 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 25 Aug 2011 14:34:45 +0200 Subject: [PATCH 46/60] [FIX] widgets client action handler: one action per widget bzr revid: xmo@openerp.com-20110825123445-ayhaeipasl4imvqt --- .../base_dashboard/static/src/js/dashboard.js | 61 +++++++++---------- .../static/src/xml/base_dashboard.xml | 9 ++- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/addons/base_dashboard/static/src/js/dashboard.js b/addons/base_dashboard/static/src/js/dashboard.js index e5b06a13461..3f9da51b157 100644 --- a/addons/base_dashboard/static/src/js/dashboard.js +++ b/addons/base_dashboard/static/src/js/dashboard.js @@ -372,39 +372,36 @@ openerp.base_dashboard.ApplicationTiles = openerp.base.View.extend({ } }); openerp.base.client_actions.add( - 'board.home.widgets', 'openerp.base_dashboard.Widgets'); -openerp.base_dashboard.Widgets = openerp.base.View.extend({ - template: 'HomeWidgets', - start: function () { - return new openerp.base.DataSetSearch( - this, 'res.widget.user', null, - ['|', ['user_id', '=', false], - ['user_id', '=', parseInt(this.session.uid, 10)]]) - .read_slice(['widget_id', 'user_id'], {}, this.on_widgets_list_loaded); + 'board.home.widgets', 'openerp.base_dashboard.Widget'); +openerp.base_dashboard.Widget = openerp.base.View.extend(/** @lends openerp.base_dashboard.Widgets# */{ + template: 'HomeWidget', + /** + * Initializes a "HomeWidget" client widget: handles the display of a given + * res.widget objects in an OpenERP view (mainly a dashboard). + * + * @constructs + * @extends openerp.base.View + * @param {Object} parent + * @param {Object} options + * @param {Number} options.widget_id + */ + init: function (parent, options) { + this._super(parent); + this.widget_id = options.widget_id; }, - on_widgets_list_loaded: function (user_widgets) { - var self = this; - var widget_user = {}; - _(user_widgets).each(function (widget) { - widget['widget_id'] = widget['widget_id'][0]; - widget_user[widget['widget_id']] = { - removable: widget['user_id'] !== false, - user_widget_id: widget['id'] - }; - }); - new openerp.base.DataSetSearch(this, 'res.widget') - .read_ids(_(user_widgets).pluck('widget_id'), ['title'], function (widgets) { - _(widgets).each(function (widget) { - _.extend(widget, widget_user[widget['id']]); - }); - var url = _.sprintf( - '/base_dashboard/widgets/content?session_id=%s&widget_id=', - self.session.session_id); - self.$element.html(QWeb.render('HomeWidgets', { - widgets: widgets, - url: url - })); - }); + start: function () { + return new openerp.base.DataSet(this, 'res.widget').read_ids( + [this.widget_id], ['title'], this.on_widget_loaded); + }, + on_widget_loaded: function (widgets) { + var widget = widgets[0]; + var url = _.sprintf( + '/base_dashboard/widgets/content?session_id=%s&widget_id=%d', + this.session.session_id, widget.id); + this.$element.html(QWeb.render('HomeWidget.content', { + widget: widget, + url: url + })); } }); }; diff --git a/addons/base_dashboard/static/src/xml/base_dashboard.xml b/addons/base_dashboard/static/src/xml/base_dashboard.xml index 51657dfd068..b60e466964b 100644 --- a/addons/base_dashboard/static/src/xml/base_dashboard.xml +++ b/addons/base_dashboard/static/src/xml/base_dashboard.xml @@ -107,10 +107,9 @@ -
    -
    +
    +

    -