@@ -101,7 +101,8 @@ class Session(openerpweb.Controller):
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def sc_list(self, req):
|
||||
return req.session.model('ir.ui.view_sc').get_sc(req.session._uid, "ir.ui.menu", {})
|
||||
return req.session.model('ir.ui.view_sc').get_sc(req.session._uid, "ir.ui.menu",
|
||||
req.session.eval_context(req.context))
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get_databases_list(self, req):
|
||||
@@ -170,9 +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_contexts(contexts)
|
||||
domain = req.session.eval_domains(domains, context)
|
||||
|
||||
context = req.session.eval_context(openerpweb.nonliterals.CompoundContext(*contexts))
|
||||
domain = req.session.eval_domain(openerpweb.nonliterals.CompoundDomain(*(domains or [])), context)
|
||||
|
||||
group_by_sequence = []
|
||||
for candidate in (group_by_seq or []):
|
||||
ctx = req.session.eval_context(candidate, context)
|
||||
@@ -183,7 +184,7 @@ class Session(openerpweb.Controller):
|
||||
group_by_sequence.append(group_by)
|
||||
else:
|
||||
group_by_sequence.extend(group_by)
|
||||
|
||||
|
||||
return {
|
||||
'context': context,
|
||||
'domain': domain,
|
||||
@@ -230,8 +231,14 @@ class Session(openerpweb.Controller):
|
||||
return None
|
||||
return saved_actions["actions"].get(key)
|
||||
|
||||
def eval_context_and_domain(session, context, domain=None):
|
||||
e_context = session.eval_context(context)
|
||||
e_domain = session.eval_domain(domain or [], e_context)
|
||||
|
||||
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)
|
||||
|
||||
@@ -305,8 +312,9 @@ class Menu(openerpweb.Controller):
|
||||
Menus = req.session.model('ir.ui.menu')
|
||||
# menus are loaded fully unlike a regular tree view, cause there are
|
||||
# less than 512 items
|
||||
menu_ids = Menus.search([])
|
||||
menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'])
|
||||
context = req.session.eval_context(req.context)
|
||||
menu_ids = Menus.search([], 0, False, False, context)
|
||||
menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'], context)
|
||||
menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, '']}
|
||||
menu_items.append(menu_root)
|
||||
|
||||
@@ -331,8 +339,8 @@ class Menu(openerpweb.Controller):
|
||||
@openerpweb.jsonrequest
|
||||
def action(self, req, menu_id):
|
||||
actions = load_actions_from_ir_values(req,'action', 'tree_but_open',
|
||||
[('ir.ui.menu', menu_id)], False, {})
|
||||
|
||||
[('ir.ui.menu', menu_id)], False,
|
||||
req.session.eval_context(req.context))
|
||||
return {"action": actions}
|
||||
|
||||
class DataSet(openerpweb.Controller):
|
||||
@@ -340,7 +348,8 @@ class DataSet(openerpweb.Controller):
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def fields(self, req, model):
|
||||
return {'fields': req.session.model(model).fields_get()}
|
||||
return {'fields': req.session.model(model).fields_get(False,
|
||||
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):
|
||||
@@ -362,21 +371,23 @@ class DataSet(openerpweb.Controller):
|
||||
:rtype: list
|
||||
"""
|
||||
Model = request.session.model(model)
|
||||
|
||||
ids = Model.search(domain or [], offset or 0, limit or False,
|
||||
sort or False, request.context)
|
||||
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)
|
||||
|
||||
if fields and fields == ['id']:
|
||||
# shortcut read if we only want the ids
|
||||
return map(lambda id: {'id': id}, ids)
|
||||
|
||||
reads = Model.read(ids, fields or False, request.context)
|
||||
reads = Model.read(ids, fields or False, context)
|
||||
reads.sort(key=lambda obj: ids.index(obj['id']))
|
||||
return reads
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def read(self, request, model, ids, fields=False):
|
||||
return self.do_search_read(request, model, ids, fields)
|
||||
return self.do_search_read(request, model, ids, fields,
|
||||
request.session.eval_context(request.context))
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get(self, request, model, ids, fields=False):
|
||||
@@ -401,40 +412,48 @@ class DataSet(openerpweb.Controller):
|
||||
:rtype: list
|
||||
"""
|
||||
Model = request.session.model(model)
|
||||
records = Model.read(ids, fields, request.context)
|
||||
records = Model.read(ids, fields, request.session.eval_context(request.context))
|
||||
|
||||
record_map = dict((record['id'], record) for record in records)
|
||||
|
||||
return [record_map[id] for id in ids if record_map.get(id)]
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
|
||||
def load(self, req, model, id, fields):
|
||||
m = req.session.model(model)
|
||||
value = {}
|
||||
r = m.read([id])
|
||||
r = m.read([id], False, req.session.eval_context(req.context))
|
||||
if r:
|
||||
value = r[0]
|
||||
return {'value': value}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def create(self, req, model, data, context={}):
|
||||
def create(self, req, model, data):
|
||||
m = req.session.model(model)
|
||||
r = m.create(data, context)
|
||||
r = m.create(data, req.session.eval_context(req.context))
|
||||
return {'result': r}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def save(self, req, model, id, data, context={}):
|
||||
def save(self, req, model, id, data):
|
||||
m = req.session.model(model)
|
||||
r = m.write([id], data, context)
|
||||
r = m.write([id], data, req.session.eval_context(req.context))
|
||||
return {'result': r}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def unlink(self, request, model, ids=[]):
|
||||
Model = request.session.model(model)
|
||||
return Model.unlink(ids)
|
||||
return Model.unlink(ids, request.session.eval_context(request.context))
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def call(self, req, model, method, args):
|
||||
def call(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):
|
||||
args[domain_id] = d
|
||||
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}
|
||||
@@ -445,9 +464,9 @@ class DataSet(openerpweb.Controller):
|
||||
return {'result': r}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def default_get(self, req, model, fields, context={}):
|
||||
def default_get(self, req, model, fields):
|
||||
m = req.session.model(model)
|
||||
r = m.default_get(fields, context)
|
||||
r = m.default_get(fields, req.session.eval_context(req.context))
|
||||
return {'result': r}
|
||||
|
||||
class DataGroup(openerpweb.Controller):
|
||||
@@ -455,10 +474,11 @@ class DataGroup(openerpweb.Controller):
|
||||
@openerpweb.jsonrequest
|
||||
def read(self, request, model, group_by_fields, domain=None):
|
||||
Model = request.session.model(model)
|
||||
context, domain = eval_context_and_domain(request.session, request.context, domain)
|
||||
|
||||
return Model.read_group(
|
||||
domain or [], False, group_by_fields, 0, False,
|
||||
dict(request.context, group_by=group_by_fields))
|
||||
dict(context, group_by=group_by_fields))
|
||||
|
||||
class View(openerpweb.Controller):
|
||||
_cp_path = "/base/view"
|
||||
@@ -466,9 +486,10 @@ class View(openerpweb.Controller):
|
||||
def fields_view_get(self, request, model, view_id, view_type,
|
||||
transform=True, toolbar=False, submenu=False):
|
||||
Model = request.session.model(model)
|
||||
fvg = Model.fields_view_get(view_id, view_type, request.context,
|
||||
toolbar, submenu)
|
||||
self.process_view(request.session, fvg, request.context, transform)
|
||||
context = request.session.eval_context(request.context)
|
||||
fvg = Model.fields_view_get(view_id, view_type, context, toolbar, submenu)
|
||||
# todo fme?: check that we should pass the evaluated context here
|
||||
self.process_view(request.session, fvg, context, transform)
|
||||
return fvg
|
||||
|
||||
def process_view(self, session, fvg, context, transform):
|
||||
@@ -490,18 +511,20 @@ class View(openerpweb.Controller):
|
||||
'user_id': request.session._uid,
|
||||
'ref_id': view_id,
|
||||
'arch': arch
|
||||
})
|
||||
}, request.session.eval_context(request.context))
|
||||
return {'result': True}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def undo_custom(self, request, view_id, reset=False):
|
||||
CustomView = request.session.model('ir.ui.view.custom')
|
||||
vcustom = CustomView.search([('user_id', '=', request.session._uid), ('ref_id' ,'=', view_id)])
|
||||
context = request.session.eval_context(request.context)
|
||||
vcustom = CustomView.search([('user_id', '=', request.session._uid), ('ref_id' ,'=', view_id)],
|
||||
0, False, False, context)
|
||||
if vcustom:
|
||||
if reset:
|
||||
CustomView.unlink(vcustom)
|
||||
CustomView.unlink(vcustom, context)
|
||||
else:
|
||||
CustomView.unlink([vcustom[0]])
|
||||
CustomView.unlink([vcustom[0]], context)
|
||||
return {'result': True}
|
||||
return {'result': False}
|
||||
|
||||
@@ -638,7 +661,7 @@ class SearchView(View):
|
||||
@openerpweb.jsonrequest
|
||||
def fields_get(self, req, model):
|
||||
Model = req.session.model(model)
|
||||
fields = Model.fields_get()
|
||||
fields = Model.fields_get(False, req.session.eval_context(req.context))
|
||||
return {'fields': fields}
|
||||
|
||||
class Binary(openerpweb.Controller):
|
||||
@@ -648,11 +671,12 @@ class Binary(openerpweb.Controller):
|
||||
def image(self, request, session_id, model, id, field, **kw):
|
||||
cherrypy.response.headers['Content-Type'] = 'image/png'
|
||||
Model = request.session.model(model)
|
||||
context = request.session.eval_context(request.context)
|
||||
try:
|
||||
if not id:
|
||||
res = Model.default_get([field], request.context).get(field, '')
|
||||
res = Model.default_get([field], context).get(field, '')
|
||||
else:
|
||||
res = Model.read([int(id)], [field], request.context)[0].get(field, '')
|
||||
res = Model.read([int(id)], [field], context)[0].get(field, '')
|
||||
return base64.decodestring(res)
|
||||
except: # TODO: what's the exception here?
|
||||
return self.placeholder()
|
||||
@@ -662,7 +686,8 @@ class Binary(openerpweb.Controller):
|
||||
@openerpweb.httprequest
|
||||
def saveas(self, request, session_id, model, id, field, fieldname, **kw):
|
||||
Model = request.session.model(model)
|
||||
res = Model.read([int(id)], [field, fieldname])[0]
|
||||
context = request.session.eval_context(request.context)
|
||||
res = Model.read([int(id)], [field, fieldname], context)[0]
|
||||
filecontent = res.get(field, '')
|
||||
if not filecontent:
|
||||
raise cherrypy.NotFound
|
||||
@@ -704,6 +729,7 @@ class Binary(openerpweb.Controller):
|
||||
@openerpweb.httprequest
|
||||
def upload_attachment(self, request, session_id, callback, model, id, ufile=None):
|
||||
cherrypy.response.timeout = 500
|
||||
context = request.session.eval_context(request.context)
|
||||
Model = request.session.model('ir.attachment')
|
||||
try:
|
||||
out = """<script language="javascript" type="text/javascript">
|
||||
@@ -718,7 +744,7 @@ class Binary(openerpweb.Controller):
|
||||
'datas': base64.encodestring(ufile.file.read()),
|
||||
'res_model': model,
|
||||
'res_id': int(id)
|
||||
})
|
||||
}, context)
|
||||
args = {
|
||||
'filename': ufile.filename,
|
||||
'id': attachment_id
|
||||
@@ -734,9 +760,12 @@ class Action(openerpweb.Controller):
|
||||
def load(self, req, action_id):
|
||||
Actions = req.session.model('ir.actions.actions')
|
||||
value = False
|
||||
action_type = Actions.read([action_id], ['type'], req.session.context)
|
||||
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, req.session.context)
|
||||
action = req.session.model(action_type[0]['type']).read([action_id], False,
|
||||
context)
|
||||
if action:
|
||||
value = clean_action(action[0], req.session)
|
||||
return {'result': value}
|
||||
|
||||
@@ -199,6 +199,8 @@ background: linear-gradient(top, #bd5e54 0%,#90322a 60%); /* W3C */
|
||||
line-height: 20px;
|
||||
font-weight: bold;
|
||||
font-size: 85%;
|
||||
|
||||
white-space: nowrap;
|
||||
}
|
||||
.openerp .menu a:hover,
|
||||
.openerp .menu a:focus,
|
||||
@@ -696,6 +698,9 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,
|
||||
.openerp td.oe_form_frame_cell {
|
||||
padding: 2px;
|
||||
}
|
||||
.openerp td.oe_form_frame_cell.oe_form_group {
|
||||
padding: 0px;
|
||||
}
|
||||
.openerp .required.error {
|
||||
border: 1px solid #900;
|
||||
}
|
||||
@@ -712,7 +717,7 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,
|
||||
.openerp label.oe_form_label, .openerp label.oe_form_label_help {
|
||||
display: block;
|
||||
text-align: right;
|
||||
margin-top: 3px;
|
||||
margin: 3px 0 0 10px;
|
||||
}
|
||||
.openerp label.oe_form_label_help span {
|
||||
font-size: 80%;
|
||||
@@ -788,7 +793,8 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,
|
||||
.openerp .separator.horizontal {
|
||||
font-weight: bold;
|
||||
border-bottom-width: 1px;
|
||||
margin: 6px 4px 6px 1px;
|
||||
margin: 3px 4px 3px 1px;
|
||||
height: 15px;
|
||||
}
|
||||
.openerp td.required input, .openerp td.required select {
|
||||
background-color: #D2D2FF;
|
||||
|
||||
@@ -144,6 +144,9 @@ openerp.base = function(instance) {
|
||||
if (openerp.base.form) {
|
||||
openerp.base.form(instance);
|
||||
}
|
||||
if (openerp.base.list && openerp.base.list.editable) {
|
||||
openerp.base.list.editable(instance);
|
||||
}
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
||||
@@ -334,9 +334,6 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
// 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;
|
||||
if (!params.context.bin_size) {
|
||||
params.context.bin_size = true;
|
||||
}
|
||||
|
||||
// Use a default error handler unless defined
|
||||
error_callback = typeof(error_callback) != "undefined" ? error_callback : this.on_rpc_error;
|
||||
@@ -737,6 +734,66 @@ openerp.base.BaseWidget = openerp.base.Controller.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Dialog = openerp.base.BaseWidget.extend({
|
||||
dialog_title: "",
|
||||
identifier_prefix: 'dialog',
|
||||
init: function (session, options) {
|
||||
this._super(null, session);
|
||||
options = _.extend({
|
||||
modal: true,
|
||||
title: this.dialog_title,
|
||||
width: '700px',
|
||||
min_width: 0,
|
||||
max_width: '100%',
|
||||
height: '500px',
|
||||
min_height: 0,
|
||||
max_height: '100%',
|
||||
buttons: {}
|
||||
}, options);
|
||||
|
||||
options.width = this.get_width(options.width);
|
||||
options.min_width = this.get_width(options.min_width);
|
||||
options.max_width = this.get_width(options.max_width);
|
||||
options.height = this.get_height(options.height);
|
||||
options.min_height = this.get_height(options.min_height);
|
||||
options.max_height = this.get_height(options.max_height);
|
||||
|
||||
if (options.width > options.max_width) options.width = options.max_width;
|
||||
if (options.width < options.min_width) options.width = options.min_width;
|
||||
if (options.height > options.max_height) options.height = options.max_height;
|
||||
if (options.height < options.min_height) options.height = options.min_height;
|
||||
|
||||
for (var f in this) {
|
||||
if (f.substr(0, 10) == 'on_button_') {
|
||||
options.buttons[f.substr(10)] = this[f];
|
||||
}
|
||||
}
|
||||
this.options = options;
|
||||
},
|
||||
get_width: function(val) {
|
||||
return this.get_size(val.toString(), $(window.top).width());
|
||||
},
|
||||
get_height: function(val) {
|
||||
return this.get_size(val.toString(), $(window.top).height());
|
||||
},
|
||||
get_size: function(val, available_size) {
|
||||
if (val == 'auto') {
|
||||
return val;
|
||||
} else if (val.slice(-1) == "%") {
|
||||
return Math.round(available_size / 100 * parseInt(val.slice(0, -1), 10));
|
||||
} else {
|
||||
return parseInt(val, 10);
|
||||
}
|
||||
},
|
||||
start: function () {
|
||||
this.$dialog = $('<div id="' + this.element_id + '"></div>').dialog(this.options);
|
||||
this._super();
|
||||
},
|
||||
stop: function () {
|
||||
this.$dialog("destroy").remove();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.CrashManager = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
|
||||
@@ -231,10 +231,10 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
* @param {openerp.base.Session} session current OpenERP session
|
||||
* @param {String} model the OpenERP model this dataset will manage
|
||||
*/
|
||||
init: function(session, model) {
|
||||
init: function(session, model, context) {
|
||||
this._super(session);
|
||||
this.model = model;
|
||||
this.context = {};
|
||||
this.context = context || {};
|
||||
this.index = 0;
|
||||
this.count = 0;
|
||||
},
|
||||
@@ -320,13 +320,22 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
call_and_eval: function (method, args, domain_id, context_id, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/call', {
|
||||
model: this.model,
|
||||
method: method,
|
||||
domain_id: domain_id || null,
|
||||
context_id: context_id || null,
|
||||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Arguments:
|
||||
* name='', args=None, operator='ilike', context=None, limit=100
|
||||
* name='', args=[], operator='ilike', context=None, limit=100
|
||||
*/
|
||||
name_search: function (args, callback, error_callback) {
|
||||
return this.call('name_search',
|
||||
args,
|
||||
return this.call_and_eval('name_search',
|
||||
args, 1, 3,
|
||||
callback, error_callback);
|
||||
},
|
||||
exec_workflow: function (id, signal, callback) {
|
||||
@@ -362,9 +371,9 @@ openerp.base.DataSetStatic = openerp.base.DataSet.extend({
|
||||
});
|
||||
|
||||
openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
||||
init: function(session, model) {
|
||||
this._super(session, model);
|
||||
this.domain = [];
|
||||
init: function(session, model, context, domain) {
|
||||
this._super(session, model, context);
|
||||
this.domain = domain || [];
|
||||
this._sort = [];
|
||||
this.offset = 0;
|
||||
// subset records[offset:offset+limit]
|
||||
@@ -431,6 +440,37 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.CompoundContext = function() {
|
||||
this.__ref = "compound_context";
|
||||
this.__contexts = [];
|
||||
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);
|
||||
return this;
|
||||
};
|
||||
|
||||
openerp.base.CompoundDomain = function() {
|
||||
this.__ref = "compound_domain";
|
||||
this.__domains = [];
|
||||
_.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);
|
||||
return this;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
||||
@@ -32,8 +32,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.ready = false;
|
||||
this.show_invalid = true;
|
||||
this.touched = false;
|
||||
this.flags = this.view_manager.action.flags || {};
|
||||
this.flags = this.view_manager.flags || {};
|
||||
this.registry = openerp.base.form.widgets;
|
||||
this.has_been_loaded = $.Deferred();
|
||||
},
|
||||
start: function() {
|
||||
//this.log('Starting FormView '+this.model+this.view_id)
|
||||
@@ -47,7 +48,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
on_loaded: function(data) {
|
||||
var self = this;
|
||||
this.fields_view = data.fields_view;
|
||||
|
||||
var frame = new (this.registry.get_object('frame'))(this, this.fields_view.arch);
|
||||
|
||||
this.$element.html(QWeb.render(this.template, { 'frame': frame, 'view': this }));
|
||||
@@ -65,6 +65,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.$element.find('#' + this.element_id + '_header button.oe_form_button_new').click(this.on_button_new);
|
||||
|
||||
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar);
|
||||
this.has_been_loaded.resolve();
|
||||
},
|
||||
do_show: function () {
|
||||
var self = this;
|
||||
@@ -176,7 +177,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
return this.rpc(ajax, {
|
||||
model: this.dataset.model,
|
||||
method: method,
|
||||
args: [].concat([(this.datarecord.id == null ? [] : [this.datarecord.id])], args)
|
||||
args: [(this.datarecord.id == null ? [] : [this.datarecord.id])].concat(args)
|
||||
}, function(response) {
|
||||
self.on_processed_onchange(response, processed);
|
||||
});
|
||||
@@ -222,8 +223,10 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
},
|
||||
on_button_new: function() {
|
||||
var self = this;
|
||||
this.dataset.default_get(_.keys(this.fields), function(result) {
|
||||
self.on_record_loaded(result.result);
|
||||
$.when(this.has_been_loaded).then(function() {
|
||||
self.dataset.default_get(_.keys(self.fields_view.fields), function(result) {
|
||||
self.on_record_loaded(result.result);
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -1013,6 +1016,18 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({
|
||||
});
|
||||
})(null);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
@@ -1048,7 +1063,8 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
"type":"ir.actions.act_window",
|
||||
"view_type":"form",
|
||||
"view_mode":"form",
|
||||
"target":"new"
|
||||
"target":"new",
|
||||
"context": build_relation_context(self)
|
||||
});
|
||||
};
|
||||
var cmenu = this.$menu_btn.contextMenu(this.cm_id, {'leftClickToo': true,
|
||||
@@ -1125,23 +1141,26 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, []);
|
||||
|
||||
dataset.name_search([search_val, false, 'ilike', {}, this.limit + 1], function(data) {
|
||||
dataset.name_search([search_val, self.field.domain || [], 'ilike',
|
||||
build_relation_context(self), this.limit + 1], function(data) {
|
||||
self.last_search = data.result;
|
||||
// possible selections for the m2o
|
||||
var values = _.map(data.result, function(x) {
|
||||
return {label: $('<span />').text(x[1]).html(), name:x[1], id:x[0]};
|
||||
});
|
||||
|
||||
// additional selections, actions that open popup
|
||||
// search more... if more results that max
|
||||
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, false, 'ilike', {}, false], function(data) {
|
||||
dataset.name_search([search_val, self.field.domain || [], 'ilike',
|
||||
build_relation_context(self), false], function(data) {
|
||||
self._change_int_value(null);
|
||||
self._search_create_popup("search", data.result);
|
||||
});
|
||||
}});
|
||||
}
|
||||
// quick create
|
||||
var raw_result = _(data.result).map(function(x) {return x[1];})
|
||||
if (search_val.length > 0 &&
|
||||
!_.include(raw_result, search_val) &&
|
||||
@@ -1151,6 +1170,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
self._quick_create(search_val);
|
||||
}});
|
||||
}
|
||||
// create...
|
||||
values.push({label: "<em> Create and Edit...</em>", action: function() {
|
||||
self._change_int_value(null);
|
||||
self._search_create_popup("form");
|
||||
@@ -1162,21 +1182,26 @@ 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, {}], function(data) {
|
||||
dataset.call("name_create", [name, build_relation_context(self)], function(data) {
|
||||
self._change_int_ext_value(data.result);
|
||||
}, function(a, b) {
|
||||
self._change_int_value(null);
|
||||
self._search_create_popup("form");
|
||||
self._search_create_popup("form", undefined, {"default_name": name});
|
||||
});
|
||||
},
|
||||
// all search/create popup handling
|
||||
_search_create_popup: function(view, ids) {
|
||||
_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.Many2XSelectPopup(null, self.view.session);
|
||||
pop.select_element(self.field.relation, ids ? _.map(ids, function(x) {return x[0]}) : undefined, view);
|
||||
pop.on_select_element.add(function(element_id) {
|
||||
dataset.call("name_get", [element_id], function(data) {
|
||||
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 || {}));
|
||||
pop.on_select_elements.add(function(element_ids) {
|
||||
dataset.call("name_get", [element_ids[0]], function(data) {
|
||||
self._change_int_ext_value(data.result[0]);
|
||||
pop.stop();
|
||||
});
|
||||
@@ -1227,29 +1252,38 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
|
||||
this.dataset = new openerp.base.DataSetStatic(this.session, this.field.relation);
|
||||
this.dataset.on_unlink.add_last(function(ids) {
|
||||
// TODO niv check form view
|
||||
var view = self.viewmanager.views[self.viewmanager.active_view].controller;
|
||||
view.reload_content();
|
||||
// TODO niv make real suppression (list or direct)
|
||||
self.dataset.set_ids(_.without.apply(_, [self.dataset.ids].concat(ids)));
|
||||
self.on_ui_change();
|
||||
self.reload_current_view();
|
||||
});
|
||||
|
||||
var modes = this.node.attrs.mode;
|
||||
modes = !!modes ? modes.split(",") : ["tree", "form"];
|
||||
var views = [];
|
||||
_.each(modes, function(mode) {
|
||||
var view = [false, mode == "tree" ? "list" : mode];
|
||||
var view = {view_id: false, view_type: mode == "tree" ? "list" : mode};
|
||||
if (self.field.views && self.field.views[mode]) {
|
||||
view.push(self.field.views[mode]);
|
||||
view.embedded_view = self.field.views[mode];
|
||||
}
|
||||
if(view.view_type === "list") {
|
||||
view.options = {
|
||||
};
|
||||
}
|
||||
views.push(view);
|
||||
});
|
||||
this.views = views;
|
||||
|
||||
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.on_controller_inited.add_last(function(view_type, controller) {
|
||||
if (view_type == "list") {
|
||||
// TODO niv
|
||||
controller.o2m = self;
|
||||
} else if (view_type == "form") {
|
||||
// TODO niv
|
||||
}
|
||||
@@ -1265,6 +1299,15 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
// TODO niv: handle other types of views
|
||||
});
|
||||
},
|
||||
reload_current_view: function() {
|
||||
var self = this;
|
||||
var view = self.viewmanager.views[self.viewmanager.active_view].controller;
|
||||
if(self.viewmanager.active_view === "list") {
|
||||
view.reload_content();
|
||||
} else if (self.viewmanager.active_view === "form") {
|
||||
// TODO niv: but fme did not implemented delete in form view anyway
|
||||
}
|
||||
},
|
||||
set_value: function(value) {
|
||||
if(value != false) {
|
||||
this.dataset.set_ids(value);
|
||||
@@ -1277,6 +1320,24 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.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
|
||||
});
|
||||
pop.on_select_elements.add(function(element_ids) {
|
||||
var ids = self.o2m.dataset.ids;
|
||||
_.each(element_ids, function(x) {if (!_.include(ids, x)) ids.push(x);});
|
||||
self.o2m.dataset.set_ids(ids);
|
||||
self.o2m.on_ui_change();
|
||||
self.o2m.reload_current_view();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
@@ -1300,14 +1361,13 @@ 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, {
|
||||
'selectable': false,
|
||||
'addable': 'Add'
|
||||
});
|
||||
this.list_view.m2m_field = this;
|
||||
this.list_view.start();
|
||||
this.list_view.on_loaded.add_last(function() {
|
||||
self.is_started.resolve();
|
||||
});
|
||||
this.list_view.start();
|
||||
$.when(this.is_started, this.is_setted).then(function() {
|
||||
self.list_view.reload_content();
|
||||
});
|
||||
@@ -1325,15 +1385,17 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
||||
|
||||
openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
||||
do_add_record: function () {
|
||||
var pop = new openerp.base.form.Many2XSelectPopup(
|
||||
var pop = new openerp.base.form.SelectCreatePopup(
|
||||
null, this.m2m_field.view.session);
|
||||
pop.select_element(this.model);
|
||||
var self = this;
|
||||
pop.on_select_element.add(function(element_id) {
|
||||
if(! _.detect(self.dataset.ids, function(x) {return x == element_id;})) {
|
||||
self.dataset.set_ids([].concat(self.dataset.ids, [element_id]));
|
||||
self.reload_content();
|
||||
}
|
||||
pop.on_select_elements.add(function(element_ids) {
|
||||
_.each(element_ids, function(element_id) {
|
||||
if(! _.detect(self.dataset.ids, function(x) {return x == element_id;})) {
|
||||
self.dataset.set_ids([].concat(self.dataset.ids, [element_id]));
|
||||
self.reload_content();
|
||||
}
|
||||
});
|
||||
pop.stop();
|
||||
});
|
||||
},
|
||||
@@ -1350,13 +1412,22 @@ openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.Many2XSelectPopup = openerp.base.BaseWidget.extend({
|
||||
identifier_prefix: "many2xselectpopup",
|
||||
template: "Many2XSelectPopup",
|
||||
select_element: function(model, initial_ids, initial_view) {
|
||||
openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
||||
identifier_prefix: "selectcreatepopup",
|
||||
template: "SelectCreatePopup",
|
||||
/**
|
||||
* options:
|
||||
* - initial_ids
|
||||
* - initial_view: form or search (default search)
|
||||
* - disable_multiple_selection
|
||||
* - alternative_form_view
|
||||
*/
|
||||
select_element: function(model, options, domain, context) {
|
||||
this.model = model;
|
||||
this.initial_ids = initial_ids;
|
||||
this.initial_view = initial_view || "search";
|
||||
this.domain = domain || [];
|
||||
this.context = context || {};
|
||||
this.options = options || {};
|
||||
this.initial_ids = this.options.initial_ids;
|
||||
jQuery(this.render()).dialog({title: '',
|
||||
modal: true,
|
||||
minWidth: 800});
|
||||
@@ -1364,8 +1435,9 @@ openerp.base.form.Many2XSelectPopup = openerp.base.BaseWidget.extend({
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
this.dataset = new openerp.base.DataSetSearch(this.session, this.model);
|
||||
if (this.initial_view == "search") {
|
||||
this.dataset = new openerp.base.DataSetSearch(this.session, this.model,
|
||||
this.context, this.domain);
|
||||
if ((this.options.initial_view || "search") == "search") {
|
||||
this.setup_search_view();
|
||||
} else { // "form"
|
||||
this.new_object();
|
||||
@@ -1377,10 +1449,14 @@ openerp.base.form.Many2XSelectPopup = openerp.base.BaseWidget.extend({
|
||||
this.searchview.stop();
|
||||
}
|
||||
this.searchview = new openerp.base.SearchView(null, this.session,
|
||||
this.element_id + "_search", this.dataset, false, {});
|
||||
this.element_id + "_search", this.dataset, false, {
|
||||
"selectable": !this.options.disable_multiple_selection,
|
||||
"deletable": false
|
||||
});
|
||||
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]]], contexts, groupbys);
|
||||
self.view_list.do_search.call(self,[[["id", "in", self.initial_ids]]],
|
||||
contexts, groupbys);
|
||||
self.initial_ids = undefined;
|
||||
} else {
|
||||
self.view_list.do_search.call(self, domains, contexts, groupbys);
|
||||
@@ -1388,15 +1464,18 @@ openerp.base.form.Many2XSelectPopup = openerp.base.BaseWidget.extend({
|
||||
});
|
||||
this.searchview.on_loaded.add_last(function () {
|
||||
var $buttons = self.searchview.$element.find(".oe_search-view-buttons");
|
||||
$buttons.append(QWeb.render("Many2XSelectPopup.search.buttons"));
|
||||
var $nbutton = $buttons.find(".oe_many2xselectpopup-search-new");
|
||||
$nbutton.click(function() {
|
||||
self.new_object();
|
||||
});
|
||||
var $cbutton = $buttons.find(".oe_many2xselectpopup-search-close");
|
||||
$buttons.append(QWeb.render("SelectCreatePopup.search.buttons"));
|
||||
var $cbutton = $buttons.find(".oe_selectcreatepopup-search-close");
|
||||
$cbutton.click(function() {
|
||||
self.stop();
|
||||
});
|
||||
var $sbutton = $buttons.find(".oe_selectcreatepopup-search-select");
|
||||
if(self.options.disable_multiple_selection) {
|
||||
$sbutton.hide();
|
||||
}
|
||||
$sbutton.click(function() {
|
||||
self.on_select_elements(self.selected_ids);
|
||||
});
|
||||
self.view_list = new openerp.base.form.Many2XPopupListView( null, self.session,
|
||||
self.element_id + "_view_list", self.dataset, false,
|
||||
{'deletable': false});
|
||||
@@ -1408,7 +1487,15 @@ openerp.base.form.Many2XSelectPopup = openerp.base.BaseWidget.extend({
|
||||
});
|
||||
this.searchview.start();
|
||||
},
|
||||
on_select_element: function(element_id) {
|
||||
on_select_elements: function(element_ids) {
|
||||
},
|
||||
on_click_element: function(ids) {
|
||||
this.selected_ids = ids || [];
|
||||
if(this.selected_ids.length > 0) {
|
||||
this.$element.find(".oe_selectcreatepopup-search-select").removeAttr('disabled');
|
||||
} else {
|
||||
this.$element.find(".oe_selectcreatepopup-search-select").attr('disabled', "disabled");
|
||||
}
|
||||
},
|
||||
new_object: function() {
|
||||
var self = this;
|
||||
@@ -1421,15 +1508,18 @@ openerp.base.form.Many2XSelectPopup = openerp.base.BaseWidget.extend({
|
||||
this.dataset.index = null;
|
||||
this.view_form = new openerp.base.FormView(null, this.session,
|
||||
this.element_id + "_view_form", this.dataset, false);
|
||||
if (this.options.alternative_form_view) {
|
||||
this.view_form.set_embedded_view(this.options.alternative_form_view);
|
||||
}
|
||||
this.view_form.start();
|
||||
this.view_form.on_loaded.add_last(function() {
|
||||
var $buttons = self.view_form.$element.find(".oe_form_buttons");
|
||||
$buttons.html(QWeb.render("Many2XSelectPopup.form.buttons"));
|
||||
var $nbutton = $buttons.find(".oe_many2xselectpopup-form-save");
|
||||
$buttons.html(QWeb.render("SelectCreatePopup.form.buttons"));
|
||||
var $nbutton = $buttons.find(".oe_selectcreatepopup-form-save");
|
||||
$nbutton.click(function() {
|
||||
self.view_form.do_save();
|
||||
});
|
||||
var $cbutton = $buttons.find(".oe_many2xselectpopup-form-close");
|
||||
var $cbutton = $buttons.find(".oe_selectcreatepopup-form-close");
|
||||
$cbutton.click(function() {
|
||||
self.stop();
|
||||
});
|
||||
@@ -1437,7 +1527,7 @@ openerp.base.form.Many2XSelectPopup = openerp.base.BaseWidget.extend({
|
||||
this.view_form.on_created.add_last(function(r, success) {
|
||||
if (r.result) {
|
||||
var id = arguments[0].result;
|
||||
self.on_select_element(id);
|
||||
self.on_select_elements([id]);
|
||||
}
|
||||
});
|
||||
this.view_form.do_show();
|
||||
@@ -1445,8 +1535,15 @@ openerp.base.form.Many2XSelectPopup = openerp.base.BaseWidget.extend({
|
||||
});
|
||||
|
||||
openerp.base.form.Many2XPopupListView = openerp.base.ListView.extend({
|
||||
do_add_record: function () {
|
||||
this.popup.new_object();
|
||||
},
|
||||
select_record: function(index) {
|
||||
this.popup.on_select_element(this.dataset.ids[index]);
|
||||
this.popup.on_select_elements([this.dataset.ids[index]]);
|
||||
},
|
||||
do_select: function(ids, records) {
|
||||
this._super(ids, records);
|
||||
this.popup.on_click_element(ids);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -78,10 +78,12 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
this.dataset = dataset;
|
||||
this.searchview = null;
|
||||
this.active_view = null;
|
||||
this.views_src = views;
|
||||
this.views_src = _.map(views, function(x)
|
||||
{return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
|
||||
this.views = {};
|
||||
this.flags = this.flags || {};
|
||||
this.sidebar = new openerp.base.NullSidebar();
|
||||
this.registry = openerp.base.views;
|
||||
},
|
||||
/**
|
||||
* @returns {jQuery.Deferred} initial view loading promise
|
||||
@@ -94,14 +96,13 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
self.on_mode_switch($(this).data('view-type'));
|
||||
});
|
||||
_.each(this.views_src, function(view) {
|
||||
self.views[view[1]] = { view_id: view[0], controller: null,
|
||||
embedded_view: view[2]};
|
||||
self.views[view.view_type] = $.extend({}, view, {controller: null});
|
||||
});
|
||||
if (this.flags.views_switcher === false) {
|
||||
this.$element.find('.oe_vm_switch').hide();
|
||||
}
|
||||
// switch to the first one in sequence
|
||||
return this.on_mode_switch(this.views_src[0][1]);
|
||||
return this.on_mode_switch(this.views_src[0].view_type);
|
||||
},
|
||||
stop: function() {
|
||||
},
|
||||
@@ -117,8 +118,9 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
var view = this.views[view_type];
|
||||
if (!view.controller) {
|
||||
// Lazy loading of views
|
||||
var controllerclass = openerp.base.views.get_object(view_type);
|
||||
var controller = new controllerclass( this, this.session, this.element_id + "_view_" + view_type, this.dataset, view.view_id);
|
||||
var controllerclass = this.registry.get_object(view_type);
|
||||
var controller = new controllerclass( this, this.session, this.element_id + "_view_" + view_type,
|
||||
this.dataset, view.view_id, view.options);
|
||||
if (view.embedded_view) {
|
||||
controller.set_embedded_view(view.embedded_view);
|
||||
}
|
||||
|
||||
@@ -232,14 +232,14 @@
|
||||
<!-- TODO prefix id with the element_id of the controller t-attf-id="#{prefix}_localid" -->
|
||||
<div class="oe_vm_switch">
|
||||
<t t-if="views.length != 1" t-foreach="views" t-as="view">
|
||||
<button type="button" t-att-data-view-type="view[1]">
|
||||
<t t-esc="view[1]"/>
|
||||
<button type="button" t-att-data-view-type="view.view_type">
|
||||
<t t-esc="view.view_type"/>
|
||||
</button>
|
||||
</t>
|
||||
</div>
|
||||
<div t-attf-id="#{prefix}_search" t-opentag="true"/>
|
||||
<t t-foreach="views" t-as="view">
|
||||
<div t-attf-id="#{prefix}_view_#{view[1]}"/>
|
||||
<div t-attf-id="#{prefix}_view_#{view.view_type}"/>
|
||||
</t>
|
||||
</td>
|
||||
<td class="view-manager-main-sidebar" height="100%">
|
||||
@@ -877,20 +877,20 @@
|
||||
</p>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="Many2XSelectPopup">
|
||||
<t t-name="SelectCreatePopup">
|
||||
<div t-att-id="element_id">
|
||||
<div t-att-id="element_id + '_search'"></div>
|
||||
<div t-att-id="element_id + '_view_list'"></div>
|
||||
<div t-att-id="element_id + '_view_form'"></div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="Many2XSelectPopup.search.buttons">
|
||||
<button type="button" class="oe_many2xselectpopup-search-new">New</button>
|
||||
<button type="button" class="oe_many2xselectpopup-search-close">Close</button>
|
||||
<t t-name="SelectCreatePopup.search.buttons">
|
||||
<button type="button" class="oe_selectcreatepopup-search-select" disabled="disabled">Select</button>
|
||||
<button type="button" class="oe_selectcreatepopup-search-close">Close</button>
|
||||
</t>
|
||||
<t t-name="Many2XSelectPopup.form.buttons">
|
||||
<button type="button" class="oe_many2xselectpopup-form-save">Save</button>
|
||||
<button type="button" class="oe_many2xselectpopup-form-close">Close</button>
|
||||
<t t-name="SelectCreatePopup.form.buttons">
|
||||
<button type="button" class="oe_selectcreatepopup-form-save">Save</button>
|
||||
<button type="button" class="oe_selectcreatepopup-form-close">Close</button>
|
||||
</t>
|
||||
|
||||
<t t-name="ListView.row.frame" t-extend="WidgetFrame">
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
.openerp table.oe-dashboard {
|
||||
width: 100%;
|
||||
}
|
||||
.openerp .oe-dashboard-links {
|
||||
text-align: right;
|
||||
margin: -2em 1em 1em 0;
|
||||
}
|
||||
.openerp .oe-dashboard-column {
|
||||
float: left;
|
||||
padding-bottom: 100px;
|
||||
margin: -2em 0.4em 1em 0;
|
||||
}
|
||||
.openerp .oe-dashboard-action {
|
||||
margin: 0 1em 1em 0;
|
||||
margin: 0 0.5em 0.5em 0;
|
||||
}
|
||||
.openerp .oe-dashboard-action .oe-dashboard-action-header {
|
||||
margin: 0.3em;
|
||||
@@ -58,7 +57,7 @@
|
||||
}
|
||||
|
||||
/* Layouts */
|
||||
.openerp .oe-dashboard-layout_1 .oe-dashboard-column {
|
||||
.openerp .oe-dashboard-layout_1 .oe-dashboard-column.index_0 {
|
||||
width: 100%;
|
||||
}
|
||||
.openerp .oe-dashboard-layout_1 .oe-dashboard-column.index_1,
|
||||
|
||||
@@ -18,13 +18,15 @@
|
||||
<span>Change layout</span>
|
||||
</button>
|
||||
</div>
|
||||
<div t-att-data-layout="node.attrs.style" t-attf-class="oe-dashboard oe-dashboard-layout_#{node.attrs.style}">
|
||||
<div t-foreach="node.children" t-as="column" t-if="column.tag == 'column'"
|
||||
<table t-att-data-layout="node.attrs.style" t-attf-class="oe-dashboard oe-dashboard-layout_#{node.attrs.style}" cellspacing="0" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td t-foreach="node.children" t-as="column" t-if="column.tag == 'column'"
|
||||
t-att-id="view.element_id + '_column_' + column_index" t-attf-class="oe-dashboard-column index_#{column_index}">
|
||||
|
||||
<t t-foreach="column.children" t-as="action" t-if="action.tag == 'action'" t-call="DashBoard.action"/>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
<t t-name="DashBoard.action">
|
||||
<div t-att-data-id="action.attrs.name" class="oe-dashboard-action ui-widget ui-widget-content ui-helper-clearfix ui-corner-all">
|
||||
|
||||
@@ -27,6 +27,16 @@ class NonLiteralEncoder(simplejson.encoder.JSONEncoder):
|
||||
'__ref': 'context',
|
||||
'__id': object.key
|
||||
}
|
||||
elif isinstance(object, CompoundDomain):
|
||||
return {
|
||||
'__ref': 'compound_domain',
|
||||
'__domains': [self.default(el) for el in object.domains]
|
||||
}
|
||||
elif isinstance(object, CompoundContext):
|
||||
return {
|
||||
'__ref': 'compound_context',
|
||||
'__contexts': [self.default(el) for el in object.contexts]
|
||||
}
|
||||
return super(NonLiteralEncoder, self).default(object)
|
||||
|
||||
def non_literal_decoder(dct):
|
||||
@@ -47,6 +57,16 @@ def non_literal_decoder(dct):
|
||||
if 'own_values' in dct:
|
||||
context.own = dct['own_values']
|
||||
return context
|
||||
elif dct["__ref"] == "compound_domain":
|
||||
cdomain = CompoundDomain()
|
||||
for el in dct["__domains"]:
|
||||
cdomain.domains.append(non_literal_decoder(el))
|
||||
return cdomain
|
||||
elif dct["__ref"] == "compound_context":
|
||||
ccontext = CompoundContext()
|
||||
for el in dct["__contexts"]:
|
||||
ccontext.contexts.append(non_literal_decoder(el))
|
||||
return ccontext
|
||||
return dct
|
||||
|
||||
class Domain(object):
|
||||
@@ -138,3 +158,63 @@ class Context(object):
|
||||
ctx.update(self.own)
|
||||
return eval(self.get_context_string(),
|
||||
ctx)
|
||||
|
||||
class CompoundDomain:
|
||||
def __init__(self, *domains):
|
||||
self.domains = []
|
||||
self.session = None
|
||||
for domain in domains:
|
||||
self.add(domain)
|
||||
|
||||
def evaluate(self, context=None):
|
||||
final_domain = []
|
||||
for domain in self.domains:
|
||||
if not isinstance(domain, (list, Domain, CompoundDomain)):
|
||||
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['context'] = ctx
|
||||
|
||||
domain.session = self.session
|
||||
final_domain.extend(domain.evaluate(ctx))
|
||||
return final_domain
|
||||
|
||||
def add(self, domain):
|
||||
self.domains.append(domain)
|
||||
return self
|
||||
|
||||
class CompoundContext:
|
||||
def __init__(self, *contexts):
|
||||
self.contexts = []
|
||||
self.session = None
|
||||
for context in contexts:
|
||||
self.add(context)
|
||||
|
||||
def evaluate(self, context=None):
|
||||
ctx = dict(context or {})
|
||||
final_context = {}
|
||||
for context_to_eval in self.contexts:
|
||||
if not isinstance(context_to_eval, (dict, Context, CompoundContext)):
|
||||
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
|
||||
|
||||
ctx.update(final_context)
|
||||
ctx["context"] = ctx
|
||||
|
||||
context_to_eval.session = self.session
|
||||
final_context.update(context_to_eval.evaluate(ctx))
|
||||
return final_context
|
||||
|
||||
def add(self, context):
|
||||
self.contexts.append(context)
|
||||
return self
|
||||
|
||||
|
||||
+14
-66
@@ -138,6 +138,9 @@ 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
|
||||
@@ -182,7 +185,7 @@ class OpenERPSession(object):
|
||||
|
||||
def eval_context(self, context_to_eval, context=None):
|
||||
""" Evaluates the provided context_to_eval in the context (haha) of
|
||||
the context.
|
||||
the context. Also merges the evaluated context with the session's context.
|
||||
|
||||
:param context_to_eval: a context to evaluate. Must be a dict or a
|
||||
non-literal context. If it's a dict, will be
|
||||
@@ -194,46 +197,15 @@ class OpenERPSession(object):
|
||||
:raises: ``TypeError`` if ``context_to_eval`` is neither a dict nor
|
||||
a Context
|
||||
"""
|
||||
if not isinstance(context_to_eval, (dict, nonliterals.Domain)):
|
||||
raise TypeError("Context %r is not a dict or a nonliteral Context",
|
||||
context_to_eval)
|
||||
|
||||
if isinstance(context_to_eval, dict):
|
||||
return context_to_eval
|
||||
|
||||
ctx = dict(context or {})
|
||||
ctx['context'] = ctx
|
||||
|
||||
# if the domain was unpacked from JSON, it needs the current
|
||||
# OpenERPSession for its data retrieval
|
||||
context_to_eval.session = self
|
||||
return context_to_eval.evaluate(ctx)
|
||||
|
||||
def eval_contexts(self, contexts, context=None):
|
||||
""" Evaluates a sequence of contexts to build a single final result
|
||||
|
||||
:param list contexts: a list of Context or dict contexts
|
||||
:param dict context: a base context, if needed
|
||||
:returns: the final combination of all provided contexts
|
||||
:rtype: dict
|
||||
"""
|
||||
# This is the context we use to evaluate stuff
|
||||
current_context = dict(
|
||||
ctx = dict(
|
||||
self.base_eval_context,
|
||||
**(context or {}))
|
||||
# this is our result, it should not contain the values
|
||||
# of the base context above
|
||||
final_context = {}
|
||||
for ctx in contexts:
|
||||
# evaluate the current context in the sequence, merge it into
|
||||
# the result
|
||||
final_context.update(
|
||||
self.eval_context(
|
||||
ctx, current_context))
|
||||
# update the current evaluation context so that future
|
||||
# evaluations can use the results we just gathered
|
||||
current_context.update(final_context)
|
||||
return final_context
|
||||
ctx['context'] = ctx
|
||||
|
||||
# adding the context of the session to send to the openerp server
|
||||
ccontext = nonliterals.CompoundContext(self.context, context_to_eval)
|
||||
ccontext.session = self
|
||||
return ccontext.evaluate(ctx)
|
||||
|
||||
def eval_domain(self, domain, context=None):
|
||||
""" Evaluates the provided domain using the provided context
|
||||
@@ -250,39 +222,15 @@ class OpenERPSession(object):
|
||||
|
||||
:raises: ``TypeError`` if ``domain`` is neither a list nor a Domain
|
||||
"""
|
||||
if not isinstance(domain, (list, nonliterals.Domain)):
|
||||
raise TypeError("Domain %r is not a list or a nonliteral Domain",
|
||||
domain)
|
||||
|
||||
if isinstance(domain, list):
|
||||
return domain
|
||||
|
||||
ctx = dict(context or {})
|
||||
ctx['context'] = ctx
|
||||
|
||||
# if the domain was unpacked from JSON, it needs the current
|
||||
# OpenERPSession for its data retrieval
|
||||
domain.session = self
|
||||
return domain.evaluate(ctx)
|
||||
|
||||
def eval_domains(self, domains, context=None):
|
||||
""" Evaluates and concatenates the provided domains using the
|
||||
provided context for all of them.
|
||||
|
||||
Returns the final, concatenated result.
|
||||
|
||||
:param list domains: a list of Domain or list domains
|
||||
:param dict context: the context in which the domains
|
||||
should be evaluated (if evaluations need
|
||||
to happen)
|
||||
:returns: the final combination of all domains in the sequence
|
||||
:rtype: list
|
||||
"""
|
||||
final_domain = []
|
||||
for domain in domains:
|
||||
final_domain.extend(
|
||||
self.eval_domain(domain, context))
|
||||
return final_domain
|
||||
cdomain = nonliterals.CompoundDomain(domain)
|
||||
cdomain.session = self
|
||||
return cdomain.evaluate(ctx)
|
||||
|
||||
#----------------------------------------------------------
|
||||
# OpenERP Web RequestHandler
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import unittest2
|
||||
from openerpweb.nonliterals import Domain
|
||||
from openerpweb.nonliterals import Domain, Context, CompoundDomain, CompoundContext
|
||||
import openerpweb.openerpweb
|
||||
|
||||
class TestOpenERPSession(unittest2.TestCase):
|
||||
@@ -77,7 +77,7 @@ class TestOpenERPSession(unittest2.TestCase):
|
||||
|
||||
def test_eval_empty_domains(self):
|
||||
self.assertEqual(
|
||||
self.session.eval_domains([]),
|
||||
self.session.eval_domain(CompoundDomain(*[])),
|
||||
[])
|
||||
|
||||
def test_eval_literal_domains(self):
|
||||
@@ -89,7 +89,7 @@ class TestOpenERPSession(unittest2.TestCase):
|
||||
('c', 'in', ['a', 'b', 'c'])]
|
||||
]
|
||||
self.assertEqual(
|
||||
self.session.eval_domains(domains),
|
||||
self.session.eval_domain(CompoundDomain(*domains)),
|
||||
[
|
||||
('a', 'is', 3),
|
||||
('b', 'ilike', 'foo'),
|
||||
@@ -104,7 +104,7 @@ class TestOpenERPSession(unittest2.TestCase):
|
||||
"['|', ('date', '<', current_date),"
|
||||
" ('date', '>', current_date)]")]
|
||||
self.assertEqual(
|
||||
self.session.eval_domains(domains),
|
||||
self.session.eval_domain(CompoundDomain(*domains)),
|
||||
[('uid', '=', -1),
|
||||
'|', ('date', '<', '1945-08-05'), ('date', '>', '1945-08-05')]
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user