[MERGE] from trunk, in order to get some dataset & groupby fixes
bzr revid: xmo@openerp.com-20110706142536-dwxuq2v10u660703
This commit is contained in:
commit
f7a47fe58c
|
@ -1,7 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import base64
|
||||
import glob, os
|
||||
import pprint
|
||||
from xml.etree import ElementTree
|
||||
from cStringIO import StringIO
|
||||
|
||||
|
@ -397,9 +396,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
|
||||
|
||||
|
@ -412,22 +412,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):
|
||||
|
|
|
@ -607,6 +607,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;
|
||||
|
@ -637,6 +640,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;
|
||||
|
|
|
@ -355,15 +355,12 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
|||
* @param {Object} params call parameters
|
||||
* @param {Function} success_callback function to execute on RPC call success
|
||||
* @param {Function} error_callback function to execute on RPC call failure
|
||||
* one
|
||||
* @returns {jQuery.Deferred} jquery-provided ajax deferred
|
||||
*/
|
||||
rpc: function(url, params, success_callback, error_callback) {
|
||||
var self = this;
|
||||
// Construct a JSON-RPC2 request, method is currently unused
|
||||
params.session_id = this.session_id;
|
||||
// niv: wtf?
|
||||
//params.context = typeof(params.context) != "undefined" ? params.context : this.context;
|
||||
|
||||
// Call using the rpc_mode
|
||||
var deferred = $.Deferred();
|
||||
|
@ -919,18 +916,15 @@ openerp.base.Database = openerp.base.Controller.extend({
|
|||
});
|
||||
|
||||
openerp.base.Login = openerp.base.Controller.extend({
|
||||
remember_creditentials: true,
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
this.has_local_storage = typeof(localStorage) != 'undefined';
|
||||
this.selected_db = null;
|
||||
this.selected_login = null;
|
||||
this.selected_password = null;
|
||||
this.remember = false;
|
||||
if (this.has_local_storage && localStorage.getItem('remember_creditentials') === 'true') {
|
||||
this.remember = true;
|
||||
if (this.has_local_storage && this.remember_creditentials) {
|
||||
this.selected_db = localStorage.getItem('last_db_login_success');
|
||||
this.selected_login = localStorage.getItem('last_login_login_success');
|
||||
this.selected_password = localStorage.getItem('last_password_login_success');
|
||||
}
|
||||
},
|
||||
start: function() {
|
||||
|
@ -959,22 +953,17 @@ openerp.base.Login = openerp.base.Controller.extend({
|
|||
var db = $e.find("form [name=db]").val();
|
||||
var login = $e.find("form input[name=login]").val();
|
||||
var password = $e.find("form input[name=password]").val();
|
||||
var remember = $e.find("form input[name=remember]").attr('checked');
|
||||
//$e.hide();
|
||||
// Should hide then call callback
|
||||
this.session.session_login(db, login, password, function() {
|
||||
if(self.session.session_is_valid()) {
|
||||
if (self.has_local_storage) {
|
||||
if(remember) {
|
||||
localStorage.setItem('remember_creditentials', 'true');
|
||||
if(self.remember_creditentials) {
|
||||
localStorage.setItem('last_db_login_success', db);
|
||||
localStorage.setItem('last_login_login_success', login);
|
||||
localStorage.setItem('last_password_login_success', password);
|
||||
} else {
|
||||
localStorage.setItem('remember_creditentials', '');
|
||||
localStorage.setItem('last_db_login_success', '');
|
||||
localStorage.setItem('last_login_login_success', '');
|
||||
localStorage.setItem('last_password_login_success', '');
|
||||
}
|
||||
}
|
||||
self.on_login_valid();
|
||||
|
|
|
@ -135,7 +135,7 @@ openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend(
|
|||
domain: this.domain,
|
||||
group_by_fields: this.group_by
|
||||
}, function () { }).then(function (response) {
|
||||
var data_groups = _(response.result).map(
|
||||
var data_groups = _(response).map(
|
||||
_.bind(self.transform_group, self));
|
||||
self.groups = data_groups;
|
||||
d.resolveWith(self, [data_groups]);
|
||||
|
@ -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}));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -429,13 +431,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);
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
@ -491,7 +490,6 @@ openerp.base.BufferedDataSet = openerp.base.DataSetStatic.extend({
|
|||
var cached = {id:_.uniqueId(this.virtual_id_prefix), values: data};
|
||||
this.to_create.push(cached);
|
||||
this.cache.push(cached);
|
||||
this.on_change();
|
||||
var to_return = $.Deferred().then(callback);
|
||||
setTimeout(function() {to_return.resolve({result: cached.id});}, 0);
|
||||
return to_return.promise();
|
||||
|
|
|
@ -166,20 +166,24 @@ 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;
|
||||
var argument_replacement = {
|
||||
'False' : false,
|
||||
'True' : true,
|
||||
'None' : null,
|
||||
'context': widget.build_context ? widget.build_context() : {}
|
||||
'False' : function() {return false;},
|
||||
'True' : function() {return true;},
|
||||
'None' : function() {return null;},
|
||||
'context': function(i) {
|
||||
context_index = i;
|
||||
var ctx = widget.build_context ? widget.build_context() : {};
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
var parent_fields = null;
|
||||
_.each(call[2].split(','), function(a) {
|
||||
_.each(call[2].split(','), function(a, i) {
|
||||
var field = _.trim(a);
|
||||
if (field in argument_replacement) {
|
||||
args.push(argument_replacement[field]);
|
||||
args.push(argument_replacement[field](i));
|
||||
return;
|
||||
} else if (self.fields[field]) {
|
||||
var value = self.fields[field].get_on_change_value();
|
||||
|
@ -193,7 +197,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
|||
}
|
||||
var p_val = parent_fields[_.trim(splitted[1])];
|
||||
if (p_val !== undefined) {
|
||||
args.push(value ? value : false);
|
||||
args.push(p_val == null ? false : p_val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +212,8 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
|||
return this.rpc(ajax, {
|
||||
model: this.dataset.model,
|
||||
method: method,
|
||||
args: [(this.datarecord.id == null ? [] : [this.datarecord.id])].concat(args)
|
||||
args: [(this.datarecord.id == null ? [] : [this.datarecord.id])].concat(args),
|
||||
context_id: context_index === null ? null : context_index + 1
|
||||
}, function(response) {
|
||||
self.on_processed_onchange(response, processed);
|
||||
});
|
||||
|
@ -220,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) {
|
||||
|
@ -236,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
|
||||
this.log("on_processed_onchange can't find field " + f, result);
|
||||
}
|
||||
}
|
||||
this.on_form_changed();
|
||||
}
|
||||
if (result.warning) {
|
||||
if (!_.isEmpty(result.warning)) {
|
||||
$(QWeb.render("DialogWarning", result.warning)).dialog({
|
||||
modal: true,
|
||||
buttons: {
|
||||
|
@ -390,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) {
|
||||
|
@ -437,7 +440,8 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
|||
get_fields_values: function() {
|
||||
var values = {};
|
||||
_.each(this.fields, function(value, key) {
|
||||
values[key] = value.get_value();
|
||||
var val = value.get_value();
|
||||
values[key] = val;
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
@ -928,7 +932,7 @@ openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({
|
|||
},
|
||||
set_value: function(value) {
|
||||
this._super.apply(this, arguments);
|
||||
if (value == null || value == false) {
|
||||
if (!value) {
|
||||
this.$element.find('input').val('');
|
||||
} else {
|
||||
this.$element.find('input').unbind('change');
|
||||
|
@ -1079,7 +1083,7 @@ openerp.base.form.FieldProgressBar = openerp.base.form.Field.extend({
|
|||
set_value: function(value) {
|
||||
this._super.apply(this, arguments);
|
||||
var show_value = Number(value);
|
||||
if (show_value === NaN) {
|
||||
if (isNaN(show_value)) {
|
||||
show_value = 0;
|
||||
}
|
||||
this.$element.find('div').progressbar('option', 'value', show_value).find('span').html(show_value + '%');
|
||||
|
@ -1298,7 +1302,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
|||
// create...
|
||||
values.push({label: "<em> Create and Edit...</em>", action: function() {
|
||||
self._change_int_value(null);
|
||||
self._search_create_popup("form");
|
||||
self._search_create_popup("form", undefined, {"default_name": search_val});
|
||||
}});
|
||||
|
||||
response(values);
|
||||
|
@ -1437,6 +1441,7 @@ var commands = {
|
|||
}
|
||||
};
|
||||
openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
multi_selection: false,
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.template = "FieldOne2Many";
|
||||
|
@ -1464,6 +1469,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
|||
}
|
||||
if(view.view_type === "list") {
|
||||
view.options = {
|
||||
'selectable': self.multi_selection
|
||||
};
|
||||
}
|
||||
views.push(view);
|
||||
|
@ -1585,26 +1591,31 @@ openerp.base.form.One2ManyDataSet = openerp.base.BufferedDataSet.extend({
|
|||
|
||||
openerp.base.form.One2ManyListView = openerp.base.ListView.extend({
|
||||
do_add_record: function () {
|
||||
var self = this;
|
||||
var pop = new openerp.base.form.SelectCreatePopup(null, self.o2m.view.session);
|
||||
pop.select_element(self.o2m.field.relation,{
|
||||
initial_view: "form",
|
||||
alternative_form_view: self.o2m.field.views ? self.o2m.field.views["form"] : undefined,
|
||||
auto_create: false,
|
||||
parent_view: self.o2m.view
|
||||
}, self.o2m.build_domain(), self.o2m.build_context());
|
||||
pop.on_create.add(function(data) {
|
||||
self.o2m.dataset.create(data, function(r) {
|
||||
self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r.result]));
|
||||
self.o2m.dataset.on_change();
|
||||
pop.stop();
|
||||
self.o2m.reload_current_view();
|
||||
if (this.options.editable) {
|
||||
this._super.apply(this, arguments);
|
||||
} else {
|
||||
var self = this;
|
||||
var pop = new openerp.base.form.SelectCreatePopup(null, self.o2m.view.session);
|
||||
pop.select_element(self.o2m.field.relation,{
|
||||
initial_view: "form",
|
||||
alternative_form_view: self.o2m.field.views ? self.o2m.field.views["form"] : undefined,
|
||||
auto_create: false,
|
||||
parent_view: self.o2m.view
|
||||
}, self.o2m.build_domain(), self.o2m.build_context());
|
||||
pop.on_create.add(function(data) {
|
||||
self.o2m.dataset.create(data, function(r) {
|
||||
self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r.result]));
|
||||
self.o2m.dataset.on_change();
|
||||
pop.stop();
|
||||
self.o2m.reload_current_view();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
||||
multi_selection: false,
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.template = "FieldMany2Many";
|
||||
|
@ -1625,7 +1636,8 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
|||
|
||||
this.list_view = new openerp.base.form.Many2ManyListView(
|
||||
null, this.view.session, this.list_id, this.dataset, false, {
|
||||
'addable': 'Add'
|
||||
'addable': 'Add',
|
||||
'selectable': self.multi_selection
|
||||
});
|
||||
this.list_view.m2m_field = this;
|
||||
this.list_view.on_loaded.add_last(function() {
|
||||
|
@ -1666,7 +1678,9 @@ openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
|||
do_add_record: function () {
|
||||
var pop = new openerp.base.form.SelectCreatePopup(
|
||||
null, this.m2m_field.view.session);
|
||||
pop.select_element(this.model, {}, this.m2m_field.build_domain(), this.m2m_field.build_context());
|
||||
pop.select_element(this.model, {},
|
||||
new openerp.base.CompoundDomain(this.m2m_field.build_domain(), ["!", ["id", "in", this.m2m_field.dataset.ids]]),
|
||||
this.m2m_field.build_context());
|
||||
var self = this;
|
||||
pop.on_select_elements.add(function(element_ids) {
|
||||
_.each(element_ids, function(element_id) {
|
||||
|
@ -1719,7 +1733,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
|||
start: function() {
|
||||
this._super();
|
||||
this.dataset = new openerp.base.ReadOnlyDataSetSearch(this.session, this.model,
|
||||
this.context, this.domain);
|
||||
this.context);
|
||||
this.dataset.parent_view = this.options.parent_view;
|
||||
if (this.options.initial_view == "search") {
|
||||
this.setup_search_view();
|
||||
|
@ -1739,11 +1753,11 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
|||
});
|
||||
this.searchview.on_search.add(function(domains, contexts, groupbys) {
|
||||
if (self.initial_ids) {
|
||||
self.view_list.do_search.call(self, domains.concat([[["id", "in", self.initial_ids]]]),
|
||||
self.view_list.do_search.call(self, domains.concat([[["id", "in", self.initial_ids]], self.domain]),
|
||||
contexts, groupbys);
|
||||
self.initial_ids = undefined;
|
||||
} else {
|
||||
self.view_list.do_search.call(self, domains, contexts, groupbys);
|
||||
self.view_list.do_search.call(self, domains.concat([self.domain]), contexts, groupbys);
|
||||
}
|
||||
});
|
||||
this.searchview.on_loaded.add_last(function () {
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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 = $('<select>')
|
||||
.appendTo($this.empty())
|
||||
.click(function (e) {e.stopPropagation();})
|
||||
.append('<option value="80">80</option>' +
|
||||
'<option value="100">100</option>' +
|
||||
'<option value="200">200</option>' +
|
||||
'<option value="500">500</option>' +
|
||||
'<option value="NaN">Unlimited</option>')
|
||||
.change(function () {
|
||||
var val = parseInt($select.val(), 10);
|
||||
self._limit = (isNaN(val) ? null : val);
|
||||
self.page = 0;
|
||||
self.reload_content();
|
||||
})
|
||||
.val(self._limit || 'NaN');
|
||||
});
|
||||
|
||||
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar);
|
||||
},
|
||||
/**
|
||||
* Configures the ListView pager based on the provided dataset's information
|
||||
*
|
||||
* Horrifying side-effect: sets the dataset's data on this.dataset?
|
||||
*
|
||||
* @param {openerp.base.DataSet} dataset
|
||||
*/
|
||||
configure_pager: function (dataset) {
|
||||
this.dataset.ids = dataset.ids;
|
||||
|
||||
var limit = this.limit(),
|
||||
total = dataset.ids.length,
|
||||
first = (this.page * limit),
|
||||
last;
|
||||
if (!limit || (total - first) < limit) {
|
||||
last = total;
|
||||
} else {
|
||||
last = first + limit;
|
||||
}
|
||||
this.$element.find('span.oe-pager-state').empty().text(_.sprintf(
|
||||
"[%d to %d] of %d", first + 1, last, total));
|
||||
|
||||
this.$element
|
||||
.find('button[data-pager-action=first], button[data-pager-action=previous]')
|
||||
.attr('disabled', this.page === 0)
|
||||
.end()
|
||||
.find('button[data-pager-action=last], button[data-pager-action=next]')
|
||||
.attr('disabled', last === total);
|
||||
},
|
||||
/**
|
||||
* Sets up the listview's columns: merges view and fields data, move
|
||||
* grouped-by columns to the front of the columns list and make them all
|
||||
|
@ -182,7 +267,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
}
|
||||
return column;
|
||||
};
|
||||
|
||||
|
||||
this.columns.splice(0, this.columns.length);
|
||||
this.columns.push.apply(
|
||||
this.columns,
|
||||
|
@ -264,10 +349,8 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
*/
|
||||
reload_view: function (grouped) {
|
||||
var self = this;
|
||||
this.dataset.offset = 0;
|
||||
this.dataset.limit = false;
|
||||
var callback = function (field_view_get) {
|
||||
self.on_loaded(field_view_get, grouped);
|
||||
self.on_loaded(field_view_get, grouped);
|
||||
};
|
||||
if (this.embedded_view) {
|
||||
return $.Deferred().then(callback).resolve({fields_view: this.embedded_view});
|
||||
|
@ -346,7 +429,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
|||
* @param {Array} records selected record values
|
||||
*/
|
||||
do_select: function (ids, records) {
|
||||
this.$element.find('#oe-list-delete')
|
||||
this.$element.find('.oe-list-delete')
|
||||
.attr('disabled', !ids.length);
|
||||
|
||||
if (!records.length) {
|
||||
|
@ -505,6 +588,7 @@ openerp.base.ListView.List = Class.extend( /** @lends openerp.base.ListView.List
|
|||
init: function (group, opts) {
|
||||
var self = this;
|
||||
this.group = group;
|
||||
this.view = group.view;
|
||||
|
||||
this.options = opts.options;
|
||||
this.columns = opts.columns;
|
||||
|
@ -555,18 +639,6 @@ openerp.base.ListView.List = Class.extend( /** @lends openerp.base.ListView.List
|
|||
this.$current = this.$_element.clone(true);
|
||||
this.$current.empty().append(QWeb.render('ListView.rows', this));
|
||||
},
|
||||
get_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;
|
||||
},
|
||||
/**
|
||||
* Gets the ids of all currently selected records, if any
|
||||
* @returns {Object} object with the keys ``ids`` and ``records``, holding respectively the ids of all selected records and the records themselves.
|
||||
|
@ -715,13 +787,10 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
|||
this.columns = view.columns;
|
||||
this.datagroup = null;
|
||||
|
||||
this.sections = [];
|
||||
this.$row = null;
|
||||
this.children = {};
|
||||
},
|
||||
pad: function ($row) {
|
||||
if (this.options.selectable) {
|
||||
$row.append('<td>');
|
||||
}
|
||||
|
||||
this.page = 0;
|
||||
},
|
||||
make_fragment: function () {
|
||||
return document.createDocumentFragment();
|
||||
|
@ -753,10 +822,35 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
|||
}
|
||||
return red_letter_tboday;
|
||||
},
|
||||
make_paginator: function () {
|
||||
var self = this;
|
||||
var $prev = $('<button type="button" data-pager-action="previous"><</button>')
|
||||
.click(function (e) {
|
||||
e.stopPropagation();
|
||||
self.page -= 1;
|
||||
|
||||
self.$row.closest('tbody').next()
|
||||
.replaceWith(self.render());
|
||||
});
|
||||
var $next = $('<button type="button" data-pager-action="next">></button>')
|
||||
.click(function (e) {
|
||||
e.stopPropagation();
|
||||
self.page += 1;
|
||||
|
||||
self.$row.closest('tbody').next()
|
||||
.replaceWith(self.render());
|
||||
});
|
||||
this.$row.children().last()
|
||||
.append($prev)
|
||||
.append('<span class="oe-pager-state"></span>')
|
||||
.append($next);
|
||||
},
|
||||
open: function (point_insertion) {
|
||||
this.render().insertAfter(point_insertion);
|
||||
this.make_paginator();
|
||||
},
|
||||
close: function () {
|
||||
this.$row.children().last().empty();
|
||||
this.apoptosis();
|
||||
},
|
||||
/**
|
||||
|
@ -788,7 +882,7 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
|||
self.bind_child_events(child);
|
||||
child.datagroup = group;
|
||||
|
||||
var $row = $('<tr>');
|
||||
var $row = child.$row = $('<tr>');
|
||||
if (group.openable) {
|
||||
$row.click(function (e) {
|
||||
if (!$row.data('open')) {
|
||||
|
@ -808,7 +902,7 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
|||
}
|
||||
placeholder.appendChild($row[0]);
|
||||
|
||||
var $group_column = $('<th>').appendTo($row);
|
||||
var $group_column = $('<th class="oe-group-name">').appendTo($row);
|
||||
if (group.grouped_on) {
|
||||
// Don't fill this if group_by_no_leaf but no group_by
|
||||
$group_column
|
||||
|
@ -822,8 +916,10 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
|||
self.indent($group_column, group.level);
|
||||
// count column
|
||||
$('<td>').text(group.length).appendTo($row);
|
||||
|
||||
self.pad($row);
|
||||
|
||||
if (self.options.selectable) {
|
||||
$row.append('<td>');
|
||||
}
|
||||
_(self.columns).chain()
|
||||
.filter(function (column) {return !column.invisible;})
|
||||
.each(function (column) {
|
||||
|
@ -844,6 +940,9 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
|||
$row.append('<td>');
|
||||
}
|
||||
});
|
||||
if (self.options.deletable) {
|
||||
$row.append('<td class="oe-group-pagination">');
|
||||
}
|
||||
});
|
||||
return placeholder;
|
||||
},
|
||||
|
@ -867,6 +966,7 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
|||
},
|
||||
render_dataset: function (dataset) {
|
||||
var rows = [],
|
||||
self = this,
|
||||
list = new openerp.base.ListView.List(this, {
|
||||
options: this.options,
|
||||
columns: this.columns,
|
||||
|
@ -875,11 +975,30 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
|||
});
|
||||
this.bind_child_events(list);
|
||||
|
||||
var d = new $.Deferred();
|
||||
var view = this.view,
|
||||
limit = view.limit(),
|
||||
d = new $.Deferred(),
|
||||
page = this.datagroup.openable ? this.page : view.page;
|
||||
|
||||
dataset.read_slice(
|
||||
_.filter(_.pluck(_.select(this.columns, function(x) {return x.tag == "field";}), 'name'), _.identity),
|
||||
0, false,
|
||||
page * limit, limit,
|
||||
function (records) {
|
||||
if (!self.datagroup.openable) {
|
||||
view.configure_pager(dataset);
|
||||
} else {
|
||||
var pages = Math.ceil(dataset.ids.length / limit);
|
||||
self.$row
|
||||
.find('.oe-pager-state')
|
||||
.text(_.sprintf('%d/%d', page + 1, pages))
|
||||
.end()
|
||||
.find('button[data-pager-action=previous]')
|
||||
.attr('disabled', page === 0)
|
||||
.end()
|
||||
.find('button[data-pager-action=next]')
|
||||
.attr('disabled', page === pages - 1);
|
||||
}
|
||||
|
||||
var form_records = _(records).map(
|
||||
$.proxy(list, 'transform_record'));
|
||||
|
||||
|
|
|
@ -736,6 +736,9 @@ openerp.base.search.ExtendedSearch = openerp.base.BaseWidget.extend({
|
|||
},
|
||||
start: function () {
|
||||
this._super();
|
||||
if (!this.$element) {
|
||||
return; // not a logical state but sometimes it happens
|
||||
}
|
||||
this.$element.closest("table.oe-searchview-render-line").css("display", "none");
|
||||
var self = this;
|
||||
this.rpc("/base/searchview/fields_get",
|
||||
|
@ -751,6 +754,9 @@ openerp.base.search.ExtendedSearch = openerp.base.BaseWidget.extend({
|
|||
return null;
|
||||
},
|
||||
get_domain: function() {
|
||||
if (!this.$element) {
|
||||
return null; // not a logical state but sometimes it happens
|
||||
}
|
||||
if(this.$element.closest("table.oe-searchview-render-line").css("display") == "none") {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -86,19 +86,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td><label for="password">Password:</label></td>
|
||||
<td><input type="password" name="password"
|
||||
t-att-value="selected_password || ''"/></td>
|
||||
</tr>
|
||||
<tr t-if="has_local_storage">
|
||||
<td><label for="remember">Remember password:</label></td>
|
||||
<td class="oe_remember">
|
||||
<t t-if="remember">
|
||||
<input type="checkbox" name="remember" checked="yes"/>
|
||||
</t>
|
||||
<t t-if="!remember">
|
||||
<input type="checkbox" name="remember"/>
|
||||
</t>
|
||||
</td>
|
||||
<td><input type="password" name="password"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
|
@ -255,11 +243,11 @@
|
|||
<th t-if="actions_span" t-att-colspan="actions_span"
|
||||
class="oe-actions">
|
||||
<t t-if="flags.action_buttons !== false">
|
||||
<button type="button" id="oe-list-add"
|
||||
<button type="button" class="oe-list-add"
|
||||
t-if="options.addable">
|
||||
<t t-esc="options.addable"/>
|
||||
</button>
|
||||
<button type="button" id="oe-list-delete"
|
||||
<button type="button" class="oe-list-delete"
|
||||
t-if="options.selectable and options.deletable">
|
||||
Delete
|
||||
</button>
|
||||
|
@ -268,16 +256,19 @@
|
|||
<th t-att-colspan="columns_count - actions_span"
|
||||
class="oe-list-pager">
|
||||
<t t-if="flags.pager !== false">
|
||||
<button type="button" data-pager-action="first">First</button>
|
||||
<button type="button" data-pager-action="previous"
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="first">First</button>
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="previous"
|
||||
><<</button>
|
||||
|
||||
<span class="oe-pager-first">1</span>
|
||||
to <span class="oe-pager-last">1</span>
|
||||
of <span class="oe-pager-total">1</span>
|
||||
<span class="oe-pager-state">
|
||||
</span>
|
||||
|
||||
<button type="button" data-pager-action="next">>></button>
|
||||
<button type="button" data-pager-action="last">Last</button>
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="next">>></button>
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="last">Last</button>
|
||||
</t>
|
||||
</th>
|
||||
</tr>
|
||||
|
@ -541,9 +532,9 @@
|
|||
<span class="oe-m2o-cm-button" t-att-id="widget.name + '_open'">
|
||||
<img src="/base/static/src/img/icons/gtk-index.png"/></span>
|
||||
<div t-att-id="widget.cm_id" class="contextMenu" style="display:none"><ul>
|
||||
<li t-att-id="widget.cm_id + '_search'">Search</li>
|
||||
<li t-att-id="widget.cm_id + '_create'">Create New</li>
|
||||
<li t-att-id="widget.cm_id + '_open'" style="color:grey">Open</li>
|
||||
<li t-att-id="widget.cm_id + '_search'">Search...</li>
|
||||
<li t-att-id="widget.cm_id + '_create'">Create New...</li>
|
||||
<li t-att-id="widget.cm_id + '_open'" style="color:grey">Open...</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
</t>
|
||||
|
@ -803,8 +794,8 @@
|
|||
<t t-name="SearchView.extended_search.group">
|
||||
<div t-att-id="element_id" class="searchview_extended_group">
|
||||
<select class="searchview_extended_group_choice">
|
||||
<option value="all">All the following conditions must match</option>
|
||||
<option value="any">Any of the following conditions must match</option>
|
||||
<option value="all">All the following conditions must match</option>
|
||||
<option value="none">None of the following conditions must match</option>
|
||||
</select>
|
||||
<a class="searchview_extended_delete_group"
|
||||
|
@ -886,7 +877,9 @@
|
|||
<td>
|
||||
<p>
|
||||
<t t-js="d">
|
||||
d.html_error = context.engine.tools.html_escape(d.error.data.fault_code).replace(/\n/g, '<br/>');
|
||||
var message = d.message ? d.message : d.error.data.fault_code;
|
||||
d.html_error = context.engine.tools.html_escape(message)
|
||||
.replace(/\n/g, '<br/>');
|
||||
</t>
|
||||
<t t-raw="html_error"/>
|
||||
</p>
|
||||
|
|
|
@ -149,7 +149,7 @@ $(document).ready(function () {
|
|||
listview.$element.find('tbody th input:eq(1)')
|
||||
.attr('checked', true);
|
||||
|
||||
listview.$element.find('#oe-list-delete').click();
|
||||
listview.$element.find('.oe-list-delete').click();
|
||||
deepEqual(deleted, [2, 3]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -262,21 +262,13 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
throw "Unrecognized date/time format";
|
||||
},
|
||||
|
||||
reload_gantt: function(domain) {
|
||||
reload_gantt: function() {
|
||||
var self = this;
|
||||
var ajax = {
|
||||
url: '/base/dataset/search_read',
|
||||
async: false
|
||||
};
|
||||
this.rpc(ajax, {
|
||||
model: this.dataset.model,
|
||||
domain: self.dataset.domain,
|
||||
context :self.dataset.get_context()
|
||||
}, function(response) {
|
||||
ganttChartControl.clearAll();
|
||||
jQuery("#GanttDiv").children().remove();
|
||||
self.load_event(response);
|
||||
});
|
||||
this.dataset.read_slice(false, false, false, function(response) {
|
||||
ganttChartControl.clearAll();
|
||||
jQuery("#GanttDiv").children().remove();
|
||||
self.load_event(response);
|
||||
});
|
||||
},
|
||||
|
||||
do_search: function (domains, contexts, groupbys) {
|
||||
|
@ -290,7 +282,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
|||
}, function (results) {
|
||||
self.dataset.context = results.context;
|
||||
self.dataset.domain = results.domain;
|
||||
return self.reload_gantt(self.dataset.domain);
|
||||
self.reload_gantt();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -90,11 +90,8 @@ openerp.web_mobile.ListView = openerp.base.Controller.extend({
|
|||
on_action: function(action) {
|
||||
var self = this;
|
||||
var view_id = action.views[0][0];
|
||||
var model = action.res_model;
|
||||
|
||||
self.rpc('/base/dataset/search_read', {
|
||||
model: model
|
||||
},function(result){
|
||||
(new openerp.base.DataSetSearch(this.session, action.res_model, null, null))
|
||||
.read_slice(false, false, false, function(result){
|
||||
this.listview = new openerp.web_mobile.ListView(this.session, "oe_app");
|
||||
self.$element.html(QWeb.render("ListView", {'records' : result}));
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue