diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 850069bb141..45c500df7c9 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import base64 import glob, os -import pprint from xml.etree import ElementTree from cStringIO import StringIO @@ -392,9 +391,10 @@ class DataSet(openerpweb.Controller): req.session.eval_context(req.context))} @openerpweb.jsonrequest - def search_read(self, request, model, fields=False, offset=0, limit=False, domain=None, context=None, sort=None): - return self.do_search_read(request, model, fields, offset, limit, domain, context, sort) - def do_search_read(self, request, model, fields=False, offset=0, limit=False, domain=None, context=None, sort=None): + def search_read(self, request, model, fields=False, offset=0, limit=False, domain=None, sort=None): + return self.do_search_read(request, model, fields, offset, limit, domain, sort) + def do_search_read(self, request, model, fields=False, offset=0, limit=False, domain=None + , sort=None): """ Performs a search() followed by a read() (if needed) using the provided search criteria @@ -407,22 +407,33 @@ class DataSet(openerpweb.Controller): :param int limit: the maximum number of records to return :param list domain: the search domain for the query :param list sort: sorting directives - :returns: a list of result records + :returns: A structure (dict) with two keys: ids (all the ids matching + the (domain, context) pair) and records (paginated records + matching fields selection set) :rtype: list """ Model = request.session.model(model) - context, domain = eval_context_and_domain(request.session, request.context, domain) - - ids = Model.search(domain, offset or 0, limit or False, - sort or False, context) + context, domain = eval_context_and_domain( + request.session, request.context, domain) + ids = Model.search(domain, 0, False, sort or False, context) + # need to fill the dataset with all ids for the (domain, context) pair, + # so search un-paginated and paginate manually before reading + paginated_ids = ids[offset:(offset + limit if limit else None)] if fields and fields == ['id']: # shortcut read if we only want the ids - return map(lambda id: {'id': id}, ids) + return { + 'ids': ids, + 'records': map(lambda id: {'id': id}, paginated_ids) + } + + records = Model.read(paginated_ids, fields or False, context) + records.sort(key=lambda obj: ids.index(obj['id'])) + return { + 'ids': ids, + 'records': records + } - reads = Model.read(ids, fields or False, context) - reads.sort(key=lambda obj: ids.index(obj['id'])) - return reads @openerpweb.jsonrequest def get(self, request, model, ids, fields=False): diff --git a/addons/base/static/src/css/base.css b/addons/base/static/src/css/base.css index 32a335d7eb8..e91bbd922ec 100644 --- a/addons/base/static/src/css/base.css +++ b/addons/base/static/src/css/base.css @@ -606,6 +606,9 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%, vertical-align: middle; text-align: left; } +.openerp .oe-listview td.oe-record-delete { + text-align: right; +} .openerp .oe-listview th.oe-sortable, .openerp .oe-listview th.oe-sortable .ui-icon { cursor: pointer; @@ -636,6 +639,17 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%, .openerp .oe-listview th.oe-list-pager { text-align: right; } +.openerp .oe-list-pager .oe-pager-state { + cursor: pointer; +} + +.openerp .oe-listview .oe-group-name { + padding-right: 1em; +} +.openerp .oe-listview .oe-group-name, +.openerp .oe-listview .oe-group-pagination { + white-space: nowrap; +} .openerp .oe-listview tfoot td { padding: 3px 3px 0; diff --git a/addons/base/static/src/js/data.js b/addons/base/static/src/js/data.js index 5fc43689709..1eb9c0f0a0d 100644 --- a/addons/base/static/src/js/data.js +++ b/addons/base/static/src/js/data.js @@ -196,7 +196,9 @@ openerp.base.GrouplessDataGroup = openerp.base.DataGroup.extend( this._super(session, model, domain, context, null, level); }, list: function (ifGroups, ifRecords) { - ifRecords(new openerp.base.DataSetSearch(this.session, this.model, this.context, this.domain)); + ifRecords(_.extend( + new openerp.base.DataSetSearch(this.session, this.model), + {domain: this.domain, context: this.context})); } }); @@ -421,13 +423,10 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({ sort: this.sort(), offset: offset, limit: limit - }, function (records) { - self.ids.splice(0, self.ids.length); + }, function (result) { + self.ids = result.ids; self.offset = offset; - for (var i=0; i < records.length; i++ ) { - self.ids.push(records[i].id); - } - callback(records); + callback(result.records); }); }, /** diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index 874ff247a6f..0c2ec73af81 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -166,7 +166,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV this.ready = false; var onchange = _.trim(widget.node.attrs.on_change); var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/); - console.log("Onchange triggered for field '%s' -> %s", widget.name, onchange); if (call) { var method = call[1], args = []; var context_index = null; @@ -226,14 +225,12 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV on_processed_onchange: function(response, processed) { var result = response.result; if (result.value) { - console.log(" |-> Onchange Response :", result.value); for (var f in result.value) { var field = this.fields[f]; if (field) { var value = result.value[f]; processed.push(field.name); if (field.get_value() != value) { - console.log(" |-> Onchange Action : change '%s' value from '%s' to '%s'", field.name, field.get_value(), value); field.set_value(value); field.touched = true; if (_.indexOf(processed, field.name) < 0) { @@ -242,12 +239,11 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV } } else { // this is a common case, the normal behavior should be to ignore it - console.debug("on_processed_onchange can't find field " + f, result); } } this.on_form_changed(); } - if (result.warning && !_.isEmpty(result.warning)) { + if (!_.isEmpty(result.warning)) { $(QWeb.render("DialogWarning", result.warning)).dialog({ modal: true, buttons: { @@ -396,12 +392,13 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV this.on_attachments_loaded([]); } else { // TODO fme: modify this so it doesn't try to load attachments when there is not sidebar - /*this.rpc('/base/dataset/search_read', { - model: 'ir.attachment', - fields: ['name', 'url', 'type'], - domain: [['res_model', '=', this.dataset.model], ['res_id', '=', this.datarecord.id], ['type', 'in', ['binary', 'url']]], - context: this.dataset.get_context() - }, this.on_attachments_loaded);*/ + /*(new openerp.base.DataSetSearch( + this.session, 'ir.attachment', this.dataset.get_context(), + [['res_model', '=', this.dataset.model], + ['res_id', '=', this.datarecord.id], + ['type', 'in', ['binary', 'url']]])).read_slice( + ['name', 'url', 'type'], false, false, + this.on_attachments_loaded);*/ } }, on_attachments_loaded: function(attachments) { diff --git a/addons/base/static/src/js/list-editable.js b/addons/base/static/src/js/list-editable.js index b97a35d0612..8b4b16faf04 100644 --- a/addons/base/static/src/js/list-editable.js +++ b/addons/base/static/src/js/list-editable.js @@ -116,6 +116,23 @@ openerp.base.list.editable = function (openerp) { delete this.edition_index; delete this.edition; }, + /** + * Adapts this list's view description to be suitable to the inner form view of a row being edited. + * + * @returns {Object} fields_view_get's view section suitable for putting into form view of editable rows. + */ + get_form_fields_view: function () { + // deep copy of view + var view = $.extend(true, {}, this.group.view.fields_view); + _(view.arch.children).each(function (widget) { + widget.attrs.nolabel = true; + if (widget.tag === 'button') { + delete widget.attrs.string; + } + }); + view.arch.attrs.col = 2 * view.arch.children.length; + return view; + }, render_row_as_form: function (row) { this.cancel_pending_edition(); @@ -161,7 +178,7 @@ openerp.base.list.editable = function (openerp) { template: 'ListView.row.form', registry: openerp.base.list.form.widgets }); - $.when(this.edition_form.on_loaded({fields_view: this.get_fields_view()})).then(function () { + $.when(this.edition_form.on_loaded({fields_view: this.get_form_fields_view()})).then(function () { // put in $.when just in case FormView.on_loaded becomes asynchronous $new_row.find('td') .addClass('oe-field-cell') diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 9c68e4f9b78..aa3fe3f658b 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -59,6 +59,24 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi if (this.dataset instanceof openerp.base.DataSetStatic) { this.groups.datagroup = new openerp.base.StaticDataGroup(this.dataset); } + + this.page = 0; + }, + /** + * Retrieves the view's number of records per page (|| section) + * + * options > defaults > view_manager.action.limit > indefinite + * + * @returns {Number|null} + */ + limit: function () { + if (this._limit === undefined) { + this._limit = (this.options.limit + || this.defaults.limit + || (this.view_manager.action || {}).limit + || null); + } + return this._limit; }, /** * Set a custom Group construct as the root of the List View. @@ -134,10 +152,10 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi this.$element.html(QWeb.render("ListView", this)); // Head hook - this.$element.find('#oe-list-add') + this.$element.find('.oe-list-add') .click(this.do_add_record) .attr('disabled', grouped && this.options.editable); - this.$element.find('#oe-list-delete') + this.$element.find('.oe-list-delete') .attr('disabled', true) .click(this.do_delete_selected); this.$element.find('thead').delegate('th[data-id]', 'click', function (e) { @@ -149,8 +167,75 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi self.reload_view(); }); + this.$element.find('.oe-list-pager') + .delegate('button', 'click', function () { + var $this = $(this); + switch ($this.data('pager-action')) { + case 'first': + self.page = 0; break; + case 'last': + self.page = Math.floor( + self.dataset.ids.length / self.limit()); + break; + case 'next': + self.page += 1; break; + case 'previous': + self.page -= 1; break; + } + self.reload_content(); + }).find('.oe-pager-state') + .click(function (e) { + e.stopPropagation(); + var $this = $(this); + + var $select = $('