[MERGE] trunk.
bzr revid: vda@tinyerp.com-20110628043508-iyop8welvnhy54ag bzr revid: vda@tinyerp.com-20110629070002-ogbwzoiy883datmy bzr revid: vda@tinyerp.com-20110630051825-02j1vps6w2euxut1
This commit is contained in:
@@ -171,8 +171,9 @@ class Session(openerpweb.Controller):
|
||||
a list of fields to group by, potentially empty (in which case
|
||||
no group by should be performed)
|
||||
"""
|
||||
context = req.session.eval_context(openerpweb.nonliterals.CompoundContext(*contexts))
|
||||
domain = req.session.eval_domain(openerpweb.nonliterals.CompoundDomain(*(domains or [])), context)
|
||||
context, domain = eval_context_and_domain(req.session,
|
||||
openerpweb.nonliterals.CompoundContext(*(contexts or [])),
|
||||
openerpweb.nonliterals.CompoundDomain(*(domains or [])))
|
||||
|
||||
group_by_sequence = []
|
||||
for candidate in (group_by_seq or []):
|
||||
@@ -233,12 +234,12 @@ class Session(openerpweb.Controller):
|
||||
|
||||
def eval_context_and_domain(session, context, domain=None):
|
||||
e_context = session.eval_context(context)
|
||||
e_domain = session.eval_domain(domain or [], e_context)
|
||||
# should we give the evaluated context as an evaluation context to the domain?
|
||||
e_domain = session.eval_domain(domain or [])
|
||||
|
||||
return (e_context, e_domain)
|
||||
return e_context, e_domain
|
||||
|
||||
def load_actions_from_ir_values(req, key, key2, models, meta, context):
|
||||
context['bin_size'] = False # Possible upstream bug. Antony says not to loose time on this.
|
||||
Values = req.session.model('ir.values')
|
||||
actions = Values.get(key, key2, models, meta, context)
|
||||
|
||||
@@ -249,12 +250,12 @@ def load_actions_from_ir_values(req, key, key2, models, meta, context):
|
||||
|
||||
def clean_action(action, session):
|
||||
# values come from the server, we can just eval them
|
||||
if isinstance(action['context'], basestring):
|
||||
if isinstance(action.get('context', None), basestring):
|
||||
action['context'] = eval(
|
||||
action['context'],
|
||||
session.evaluation_context()) or {}
|
||||
|
||||
if isinstance(action['domain'], basestring):
|
||||
if isinstance(action.get('domain', None), basestring):
|
||||
action['domain'] = eval(
|
||||
action['domain'],
|
||||
session.evaluation_context(
|
||||
@@ -285,13 +286,15 @@ def fix_view_modes(action):
|
||||
if action.pop('view_type') != 'form':
|
||||
return
|
||||
|
||||
action['view_mode'] = ','.join(
|
||||
mode if mode != 'tree' else 'list'
|
||||
for mode in action['view_mode'].split(','))
|
||||
action['views'] = [
|
||||
[id, mode if mode != 'tree' else 'list']
|
||||
for id, mode in action['views']
|
||||
]
|
||||
if action.has_key('view_mode'):
|
||||
action['view_mode'] = ','.join(
|
||||
mode if mode != 'tree' else 'list'
|
||||
for mode in action['view_mode'].split(','))
|
||||
if action.has_key('views'):
|
||||
action['views'] = [
|
||||
[id, mode if mode != 'tree' else 'list']
|
||||
for id, mode in action['views']
|
||||
]
|
||||
return action
|
||||
|
||||
class Menu(openerpweb.Controller):
|
||||
@@ -435,23 +438,31 @@ class DataSet(openerpweb.Controller):
|
||||
return {'result': r}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def unlink(self, request, model, ids=[]):
|
||||
def unlink(self, request, model, ids=()):
|
||||
Model = request.session.model(model)
|
||||
return Model.unlink(ids, request.session.eval_context(request.context))
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def call(self, req, model, method, args, domain_id=None, context_id=None):
|
||||
def call_common(self, req, model, method, args, domain_id=None, context_id=None):
|
||||
domain = args[domain_id] if domain_id and len(args) - 1 >= domain_id else []
|
||||
context = args[context_id] if context_id and len(args) - 1 >= context_id else {}
|
||||
c, d = eval_context_and_domain(req.session, context, domain);
|
||||
if(domain_id and len(args) - 1 >= domain_id):
|
||||
c, d = eval_context_and_domain(req.session, context, domain)
|
||||
if domain_id and len(args) - 1 >= domain_id:
|
||||
args[domain_id] = d
|
||||
if(context_id and len(args) - 1 >= context_id):
|
||||
if context_id and len(args) - 1 >= context_id:
|
||||
args[context_id] = c
|
||||
|
||||
m = req.session.model(model)
|
||||
r = getattr(m, method)(*args)
|
||||
return {'result': r}
|
||||
|
||||
return getattr(req.session.model(model), method)(*args)
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def call(self, req, model, method, args, domain_id=None, context_id=None):
|
||||
return {'result': self.call_common(req, model, method, args, domain_id, context_id)}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def call_button(self, req, model, method, args, domain_id=None, context_id=None):
|
||||
action = self.call_common(req, model, method, args, domain_id, context_id)
|
||||
if isinstance(action, dict) and action.get('type') != '':
|
||||
clean_action(action, req.session)
|
||||
return {'result': action}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def exec_workflow(self, req, model, id, signal):
|
||||
@@ -701,7 +712,7 @@ class Binary(openerpweb.Controller):
|
||||
for key, val in cherrypy.request.headers.iteritems():
|
||||
headers[key.lower()] = val
|
||||
size = int(headers.get('content-length', 0))
|
||||
# TODO: might be usefull to have a configuration flag for max-lenght file uploads
|
||||
# TODO: might be useful to have a configuration flag for max-length file uploads
|
||||
try:
|
||||
out = """<script language="javascript" type="text/javascript">
|
||||
var win = window.top.window,
|
||||
@@ -756,7 +767,6 @@ class Action(openerpweb.Controller):
|
||||
Actions = req.session.model('ir.actions.actions')
|
||||
value = False
|
||||
context = req.session.eval_context(req.context)
|
||||
context["bin_size"] = False
|
||||
action_type = Actions.read([action_id], ['type'], context)
|
||||
if action_type:
|
||||
action = req.session.model(action_type[0]['type']).read([action_id], False,
|
||||
|
||||
@@ -11,8 +11,8 @@ openerp.base.callback = function(obj, method) {
|
||||
for(var i = 0; i < callback.callback_chain.length; i++) {
|
||||
var c = callback.callback_chain[i];
|
||||
if(c.unique) {
|
||||
// al: obscure but shortening C-style hack, sorry
|
||||
callback.callback_chain.pop(i--);
|
||||
callback.callback_chain.splice(i, 1);
|
||||
i -= 1;
|
||||
}
|
||||
r = c.callback.apply(c.self, c.args.concat(args));
|
||||
// TODO special value to stop the chain
|
||||
@@ -137,6 +137,29 @@ openerp.base.Registry = Class.extend( /** @lends openerp.base.Registry# */ {
|
||||
}
|
||||
return object_match;
|
||||
},
|
||||
/**
|
||||
* Tries a number of keys, and returns the first object matching one of
|
||||
* the keys.
|
||||
*
|
||||
* @param {Array} keys a sequence of keys to fetch the object for
|
||||
* @returns {Class} the first class found matching an object
|
||||
*
|
||||
* @throws {openerp.base.KeyNotFound} if none of the keys was in the mapping
|
||||
* @trows {openerp.base.ObjectNotFound} if a found object path was invalid
|
||||
*/
|
||||
get_any: function (keys) {
|
||||
for (var i=0; i<keys.length; ++i) {
|
||||
try {
|
||||
return this.get_object(keys[i]);
|
||||
} catch (e) {
|
||||
if (e instanceof openerp.base.KeyNotFound) {
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
throw new openerp.base.KeyNotFound(keys.join(','));
|
||||
},
|
||||
/**
|
||||
* Adds a new key and value to the registry.
|
||||
*
|
||||
@@ -261,13 +284,12 @@ openerp.base.generate_null_object_class = function(claz, add) {
|
||||
}
|
||||
if (prototype.prototype)
|
||||
copy_proto(prototype.prototype);
|
||||
}
|
||||
};
|
||||
copy_proto(claz.prototype);
|
||||
var init = openerp.base.BasicController.prototype.init;
|
||||
newer.init = init;
|
||||
newer.init = openerp.base.BasicController.prototype.init;
|
||||
var tmpclass = claz.extend(newer);
|
||||
return tmpclass.extend(add || {});
|
||||
}
|
||||
};
|
||||
|
||||
openerp.base.Notification = openerp.base.BasicController.extend({
|
||||
init: function(element_id) {
|
||||
@@ -328,30 +350,39 @@ 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;
|
||||
params.context = typeof(params.context) != "undefined" ? params.context : this.context;
|
||||
|
||||
// Use a default error handler unless defined
|
||||
error_callback = typeof(error_callback) != "undefined" ? error_callback : this.on_rpc_error;
|
||||
// niv: wtf?
|
||||
//params.context = typeof(params.context) != "undefined" ? params.context : this.context;
|
||||
|
||||
// Call using the rpc_mode
|
||||
return this.rpc_ajax(url, {
|
||||
var deferred = $.Deferred();
|
||||
this.rpc_ajax(url, {
|
||||
jsonrpc: "2.0",
|
||||
method: "call",
|
||||
params: params,
|
||||
id:null
|
||||
}, success_callback, error_callback);
|
||||
}).then(function () {deferred.resolve.apply(deferred, arguments);},
|
||||
function(error) {deferred.reject(error, $.Event());});
|
||||
return deferred.fail(function() {
|
||||
deferred.fail(function(error, event) {
|
||||
if (!event.isDefaultPrevented()) {
|
||||
self.on_rpc_error(error, event);
|
||||
}
|
||||
});
|
||||
}).then(success_callback, error_callback).promise();
|
||||
},
|
||||
/**
|
||||
* Raw JSON-RPC call
|
||||
*
|
||||
* @returns {jQuery.Deferred} ajax-based deferred object
|
||||
*/
|
||||
rpc_ajax: function(url, payload, success_callback, error_callback) {
|
||||
rpc_ajax: function(url, payload) {
|
||||
var self = this;
|
||||
this.on_rpc_request();
|
||||
// url can be an $.ajax option object
|
||||
@@ -366,33 +397,35 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(payload),
|
||||
processData: false,
|
||||
success: function(response, textStatus, jqXHR) {
|
||||
processData: false
|
||||
}, url);
|
||||
var deferred = $.Deferred();
|
||||
$.ajax(ajax).done(function(response, textStatus, jqXHR) {
|
||||
self.on_rpc_response();
|
||||
if (response.error) {
|
||||
if (response.error.data.type == "session_invalid") {
|
||||
self.uid = false;
|
||||
self.on_session_invalid(function() {
|
||||
self.rpc(url, payload.params, success_callback, error_callback);
|
||||
self.rpc(url, payload.params,
|
||||
function() {deferred.resolve.apply(deferred, arguments);},
|
||||
function() {deferred.reject.apply(deferred, arguments);});
|
||||
});
|
||||
} else {
|
||||
error_callback(response.error);
|
||||
deferred.reject(response.error);
|
||||
}
|
||||
} else if (success_callback) {
|
||||
success_callback(response["result"], textStatus, jqXHR);
|
||||
} else {
|
||||
deferred.resolve(response["result"], textStatus, jqXHR);
|
||||
}
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||
self.on_rpc_response();
|
||||
var error = {
|
||||
code: -32098,
|
||||
message: "XmlHttpRequestError " + errorThrown,
|
||||
data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] }
|
||||
};
|
||||
error_callback(error);
|
||||
}
|
||||
}, url);
|
||||
return $.ajax(ajax);
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise();
|
||||
},
|
||||
on_rpc_request: function() {
|
||||
},
|
||||
@@ -557,7 +590,7 @@ openerp.base.Controller = openerp.base.BasicController.extend( /** @lends opener
|
||||
*/
|
||||
controller_get: function(key) {
|
||||
return this.controller_registry[key];
|
||||
// OR should contrustct it ? setting parent correctly ?
|
||||
// OR should build it ? setting parent correctly ?
|
||||
// function construct(constructor, args) {
|
||||
// function F() {
|
||||
// return constructor.apply(this, args);
|
||||
@@ -617,7 +650,7 @@ openerp.base.Controller = openerp.base.BasicController.extend( /** @lends opener
|
||||
}
|
||||
// TODO if post prefix
|
||||
//this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
|
||||
};
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Performs a JSON-RPC call
|
||||
|
||||
@@ -196,9 +196,7 @@ openerp.base.GrouplessDataGroup = openerp.base.DataGroup.extend(
|
||||
this._super(session, model, domain, context, null, level);
|
||||
},
|
||||
list: function (ifGroups, ifRecords) {
|
||||
ifRecords(_.extend(
|
||||
new openerp.base.DataSetSearch(this.session, this.model),
|
||||
{domain: this.domain, context: this.context}));
|
||||
ifRecords(new openerp.base.DataSetSearch(this.session, this.model, this.context, this.domain));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -236,20 +234,19 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
this.model = model;
|
||||
this.context = context || {};
|
||||
this.index = null;
|
||||
this.count = 0;
|
||||
},
|
||||
start: function() {
|
||||
},
|
||||
previous: function () {
|
||||
this.index -= 1;
|
||||
if (this.index < 0) {
|
||||
this.index = this.count - 1;
|
||||
this.index = this.ids.length - 1;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
next: function () {
|
||||
this.index += 1;
|
||||
if (this.index >= this.count) {
|
||||
if (this.index >= this.ids.length) {
|
||||
this.index = 0;
|
||||
}
|
||||
return this;
|
||||
@@ -262,7 +259,8 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
return this.rpc('/base/dataset/get', {
|
||||
model: this.model,
|
||||
ids: ids,
|
||||
fields: fields
|
||||
fields: fields,
|
||||
context: this.get_context()
|
||||
}, callback);
|
||||
},
|
||||
/**
|
||||
@@ -287,19 +285,18 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
});
|
||||
}
|
||||
},
|
||||
default_get: function(fields, context, callback) {
|
||||
context = context || this.context;
|
||||
default_get: function(fields, callback) {
|
||||
return this.rpc('/base/dataset/default_get', {
|
||||
model: this.model,
|
||||
fields: fields,
|
||||
context: context
|
||||
context: this.get_context()
|
||||
}, callback);
|
||||
},
|
||||
create: function(data, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/create', {
|
||||
model: this.model,
|
||||
data: data,
|
||||
context: this.context
|
||||
context: this.get_context()
|
||||
}, callback, error_callback);
|
||||
},
|
||||
write: function (id, data, callback) {
|
||||
@@ -307,12 +304,12 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
model: this.model,
|
||||
id: id,
|
||||
data: data,
|
||||
context: this.context
|
||||
context: this.get_context()
|
||||
}, callback);
|
||||
},
|
||||
unlink: function(ids, callback, error_callback) {
|
||||
var self = this;
|
||||
return this.call_and_eval("unlink", [ids, this.context], null, 1,
|
||||
return this.call_and_eval("unlink", [ids, this.get_context()], null, 1,
|
||||
callback, error_callback);
|
||||
},
|
||||
call: function (method, args, callback, error_callback) {
|
||||
@@ -331,14 +328,28 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Arguments:
|
||||
* name='', args=[], operator='ilike', context=None, limit=100
|
||||
call_button: function (method, args, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/call_button', {
|
||||
model: this.model,
|
||||
method: method,
|
||||
domain_id: null,
|
||||
context_id: 1,
|
||||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
name_get: function(ids, callback) {
|
||||
return this.call_and_eval('name_get', [ids, this.get_context()], null, 1, callback);
|
||||
},
|
||||
/*
|
||||
* args = domain
|
||||
*/
|
||||
name_search: function (args, callback, error_callback) {
|
||||
name_search: function (name, args, operator, limit, callback) {
|
||||
return this.call_and_eval('name_search',
|
||||
args, 1, 3,
|
||||
callback, error_callback);
|
||||
[name || '', args || false, operator || 'ilike', this.get_context(), limit || 100],
|
||||
1, 3, callback);
|
||||
},
|
||||
name_create: function(name, callback) {
|
||||
return this.call_and_eval('name_create', [name, this.get_context()], null, 1, callback);
|
||||
},
|
||||
exec_workflow: function (id, signal, callback) {
|
||||
return this.rpc('/base/dataset/exec_workflow', {
|
||||
@@ -346,15 +357,20 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
id: id,
|
||||
signal: signal
|
||||
}, callback);
|
||||
},
|
||||
get_context: function() {
|
||||
return this.context;
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.DataSetStatic = openerp.base.DataSet.extend({
|
||||
init: function(session, model, ids) {
|
||||
this._super(session, model);
|
||||
init: function(session, model, context, ids) {
|
||||
this._super(session, model, context);
|
||||
// all local records
|
||||
this.ids = ids || [];
|
||||
this.count = this.ids.length;
|
||||
if (this.ids.length) {
|
||||
this.index = 0;
|
||||
}
|
||||
},
|
||||
read_slice: function (fields, offset, limit, callback) {
|
||||
var self = this;
|
||||
@@ -364,9 +380,8 @@ openerp.base.DataSetStatic = openerp.base.DataSet.extend({
|
||||
},
|
||||
set_ids: function (ids) {
|
||||
this.ids = ids;
|
||||
this.count = this.ids.length;
|
||||
this.index = this.index <= this.count - 1 ?
|
||||
this.index : (this.count > 0 ? this.count - 1 : 0);
|
||||
this.index = this.index <= this.ids.length - 1 ?
|
||||
this.index : (this.ids.length > 0 ? this.length - 1 : 0);
|
||||
},
|
||||
unlink: function(ids) {
|
||||
this.on_unlink(ids);
|
||||
@@ -402,14 +417,13 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
||||
model: this.model,
|
||||
fields: fields,
|
||||
domain: this.domain,
|
||||
context: this.context,
|
||||
context: this.get_context(),
|
||||
sort: this.sort(),
|
||||
offset: offset,
|
||||
limit: limit
|
||||
}, function (records) {
|
||||
self.ids.splice(0, self.ids.length);
|
||||
self.offset = offset;
|
||||
self.count = records.length; // TODO: get real count
|
||||
for (var i=0; i < records.length; i++ ) {
|
||||
self.ids.push(records[i].id);
|
||||
}
|
||||
@@ -449,9 +463,8 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
||||
var self = this;
|
||||
return this._super(ids, function(result) {
|
||||
self.ids = _.without.apply(_, [self.ids].concat(ids));
|
||||
self.count = self.ids.length;
|
||||
self.index = self.index <= self.count - 1 ?
|
||||
self.index : (self.count > 0 ? self.count -1 : 0);
|
||||
self.index = self.index <= self.ids.length - 1 ?
|
||||
self.index : (self.ids.length > 0 ? self.ids.length -1 : 0);
|
||||
if (callback)
|
||||
callback(result);
|
||||
}, error_callback);
|
||||
@@ -514,6 +527,7 @@ openerp.base.BufferedDataSet = openerp.base.DataSetStatic.extend({
|
||||
this.to_create = [];
|
||||
this.to_write = [];
|
||||
this.cache = [];
|
||||
this.delete_all = false;
|
||||
},
|
||||
on_change: function() {},
|
||||
read_ids: function (ids, fields, callback) {
|
||||
@@ -560,7 +574,7 @@ openerp.base.BufferedDataSet = openerp.base.DataSetStatic.extend({
|
||||
return_records();
|
||||
}
|
||||
return completion.promise();
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ReadOnlyDataSetSearch = openerp.base.DataSetSearch.extend({
|
||||
@@ -590,33 +604,44 @@ openerp.base.ReadOnlyDataSetSearch = openerp.base.DataSetSearch.extend({
|
||||
openerp.base.CompoundContext = function() {
|
||||
this.__ref = "compound_context";
|
||||
this.__contexts = [];
|
||||
this.__eval_context = null;
|
||||
var self = this;
|
||||
_.each(arguments, function(x) {
|
||||
self.add(x);
|
||||
});
|
||||
};
|
||||
openerp.base.CompoundContext.prototype.add = function(context) {
|
||||
if (context.__ref === "compound_context")
|
||||
this.__contexts = this.__contexts.concat(context.__contexts);
|
||||
else
|
||||
this.__contexts.push(context);
|
||||
this.__contexts.push(context);
|
||||
return this;
|
||||
};
|
||||
openerp.base.CompoundContext.prototype.set_eval_context = function(eval_context) {
|
||||
this.__eval_context = eval_context;
|
||||
return this;
|
||||
};
|
||||
openerp.base.CompoundContext.prototype.get_eval_context = function() {
|
||||
return this.__eval_context;
|
||||
};
|
||||
|
||||
openerp.base.CompoundDomain = function() {
|
||||
this.__ref = "compound_domain";
|
||||
this.__domains = [];
|
||||
this.__eval_context = null;
|
||||
var self = this;
|
||||
_.each(arguments, function(x) {
|
||||
self.add(x);
|
||||
});
|
||||
};
|
||||
openerp.base.CompoundDomain.prototype.add = function(domain) {
|
||||
if (domain.__ref === "compound_domain")
|
||||
this.__domains = this.__domains.concat(domain.__domains);
|
||||
else
|
||||
this.__domains.push(domain);
|
||||
this.__domains.push(domain);
|
||||
return this;
|
||||
};
|
||||
openerp.base.CompoundDomain.prototype.set_eval_context = function(eval_context) {
|
||||
this.__eval_context = eval_context;
|
||||
return this;
|
||||
};
|
||||
openerp.base.CompoundDomain.prototype.get_eval_context = function() {
|
||||
return this.__eval_context;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
var $pager = this.$element.find('#' + this.element_id + '_header div.oe_form_pager');
|
||||
var index = hide_index ? '-' : this.dataset.index + 1;
|
||||
$pager.find('span.oe_pager_index').html(index);
|
||||
$pager.find('span.oe_pager_count').html(this.dataset.count);
|
||||
$pager.find('span.oe_pager_count').html(this.dataset.ids.length);
|
||||
},
|
||||
do_onchange: function(widget, processed) {
|
||||
processed = processed || [];
|
||||
@@ -174,17 +174,31 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
'True' : true,
|
||||
'None' : null
|
||||
}
|
||||
var parent_fields = null;
|
||||
_.each(call[2].split(','), function(a) {
|
||||
var field = _.trim(a);
|
||||
if (field in argument_replacement) {
|
||||
args.push(argument_replacement[field]);
|
||||
return;
|
||||
} else if (self.fields[field]) {
|
||||
var value = self.fields[field].get_value();
|
||||
var value = self.fields[field].get_on_change_value();
|
||||
args.push(value == null ? false : value);
|
||||
return;
|
||||
} else {
|
||||
args.push(false);
|
||||
self.log("warning : on_change can't find field " + field, onchange);
|
||||
var splitted = field.split('.');
|
||||
if (splitted.length > 1 && _.trim(splitted[0]) === "parent" && self.dataset.parent_view) {
|
||||
if (parent_fields === null) {
|
||||
parent_fields = self.dataset.parent_view.get_fields_values();
|
||||
}
|
||||
var p_val = parent_fields[_.trim(splitted[1])];
|
||||
if (p_val !== undefined) {
|
||||
args.push(value ? value : false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw "Could not get field with name '" + field +
|
||||
"' for onchange '" + onchange + "'";
|
||||
});
|
||||
var ajax = {
|
||||
url: '/base/dataset/call',
|
||||
@@ -241,12 +255,8 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
},
|
||||
on_button_new: function() {
|
||||
var self = this;
|
||||
var context = new openerp.base.CompoundContext(this.dataset.context);
|
||||
if (this.view_manager.action && this.view_manager.action.context) {
|
||||
context.add(this.view_manager.action.context);
|
||||
}
|
||||
$.when(this.has_been_loaded).then(function() {
|
||||
self.dataset.default_get(_.keys(self.fields_view.fields), context, function(result) {
|
||||
self.dataset.default_get(_.keys(self.fields_view.fields), function(result) {
|
||||
self.on_record_loaded(result.result);
|
||||
});
|
||||
});
|
||||
@@ -351,7 +361,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.dataset.ids.unshift(this.datarecord.id);
|
||||
this.dataset.index = 0;
|
||||
}
|
||||
this.dataset.count++;
|
||||
this.do_update_pager();
|
||||
this.do_update_sidebar();
|
||||
this.notification.notify("Record created", "The record has been created with id #" + this.datarecord.id);
|
||||
@@ -421,6 +430,13 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
} else {
|
||||
this.on_button_new();
|
||||
}
|
||||
},
|
||||
get_fields_values: function() {
|
||||
var values = {};
|
||||
_.each(this.fields, function(value, key) {
|
||||
values[key] = value.get_value();
|
||||
});
|
||||
return values;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -448,7 +464,7 @@ openerp.base.form.compute_domain = function(expr, fields) {
|
||||
}
|
||||
}
|
||||
|
||||
var field = fields[ex[0]].value;
|
||||
var field = fields[ex[0]].get_value ? fields[ex[0]].get_value() : fields[ex[0]].value;
|
||||
var op = ex[1];
|
||||
var val = ex[2];
|
||||
|
||||
@@ -568,8 +584,8 @@ openerp.base.form.WidgetFrame = openerp.base.form.Widget.extend({
|
||||
},
|
||||
handle_node: function(node) {
|
||||
var type = this.view.fields_view.fields[node.attrs.name] || {};
|
||||
var widget_type = node.attrs.widget || type.type || node.tag;
|
||||
var widget = new (this.view.registry.get_object(widget_type)) (this.view, node);
|
||||
var widget = new (this.view.registry.get_any(
|
||||
[node.attrs.widget, type.type, node.tag])) (this.view, node);
|
||||
if (node.tag == 'field') {
|
||||
if (!this.view.default_focus_field || node.attrs.default_focus == '1') {
|
||||
this.view.default_focus_field = widget;
|
||||
@@ -666,18 +682,26 @@ openerp.base.form.WidgetButton = openerp.base.form.Widget.extend({
|
||||
this.view.datarecord.id, function (result) {
|
||||
self.log("Button returned", result);
|
||||
self.view.reload();
|
||||
}, function() {
|
||||
self.view.reload();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.WidgetLabel = openerp.base.form.Widget.extend({
|
||||
init: function(view, node) {
|
||||
this.is_field_label = true;
|
||||
this.element_name = 'label_' + node.attrs.name;
|
||||
|
||||
this._super(view, node);
|
||||
|
||||
this.template = "WidgetLabel";
|
||||
// TODO fme: support for attrs.align
|
||||
if (this.node.tag == 'label' && this.node.attrs.colspan) {
|
||||
this.is_field_label = false;
|
||||
this.template = "WidgetParagraph";
|
||||
} else {
|
||||
this.is_field_label = true;
|
||||
this.template = "WidgetLabel";
|
||||
}
|
||||
this.colspan = 1;
|
||||
},
|
||||
render: function () {
|
||||
@@ -723,6 +747,9 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({
|
||||
get_value: function() {
|
||||
return this.value;
|
||||
},
|
||||
get_on_change_value: function() {
|
||||
return this.get_value();
|
||||
},
|
||||
update_dom: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.toggleClass('disabled', this.readonly);
|
||||
@@ -1073,17 +1100,29 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({
|
||||
});
|
||||
})();
|
||||
|
||||
var build_view_fields_values = function(view) {
|
||||
var a_dataset = view.dataset || {};
|
||||
var fields_values = view.get_fields_values();
|
||||
var parent_values = a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {};
|
||||
fields_values.parent = parent_values;
|
||||
return fields_values;
|
||||
}
|
||||
/**
|
||||
* Builds a new context usable for operations related to fields by merging
|
||||
* the fields'context with the action's context.
|
||||
*/
|
||||
var build_relation_context = function(relation_field) {
|
||||
var action = relation_field.view.view_manager.action || {};
|
||||
var a_context = action.context || {};
|
||||
var f_context = relation_field.field.context || {};
|
||||
var ctx = new openerp.base.CompoundContext(a_context).add(f_context);
|
||||
var a_context = relation_field.view.dataset.get_context() || {};
|
||||
var fields_values = build_view_fields_values(relation_field.view);
|
||||
var f_context = new openerp.base.CompoundContext(relation_field.field.context || {}).set_eval_context(fields_values);
|
||||
var ctx = new openerp.base.CompoundContext(a_context, f_context);
|
||||
return ctx;
|
||||
}
|
||||
var build_relation_domain = function(relation_field) {
|
||||
var fields_values = build_view_fields_values(relation_field.view);
|
||||
var f_domain = new openerp.base.CompoundDomain(relation_field.field.domain || []).set_eval_context(fields_values);
|
||||
return f_domain;
|
||||
}
|
||||
|
||||
openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
@@ -1197,10 +1236,10 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
var search_val = request.term;
|
||||
var self = this;
|
||||
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, []);
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, build_relation_context(self));
|
||||
|
||||
dataset.name_search([search_val, self.field.domain || [], 'ilike',
|
||||
build_relation_context(self), this.limit + 1], function(data) {
|
||||
dataset.name_search(search_val, build_relation_domain(self), 'ilike',
|
||||
this.limit + 1, function(data) {
|
||||
self.last_search = data.result;
|
||||
// possible selections for the m2o
|
||||
var values = _.map(data.result, function(x) {
|
||||
@@ -1211,8 +1250,8 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
if (values.length > self.limit) {
|
||||
values = values.slice(0, self.limit);
|
||||
values.push({label: "<em> Search More...</em>", action: function() {
|
||||
dataset.name_search([search_val, self.field.domain || [], 'ilike',
|
||||
build_relation_context(self), false], function(data) {
|
||||
dataset.name_search(search_val, build_relation_domain(self), 'ilike'
|
||||
, false, function(data) {
|
||||
self._change_int_value(null);
|
||||
self._search_create_popup("search", data.result);
|
||||
});
|
||||
@@ -1239,27 +1278,28 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
},
|
||||
_quick_create: function(name) {
|
||||
var self = this;
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, []);
|
||||
dataset.call("name_create", [name, build_relation_context(self)], function(data) {
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, build_relation_context(self));
|
||||
dataset.name_create(name, function(data) {
|
||||
self._change_int_ext_value(data.result);
|
||||
}, function(a, b) {
|
||||
}).fail(function(error, event) {
|
||||
event.preventDefault();
|
||||
self._change_int_value(null);
|
||||
self._search_create_popup("form", undefined, {"default_name": name});
|
||||
});
|
||||
},
|
||||
// all search/create popup handling
|
||||
_search_create_popup: function(view, ids, context) {
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, []);
|
||||
var self = this;
|
||||
var pop = new openerp.base.form.SelectCreatePopup(null, self.view.session);
|
||||
pop.select_element(self.field.relation,{
|
||||
initial_ids: ids ? _.map(ids, function(x) {return x[0]}) : undefined,
|
||||
initial_view: view,
|
||||
disable_multiple_selection: true
|
||||
}, self.view.domain || [],
|
||||
new openerp.base.CompoundContext(build_relation_context(self)).add(context || {}));
|
||||
}, build_relation_domain(self),
|
||||
new openerp.base.CompoundContext(build_relation_context(self), context || {}));
|
||||
pop.on_select_elements.add(function(element_ids) {
|
||||
dataset.call("name_get", [element_ids[0]], function(data) {
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, build_relation_context(self));
|
||||
dataset.name_get([element_ids[0]], function(data) {
|
||||
self._change_int_ext_value(data.result[0]);
|
||||
pop.stop();
|
||||
});
|
||||
@@ -1271,9 +1311,15 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
},
|
||||
_change_int_value: function(value) {
|
||||
this.value = value;
|
||||
if (this.original_value === undefined || (this.value !== undefined &&
|
||||
((this.original_value ? this.original_value[0] : null) !== (this.value ? this.value[0] : null)))) {
|
||||
this.original_value = undefined;
|
||||
var back_orig_value = this.original_value;
|
||||
if (this.value === null || this.value) {
|
||||
this.original_value = this.value;
|
||||
}
|
||||
if (back_orig_value === undefined) { // first use after a set_value()
|
||||
return;
|
||||
}
|
||||
if (this.value !== undefined && ((back_orig_value ? back_orig_value[0] : null)
|
||||
!== (this.value ? this.value[0] : null))) {
|
||||
this.on_ui_change();
|
||||
}
|
||||
},
|
||||
@@ -1284,14 +1330,14 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
var _super = this._super;
|
||||
this.tmp_value = value;
|
||||
var real_set_value = function(rval) {
|
||||
this.tmp_value = undefined;
|
||||
self.tmp_value = undefined;
|
||||
_super.apply(self, rval);
|
||||
self.original_value = rval;
|
||||
self.original_value = undefined;
|
||||
self._change_int_ext_value(rval);
|
||||
};
|
||||
if(typeof(value) === "number") {
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, []);
|
||||
dataset.call("name_get", [value], function(data) {
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, build_relation_context(self));
|
||||
dataset.name_get([value], function(data) {
|
||||
real_set_value(data.result[0]);
|
||||
}).fail(function() {self.tmp_value = undefined;});
|
||||
} else {
|
||||
@@ -1303,10 +1349,10 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
if (this.tmp_value instanceof Array) {
|
||||
return this.tmp_value[0];
|
||||
}
|
||||
return this.tmp_value;
|
||||
return this.tmp_value ? this.tmp_value : false;
|
||||
}
|
||||
if (this.value === undefined)
|
||||
throw "theorically unreachable state";
|
||||
return this.original_value ? this.original_value[0] : false;
|
||||
return this.value ? this.value[0] : false;
|
||||
},
|
||||
validate: function() {
|
||||
@@ -1325,7 +1371,43 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
# (4, ID) link
|
||||
# (5) unlink all (only valid for one2many)
|
||||
*/
|
||||
|
||||
var commands = {
|
||||
// (0, _, {values})
|
||||
CREATE: 0,
|
||||
'create': function (values) {
|
||||
return [commands.CREATE, false, values];
|
||||
},
|
||||
// (1, id, {values})
|
||||
UPDATE: 1,
|
||||
'update': function (id, values) {
|
||||
return [commands.UPDATE, id, values];
|
||||
},
|
||||
// (2, id[, _])
|
||||
DELETE: 2,
|
||||
'delete': function (id) {
|
||||
return [commands.DELETE, id, false];
|
||||
},
|
||||
// (3, id[, _]) removes relation, but not linked record itself
|
||||
FORGET: 3,
|
||||
'forget': function (id) {
|
||||
return [commands.FORGET, id, false];
|
||||
},
|
||||
// (4, id[, _])
|
||||
LINK_TO: 4,
|
||||
'link_to': function (id) {
|
||||
return [commands.LINK_TO, id, false];
|
||||
},
|
||||
// (5[, _[, _]])
|
||||
DELETE_ALL: 5,
|
||||
'delete_all': function () {
|
||||
return [5, false, false];
|
||||
},
|
||||
// (6, _, ids) replaces all linked records with provided ids
|
||||
REPLACE_WITH: 6,
|
||||
'replace_with': function (ids) {
|
||||
return [6, false, ids];
|
||||
}
|
||||
};
|
||||
openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
@@ -1337,7 +1419,9 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
|
||||
var self = this;
|
||||
|
||||
this.dataset = new openerp.base.BufferedDataSet(this.session, this.field.relation);
|
||||
this.dataset = new openerp.base.form.One2ManyDataSet(this.session, this.field.relation);
|
||||
this.dataset.o2m = this;
|
||||
this.dataset.parent_view = this.view;
|
||||
this.dataset.on_change.add_last(function() {
|
||||
self.on_ui_change();
|
||||
});
|
||||
@@ -1360,11 +1444,9 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
|
||||
this.viewmanager = new openerp.base.ViewManager(this.view.session,
|
||||
this.element_id, this.dataset, views);
|
||||
var reg = new openerp.base.Registry();
|
||||
reg.add("form", openerp.base.views.map["form"]);
|
||||
reg.add("graph", openerp.base.views.map["graph"]);
|
||||
reg.add("list", "openerp.base.form.One2ManyListView");
|
||||
this.viewmanager.registry = reg;
|
||||
this.viewmanager.registry = openerp.base.views.clone({
|
||||
list: 'openerp.base.form.One2ManyListView'
|
||||
});
|
||||
|
||||
this.viewmanager.on_controller_inited.add_last(function(view_type, controller) {
|
||||
if (view_type == "list") {
|
||||
@@ -1389,27 +1471,49 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
set_value: function(value) {
|
||||
value = value || [];
|
||||
var self = this;
|
||||
this.dataset.reset_ids([]);
|
||||
if(value.length >= 1 && value[0] instanceof Array) {
|
||||
var ids = [];
|
||||
_each(value, function(command) {
|
||||
if(command[0] == 0) {
|
||||
var obj = {id: _.uniqueId(self.dataset.virtual_id_prefix), values: command[2]};
|
||||
self.dataset.to_create.push(obj);
|
||||
self.dataset.cache.push(_.clone(obj));
|
||||
ids.push(obj.id);
|
||||
} else if(command[0] == 1) {
|
||||
var obj = {id: command[1], values: command[2]};
|
||||
self.dataset.to_write.push(obj);
|
||||
self.dataset.cache.push(_.clone(obj));
|
||||
ids.push(obj.id);
|
||||
} else if(command[0] == 2) {
|
||||
self.dataset.to_delete.push({id: command[1]});
|
||||
} else if(command[0] == 4) {
|
||||
ids.push(command[1]);
|
||||
_.each(value, function(command) {
|
||||
var obj = {values: command[2]};
|
||||
switch (command[0]) {
|
||||
case commands.CREATE:
|
||||
obj['id'] = _.uniqueId(self.dataset.virtual_id_prefix);
|
||||
self.dataset.to_create.push(obj);
|
||||
self.dataset.cache.push(_.clone(obj));
|
||||
ids.push(obj.id);
|
||||
return;
|
||||
case commands.UPDATE:
|
||||
obj['id'] = command[1];
|
||||
self.dataset.to_write.push(obj);
|
||||
self.dataset.cache.push(_.clone(obj));
|
||||
ids.push(obj.id);
|
||||
return;
|
||||
case commands.DELETE:
|
||||
self.dataset.to_delete.push({id: command[1]});
|
||||
return;
|
||||
case commands.LINK_TO:
|
||||
ids.push(command[1]);
|
||||
return;
|
||||
case commands.DELETE_ALL:
|
||||
self.dataset.delete_all = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
this._super(ids);
|
||||
this.dataset.set_ids(ids);
|
||||
} else if (value.length >= 1 && typeof(value[0]) === "object") {
|
||||
var ids = [];
|
||||
this.dataset.delete_all = true;
|
||||
_.each(value, function(command) {
|
||||
var obj = {values: command};
|
||||
obj['id'] = _.uniqueId(self.dataset.virtual_id_prefix);
|
||||
self.dataset.to_create.push(obj);
|
||||
self.dataset.cache.push(_.clone(obj));
|
||||
ids.push(obj.id);
|
||||
});
|
||||
this._super(ids);
|
||||
this.dataset.set_ids(ids);
|
||||
} else {
|
||||
this._super(value);
|
||||
this.dataset.reset_ids(value);
|
||||
@@ -1420,19 +1524,37 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
},
|
||||
get_value: function() {
|
||||
var self = this;
|
||||
var val = _.map(this.dataset.ids, function(id) {
|
||||
if (!this.dataset)
|
||||
return [];
|
||||
var val = this.dataset.delete_all ? [commands.delete_all()] : [];
|
||||
val = val.concat(_.map(this.dataset.ids, function(id) {
|
||||
var alter_order = _.detect(self.dataset.to_create, function(x) {return x.id === id;});
|
||||
if (alter_order) {
|
||||
return [0, 0, alter_order.values];
|
||||
return commands.create(alter_order.values);
|
||||
}
|
||||
alter_order = _.detect(self.dataset.to_write, function(x) {return x.id === id;});
|
||||
if (alter_order) {
|
||||
return [1, alter_order.id, alter_order.values];
|
||||
return commands.update(alter_order.id, alter_order.values);
|
||||
}
|
||||
return commands.link_to(id);
|
||||
}));
|
||||
return val.concat(_.map(
|
||||
this.dataset.to_delete, function(x) {
|
||||
return commands['delete'](x.id);}));
|
||||
},
|
||||
get_on_change_value: function() {
|
||||
var self;
|
||||
return _.map(this.dataset.ids, function(id) {
|
||||
var values = _.detect(self.dataset.cache, function(x) {return x.id === id});
|
||||
if (values) {
|
||||
values = _.clone(values);
|
||||
delete values["id"];
|
||||
return values;
|
||||
} else {
|
||||
console.info("trying to get value in a o2m before that value is loaded");
|
||||
return {};
|
||||
}
|
||||
return [4, id];
|
||||
});
|
||||
val = val.concat(_.map(this.dataset.to_delete, function(v, k) {return [2, x.id];}));
|
||||
return val;
|
||||
},
|
||||
validate: function() {
|
||||
this.invalid = false;
|
||||
@@ -1440,6 +1562,13 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.One2ManyDataSet = openerp.base.BufferedDataSet.extend({
|
||||
get_context: function() {
|
||||
this.context = build_relation_context(this.o2m);
|
||||
return this.context;
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.One2ManyListView = openerp.base.ListView.extend({
|
||||
do_add_record: function () {
|
||||
var self = this;
|
||||
@@ -1447,8 +1576,9 @@ openerp.base.form.One2ManyListView = openerp.base.ListView.extend({
|
||||
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
|
||||
});
|
||||
auto_create: false,
|
||||
parent_view: self.o2m.view
|
||||
}, build_relation_domain(self.o2m), build_relation_context(self.o2m));
|
||||
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]));
|
||||
@@ -1501,7 +1631,7 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
||||
});
|
||||
},
|
||||
get_value: function() {
|
||||
return [[6,false,this.dataset.ids]];
|
||||
return [commands.replace_with(this.dataset.ids)];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1544,6 +1674,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
||||
* - disable_multiple_selection
|
||||
* - alternative_form_view
|
||||
* - auto_create (default true)
|
||||
* - parent_view
|
||||
*/
|
||||
select_element: function(model, options, domain, context) {
|
||||
this.model = model;
|
||||
@@ -1560,6 +1691,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
||||
this._super();
|
||||
this.dataset = new openerp.base.ReadOnlyDataSetSearch(this.session, this.model,
|
||||
this.context, this.domain);
|
||||
this.dataset.parent_view = this.options.parent_view;
|
||||
if (this.options.initial_view == "search") {
|
||||
this.setup_search_view();
|
||||
} else { // "form"
|
||||
@@ -1578,7 +1710,7 @@ 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,[[["id", "in", self.initial_ids]]],
|
||||
self.view_list.do_search.call(self, domains.concat([[["id", "in", self.initial_ids]]]),
|
||||
contexts, groupbys);
|
||||
self.initial_ids = undefined;
|
||||
} else {
|
||||
@@ -1615,6 +1747,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
||||
return;
|
||||
var self = this;
|
||||
var wdataset = new openerp.base.DataSetSearch(this.session, this.model, this.context, this.domain);
|
||||
wdataset = this.options.parent_view;
|
||||
wdataset.create(data, function(r) {
|
||||
self.on_select_elements([r.result]);
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
* @param {Boolean} [options.selectable=true] determines whether view rows are selectable (e.g. via a checkbox)
|
||||
* @param {Boolean} [options.header=true] should the list's header be displayed
|
||||
* @param {Boolean} [options.deletable=true] are the list rows deletable
|
||||
* @param {null|String} [options.addable="New"] should the new-record button be displayed, and what should its label be. Use ``null`` to hide the button.
|
||||
* @param {void|String} [options.addable="New"] should the new-record button be displayed, and what should its label be. Use ``null`` to hide the button.
|
||||
* @param {Boolean} [options.sortable=true] is it possible to sort the table by clicking on column headers
|
||||
* @param {Boolean} [options.reorderable=true] is it possible to reorder list rows
|
||||
*
|
||||
@@ -232,7 +232,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
* If the index is null, ``switch_to_record`` asks for the creation of a
|
||||
* new record.
|
||||
*
|
||||
* @param {Number|null} index the record index (in the current dataset) to switch to
|
||||
* @param {Number|void} index the record index (in the current dataset) to switch to
|
||||
* @param {String} [view="form"] the view type to switch to
|
||||
*/
|
||||
select_record:function (index, view) {
|
||||
|
||||
@@ -18,7 +18,7 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
* Process an action
|
||||
* Supported actions: act_window
|
||||
*/
|
||||
do_action: function(action) {
|
||||
do_action: function(action, on_closed) {
|
||||
var self = this;
|
||||
action.flags = _.extend({
|
||||
sidebar : action.target != 'new',
|
||||
@@ -31,6 +31,9 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
// instantiate the right controllers by understanding the action
|
||||
switch (action.type) {
|
||||
case 'ir.actions.act_window':
|
||||
if (!action.target && this.dialog_stack.length) {
|
||||
action.flags.new_window = true;
|
||||
}
|
||||
if (action.target == 'new') {
|
||||
var element_id = _.uniqueId("act_window_dialog");
|
||||
$('<div>', {id: element_id}).dialog({
|
||||
@@ -44,6 +47,8 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
});
|
||||
var viewmanager = new openerp.base.ViewManagerAction(this.session, element_id, action);
|
||||
viewmanager.start();
|
||||
viewmanager.on_act_window_closed.add(on_closed);
|
||||
viewmanager.is_dialog = true;
|
||||
this.dialog_stack.push(viewmanager);
|
||||
} else if (action.flags.new_window) {
|
||||
action.flags.new_window = false;
|
||||
@@ -62,6 +67,9 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
break;
|
||||
case 'ir.actions.act_window_close':
|
||||
var dialog = this.dialog_stack.pop();
|
||||
if (!action.special) {
|
||||
dialog.on_act_window_closed();
|
||||
}
|
||||
dialog.$element.dialog('destroy');
|
||||
dialog.stop();
|
||||
break;
|
||||
@@ -84,6 +92,7 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
this.flags = this.flags || {};
|
||||
this.sidebar = new openerp.base.NullSidebar();
|
||||
this.registry = openerp.base.views;
|
||||
this.is_dialog = false;
|
||||
},
|
||||
/**
|
||||
* @returns {jQuery.Deferred} initial view loading promise
|
||||
@@ -126,17 +135,20 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
controller.set_embedded_view(view.embedded_view);
|
||||
}
|
||||
if (view_type === 'list' && this.flags.search_view === false && this.action && this.action['auto_search']) {
|
||||
// In case the search view is not instanciated: manually call ListView#search
|
||||
// In case the search view is not instantiated: manually call ListView#search
|
||||
var domains = !_(self.action.domain).isEmpty()
|
||||
? [self.action.domain] : [],
|
||||
contexts = !_(self.action.context).isEmpty()
|
||||
? [self.action.context] : [];
|
||||
controller.on_loaded.add({
|
||||
callback: function () {
|
||||
controller.do_search([self.action.domain], [self.action.context], []);
|
||||
controller.do_search(domains, contexts, []);
|
||||
},
|
||||
position: 'last',
|
||||
unique: true
|
||||
});
|
||||
}
|
||||
view_promise = controller.start();
|
||||
var self = this;
|
||||
$.when(view_promise).then(function() {
|
||||
self.on_controller_inited(view_type, controller);
|
||||
});
|
||||
@@ -157,12 +169,13 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
.filter('[data-view-type="' + view_type + '"]')
|
||||
.attr('disabled', true);
|
||||
|
||||
for (var i in this.views) {
|
||||
if (this.views[i].controller) {
|
||||
if (i === view_type) {
|
||||
$.when(view_promise).then(this.views[i].controller.do_show);
|
||||
for (var view_name in this.views) {
|
||||
if (!this.views.hasOwnProperty(view_name)) { continue; }
|
||||
if (this.views[view_name].controller) {
|
||||
if (view_name === view_type) {
|
||||
$.when(view_promise).then(this.views[view_name].controller.do_show);
|
||||
} else {
|
||||
this.views[i].controller.do_hide();
|
||||
this.views[view_name].controller.do_hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +210,11 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
});
|
||||
return this.searchview.start();
|
||||
},
|
||||
/**
|
||||
* Called when this view manager has been created by an action 'act_window@target=new' is closed
|
||||
*/
|
||||
on_act_window_closed : function() {
|
||||
},
|
||||
/**
|
||||
* Called when one of the view want to execute an action
|
||||
*/
|
||||
@@ -238,12 +256,14 @@ openerp.base.NullViewManager = openerp.base.generate_null_object_class(openerp.b
|
||||
openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
init: function(session, element_id, action) {
|
||||
var dataset;
|
||||
if(!action.res_id) {
|
||||
dataset = new openerp.base.DataSetSearch(session, action.res_model);
|
||||
if (!action.res_id) {
|
||||
dataset = new openerp.base.DataSetSearch(session, action.res_model, action.context || null);
|
||||
} else {
|
||||
dataset = new openerp.base.DataSetStatic(session, action.res_model);
|
||||
dataset.ids = [action.res_id];
|
||||
dataset.count = 1;
|
||||
dataset = new openerp.base.DataSetStatic(session, action.res_model, {}, [action.res_id]);
|
||||
if (action.context) {
|
||||
// TODO fme: should normalize all DataSets constructors to (session, model, context, ...)
|
||||
dataset.context = action.context;
|
||||
}
|
||||
}
|
||||
this._super(session, element_id, dataset, action.views);
|
||||
this.action = action;
|
||||
@@ -336,16 +356,12 @@ openerp.base.Sidebar = openerp.base.BaseWidget.extend({
|
||||
},
|
||||
do_refresh: function(new_view) {
|
||||
var view = this.view_manager.active_view;
|
||||
the_condition = this.sections.length > 0 && _.detect(this.sections,
|
||||
var the_condition = this.sections.length > 0 && _.detect(this.sections,
|
||||
function(x) {return x.elements.length > 0;}) != undefined
|
||||
&& (!new_view || view != 'list');
|
||||
if (!the_condition) {
|
||||
this.$element.addClass('closed-sidebar');
|
||||
this.$element.removeClass('open-sidebar');
|
||||
} else {
|
||||
this.$element.addClass('open-sidebar');
|
||||
this.$element.removeClass('closed-sidebar');
|
||||
}
|
||||
|
||||
this.$element.toggleClass('open-sidebar', the_condition)
|
||||
.toggleClass('closed-sidebar', !the_condition);
|
||||
|
||||
this.$element.html(QWeb.render("ViewManager.sidebar.internal", { sidebar: this, view: view }));
|
||||
|
||||
@@ -409,14 +425,17 @@ openerp.base.View = openerp.base.Controller.extend({
|
||||
* @param {Object} [record_id] the identifier of the object on which the action is to be applied
|
||||
* @param {Function} on_no_action callback to execute if the action does not generate any result (no new action)
|
||||
*/
|
||||
execute_action: function (action_data, dataset, action_manager, record_id, on_no_action) {
|
||||
execute_action: function (action_data, dataset, action_manager, record_id, on_no_action, on_closed) {
|
||||
var self = this;
|
||||
var handler = function (r) {
|
||||
var action = r.result;
|
||||
if (action && action.constructor == Object) {
|
||||
action.context = action.context || {};
|
||||
action.context['active_id'] = dataset.ids[dataset.index];
|
||||
action.context['active_ids'] = [dataset.ids[dataset.index]];
|
||||
action.context['active_model'] = dataset.model;
|
||||
_.extend(action.context, {
|
||||
active_id: record_id || false,
|
||||
active_ids: [record_id || false],
|
||||
active_model: dataset.model
|
||||
});
|
||||
action.flags = {
|
||||
sidebar : false,
|
||||
search_view : false,
|
||||
@@ -424,7 +443,12 @@ openerp.base.View = openerp.base.Controller.extend({
|
||||
action_buttons : false,
|
||||
pager : false
|
||||
};
|
||||
action_manager.do_action(action);
|
||||
action_manager.do_action(action, on_closed);
|
||||
if (self.view_manager.is_dialog && action.type != 'ir.actions.act_window_close') {
|
||||
handler({
|
||||
result : { type: 'ir.actions.act_window_close' }
|
||||
});
|
||||
}
|
||||
} else {
|
||||
on_no_action(action);
|
||||
}
|
||||
@@ -432,13 +456,13 @@ openerp.base.View = openerp.base.Controller.extend({
|
||||
|
||||
if (action_data.special) {
|
||||
handler({
|
||||
result : { type: 'ir.actions.act_window_close' }
|
||||
result : { type: 'ir.actions.act_window_close', special: action_data.special }
|
||||
});
|
||||
} else {
|
||||
var context = new openerp.base.CompoundContext(dataset.context).add(action_data.context || {});
|
||||
var context = new openerp.base.CompoundContext(dataset.context, action_data.context || {});
|
||||
switch(action_data.type) {
|
||||
case 'object':
|
||||
return dataset.call_and_eval(action_data.name, [[record_id], context], null, 1, handler);
|
||||
return dataset.call_button(action_data.name, [[record_id], context], handler);
|
||||
case 'action':
|
||||
return this.rpc('/base/action/load', { action_id: parseInt(action_data.name, 10), context: context }, handler);
|
||||
default:
|
||||
@@ -476,7 +500,7 @@ openerp.base.json_node_to_xml = function(node, single_quote, indent) {
|
||||
throw("Node a json node");
|
||||
}
|
||||
indent = indent || 0;
|
||||
var sindent = Array(indent + 1).join('\t'),
|
||||
var sindent = new Array(indent + 1).join('\t'),
|
||||
r = sindent + '<' + node.tag;
|
||||
for (var attr in node.attrs) {
|
||||
var vattr = node.attrs[attr];
|
||||
|
||||
@@ -468,6 +468,9 @@
|
||||
<t t-if="widget.string and widget.node.tag != 'label'">:</t>
|
||||
</label>
|
||||
</t>
|
||||
<t t-name="WidgetParagraph">
|
||||
<p class="oe_form_paragraph"><t t-esc="widget.string"/></p>
|
||||
</t>
|
||||
<t t-name="FieldChar">
|
||||
<input type="text"
|
||||
t-att-name="widget.name"
|
||||
|
||||
+46
-13
@@ -8,7 +8,7 @@ import binascii
|
||||
import hashlib
|
||||
import simplejson.encoder
|
||||
|
||||
__all__ = ['Domain', 'Context', 'NonLiteralEncoder, non_literal_decoder']
|
||||
__all__ = ['Domain', 'Context', 'NonLiteralEncoder, non_literal_decoder', 'CompoundDomain', 'CompoundContext']
|
||||
|
||||
#: 48 bits should be sufficient to have almost no chance of collision
|
||||
#: with a million hashes, according to hg@67081329d49a
|
||||
@@ -31,12 +31,14 @@ class NonLiteralEncoder(simplejson.encoder.JSONEncoder):
|
||||
elif isinstance(object, CompoundDomain):
|
||||
return {
|
||||
'__ref': 'compound_domain',
|
||||
'__domains': object.domains
|
||||
'__domains': object.domains,
|
||||
'__eval_context': object.get_eval_context()
|
||||
}
|
||||
elif isinstance(object, CompoundContext):
|
||||
return {
|
||||
'__ref': 'compound_context',
|
||||
'__contexts': object.contexts
|
||||
'__contexts': object.contexts,
|
||||
'__eval_context': object.get_eval_context()
|
||||
}
|
||||
raise TypeError('Could not encode unknown non-literal %s' % object)
|
||||
|
||||
@@ -61,12 +63,14 @@ def non_literal_decoder(dct):
|
||||
elif dct["__ref"] == "compound_domain":
|
||||
cdomain = CompoundDomain()
|
||||
for el in dct["__domains"]:
|
||||
cdomain.domains.append(non_literal_decoder(el))
|
||||
cdomain.domains.append(el)
|
||||
cdomain.set_eval_context(dct.get("__eval_context"))
|
||||
return cdomain
|
||||
elif dct["__ref"] == "compound_context":
|
||||
ccontext = CompoundContext()
|
||||
for el in dct["__contexts"]:
|
||||
ccontext.contexts.append(non_literal_decoder(el))
|
||||
ccontext.contexts.append(el)
|
||||
ccontext.set_eval_context(dct.get("__eval_context"))
|
||||
return ccontext
|
||||
return dct
|
||||
|
||||
@@ -121,7 +125,7 @@ class Domain(BaseDomain):
|
||||
ctx = self.session.evaluation_context(context)
|
||||
if self.own:
|
||||
ctx.update(self.own)
|
||||
return eval(self.get_domain_string(), ctx)
|
||||
return eval(self.get_domain_string(), SuperDict(ctx))
|
||||
|
||||
class Context(BaseContext):
|
||||
def __init__(self, session, context_string=None, key=None):
|
||||
@@ -167,12 +171,25 @@ class Context(BaseContext):
|
||||
if self.own:
|
||||
ctx.update(self.own)
|
||||
return eval(self.get_context_string(),
|
||||
ctx)
|
||||
SuperDict(ctx))
|
||||
|
||||
def SuperDict(dict):
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return self[name]
|
||||
except KeyError:
|
||||
raise AttributeError(name)
|
||||
def __getitem__(self, key):
|
||||
tmp = super(dict, self)[key]
|
||||
if isinstance(tmp, dict):
|
||||
return SuperDict(tmp)
|
||||
return tmp
|
||||
|
||||
class CompoundDomain(BaseDomain):
|
||||
def __init__(self, *domains):
|
||||
self.domains = []
|
||||
self.session = None
|
||||
self.eval_context = None
|
||||
for domain in domains:
|
||||
self.add(domain)
|
||||
|
||||
@@ -180,14 +197,15 @@ class CompoundDomain(BaseDomain):
|
||||
final_domain = []
|
||||
for domain in self.domains:
|
||||
if not isinstance(domain, (list, BaseDomain)):
|
||||
raise TypeError("Domain %r is not a list or a nonliteral Domain",
|
||||
domain)
|
||||
|
||||
raise TypeError(
|
||||
"Domain %r is not a list or a nonliteral Domain" % domain)
|
||||
|
||||
if isinstance(domain, list):
|
||||
final_domain.extend(domain)
|
||||
continue
|
||||
|
||||
ctx = dict(context or {})
|
||||
ctx.update(self.get_eval_context() or {})
|
||||
ctx['context'] = ctx
|
||||
|
||||
domain.session = self.session
|
||||
@@ -197,22 +215,31 @@ class CompoundDomain(BaseDomain):
|
||||
def add(self, domain):
|
||||
self.domains.append(domain)
|
||||
return self
|
||||
|
||||
def set_eval_context(self, eval_context):
|
||||
self.eval_context = eval_context
|
||||
return self
|
||||
|
||||
def get_eval_context(self):
|
||||
return self.eval_context
|
||||
|
||||
class CompoundContext(BaseContext):
|
||||
def __init__(self, *contexts):
|
||||
self.contexts = []
|
||||
self.eval_context = None
|
||||
self.session = None
|
||||
for context in contexts:
|
||||
self.add(context)
|
||||
|
||||
def evaluate(self, context=None):
|
||||
ctx = dict(context or {})
|
||||
ctx.update(self.get_eval_context() or {})
|
||||
final_context = {}
|
||||
for context_to_eval in self.contexts:
|
||||
if not isinstance(context_to_eval, (dict, BaseContext)):
|
||||
raise TypeError("Context %r is not a dict or a nonliteral Context",
|
||||
context_to_eval)
|
||||
|
||||
raise TypeError(
|
||||
"Context %r is not a dict or a nonliteral Context" % context_to_eval)
|
||||
|
||||
if isinstance(context_to_eval, dict):
|
||||
final_context.update(context_to_eval)
|
||||
continue
|
||||
@@ -227,4 +254,10 @@ class CompoundContext(BaseContext):
|
||||
def add(self, context):
|
||||
self.contexts.append(context)
|
||||
return self
|
||||
|
||||
def set_eval_context(self, eval_context):
|
||||
self.eval_context = eval_context
|
||||
return self
|
||||
|
||||
def get_eval_context(self):
|
||||
return self.eval_context
|
||||
|
||||
@@ -138,15 +138,13 @@ class OpenERPSession(object):
|
||||
"""
|
||||
assert self._uid, "The user needs to be logged-in to initialize his context"
|
||||
self.context = self.model('res.users').context_get(self.context)
|
||||
# set bin_size to True all the time
|
||||
self.context = self.context or {}
|
||||
self.context["bin_size"] = True
|
||||
|
||||
|
||||
self.client_timezone = self.context.get("tz", False)
|
||||
# invalid code, anyway we decided the server will be in UTC
|
||||
#if self.client_timezone:
|
||||
# self.remote_timezone = self.execute('common', 'timezone_get')
|
||||
|
||||
|
||||
self._locale = self.context.get('lang','en_US')
|
||||
lang_ids = self.execute('res.lang','search', [('code', '=', self._locale)])
|
||||
if lang_ids:
|
||||
@@ -203,7 +201,7 @@ class OpenERPSession(object):
|
||||
ctx['context'] = ctx
|
||||
|
||||
# adding the context of the session to send to the openerp server
|
||||
ccontext = nonliterals.CompoundContext(self.context, context_to_eval)
|
||||
ccontext = nonliterals.CompoundContext(self.context, context_to_eval or {})
|
||||
ccontext.session = self
|
||||
return ccontext.evaluate(ctx)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user