[MERGE]Merge with trunk upto revision no 808.
bzr revid: kch@tinyerp.com-20110816060212-iwm7u82ur0mxw1s5
This commit is contained in:
+6
-7
@@ -1,12 +1,11 @@
|
||||
RE:lib/(?!populate.sh).*
|
||||
.*
|
||||
*.egg-info
|
||||
*.orig
|
||||
bin/
|
||||
build/
|
||||
dist/
|
||||
include/
|
||||
RE:^bin/
|
||||
RE:^dist/
|
||||
RE:^include/
|
||||
|
||||
share/
|
||||
man/
|
||||
lib/
|
||||
RE:^share/
|
||||
RE:^man/
|
||||
RE:^lib/
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"static/lib/underscore/underscore.string.js",
|
||||
"static/src/js/boot.js",
|
||||
"static/src/js/core.js",
|
||||
"static/src/js/dates.js",
|
||||
"static/src/js/formats.js",
|
||||
"static/src/js/chrome.js",
|
||||
"static/src/js/views.js",
|
||||
"static/src/js/data.js",
|
||||
|
||||
@@ -391,10 +391,10 @@ def load_actions_from_ir_values(req, key, key2, models, meta, context):
|
||||
Values = req.session.model('ir.values')
|
||||
actions = Values.get(key, key2, models, meta, context)
|
||||
|
||||
return [(id, name, clean_action(action, req.session))
|
||||
return [(id, name, clean_action(action, req.session, context=context))
|
||||
for id, name, action in actions]
|
||||
|
||||
def clean_action(action, session):
|
||||
def clean_action(action, session, context=None):
|
||||
action.setdefault('flags', {})
|
||||
if action['type'] != 'ir.actions.act_window':
|
||||
return action
|
||||
@@ -402,7 +402,7 @@ def clean_action(action, session):
|
||||
if isinstance(action.get('context'), basestring):
|
||||
action['context'] = eval(
|
||||
action['context'],
|
||||
session.evaluation_context()) or {}
|
||||
session.evaluation_context(context=context)) or {}
|
||||
|
||||
if isinstance(action.get('domain'), basestring):
|
||||
action['domain'] = eval(
|
||||
@@ -560,6 +560,7 @@ class DataSet(openerpweb.Controller):
|
||||
:rtype: list
|
||||
"""
|
||||
Model = request.session.model(model)
|
||||
|
||||
context, domain = eval_context_and_domain(
|
||||
request.session, request.context, domain)
|
||||
|
||||
@@ -582,9 +583,14 @@ class DataSet(openerpweb.Controller):
|
||||
}
|
||||
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def read(self, request, model, ids, fields=False):
|
||||
return self.do_search_read(request, model, ids, fields)
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get(self, request, model, ids, fields=False):
|
||||
return self.do_get(request, model, ids, fields)
|
||||
|
||||
def do_get(self, request, model, ids, fields=False):
|
||||
""" Fetches and returns the records of the model ``model`` whose ids
|
||||
are in ``ids``.
|
||||
@@ -669,6 +675,12 @@ class DataSet(openerpweb.Controller):
|
||||
Model = req.session.model(model)
|
||||
return Model.default_get(fields, req.session.eval_context(req.context))
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def name_search(self, req, model, search_str, domain=[], context={}):
|
||||
m = req.session.model(model)
|
||||
r = m.name_search(search_str+'%', domain, '=ilike', context)
|
||||
return {'result': r}
|
||||
|
||||
class DataGroup(openerpweb.Controller):
|
||||
_cp_path = "/base/group"
|
||||
@openerpweb.jsonrequest
|
||||
@@ -761,8 +773,8 @@ class View(openerpweb.Controller):
|
||||
""" Parses an arbitrary string containing a domain, transforms it
|
||||
to either a literal domain or a :class:`openerpweb.nonliterals.Domain`
|
||||
|
||||
:param domain: the domain to parse, if the domain is not a string it is assumed to
|
||||
be a literal domain and is returned as-is
|
||||
:param domain: the domain to parse, if the domain is not a string it
|
||||
is assumed to be a literal domain and is returned as-is
|
||||
:param session: Current OpenERP session
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
"""
|
||||
@@ -778,8 +790,8 @@ class View(openerpweb.Controller):
|
||||
""" Parses an arbitrary string containing a context, transforms it
|
||||
to either a literal context or a :class:`openerpweb.nonliterals.Context`
|
||||
|
||||
:param context: the context to parse, if the context is not a string it is assumed to
|
||||
be a literal domain and is returned as-is
|
||||
:param context: the context to parse, if the context is not a string it
|
||||
is assumed to be a literal domain and is returned as-is
|
||||
:param session: Current OpenERP session
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
"""
|
||||
@@ -1002,6 +1014,19 @@ class Action(openerpweb.Controller):
|
||||
return clean_action(req.session.model('ir.actions.server').run(
|
||||
[action_id], req.session.eval_context(req.context)), req.session)
|
||||
|
||||
class TreeView(View):
|
||||
_cp_path = "/base/treeview"
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def load(self, req, model, view_id, toolbar=False):
|
||||
return self.fields_view_get(req, model, view_id, 'tree', toolbar=toolbar)
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def action(self, req, model, id):
|
||||
return load_actions_from_ir_values(
|
||||
req,'action', 'tree_but_open',[(model, id)],
|
||||
False, req.session.eval_context(req.context))
|
||||
|
||||
def export_csv(fields, result):
|
||||
fp = StringIO()
|
||||
writer = csv.writer(fp, quoting=csv.QUOTE_ALL)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// TODO: trim support
|
||||
// TODO: line number -> https://bugzilla.mozilla.org/show_bug.cgi?id=618650
|
||||
// TODO: templates orverwritten could be called by t-call="__super__" ?
|
||||
// TODO: t-set + t-value + children node == scoped variable ?
|
||||
var QWeb2 = {
|
||||
expressions_cache: {},
|
||||
reserved_words: 'true,false,NaN,null,undefined,debugger,in,instanceof,new,function,return,this,typeof,eval,Math,RegExp,Array,Object,Date'.split(','),
|
||||
@@ -21,6 +23,11 @@ var QWeb2 = {
|
||||
}
|
||||
throw new Error(prefix + ": " + message);
|
||||
},
|
||||
warning : function(message) {
|
||||
if (typeof(window) !== 'undefined' && window.console) {
|
||||
window.console.warn(message);
|
||||
}
|
||||
},
|
||||
trim: function(s, mode) {
|
||||
switch (mode) {
|
||||
case "left":
|
||||
@@ -638,6 +645,9 @@ QWeb2.Element = (function() {
|
||||
compile_action_set : function(value) {
|
||||
var variable = this.format_expression(value);
|
||||
if (this.actions['value']) {
|
||||
if (this.children.length) {
|
||||
this.engine.tools.warning("@set with @value plus node chidren found. Children are ignored.");
|
||||
}
|
||||
this.top(variable + " = (" + (this.format_expression(this.actions['value'])) + ");");
|
||||
this.process_children = false;
|
||||
} else {
|
||||
|
||||
@@ -269,7 +269,7 @@ label.error {
|
||||
border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
|
||||
|
||||
color: #eee;
|
||||
text-shadow: #222 0 1px 0;
|
||||
text-decoration: none;
|
||||
@@ -923,11 +923,11 @@ label.error {
|
||||
height: 15px;
|
||||
}
|
||||
.openerp td.required input, .openerp td.required select {
|
||||
background-color: #D2D2FF;
|
||||
background-color: #D2D2FF !important;
|
||||
}
|
||||
.openerp td.invalid input, .openerp td.invalid select, .openerp td.invalid textarea {
|
||||
background-color: #F66;
|
||||
border: 1px solid #D00;
|
||||
background-color: #F66 !important;
|
||||
border: 1px solid #D00 !important;
|
||||
}
|
||||
.openerp div.oe-progressbar span {
|
||||
position: absolute;
|
||||
@@ -1053,7 +1053,7 @@ label.error {
|
||||
padding-left: 10px;
|
||||
padding-right: 21px;
|
||||
height: 21px;
|
||||
|
||||
|
||||
background: #ffffff; /* Old browsers */
|
||||
background: -moz-linear-gradient(top, #ffffff 0%, #ebe9e9 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#ebe9e9)); /* Chrome,Safari4+ */
|
||||
@@ -1062,7 +1062,7 @@ background: -o-linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* Opera11.10+ */
|
||||
background: -ms-linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* IE10+ */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#EBE9E9',GradientType=0 ); /* IE6-9 */
|
||||
background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */
|
||||
|
||||
|
||||
border: 1px solid #D2CFCF;
|
||||
border-right-width: 0;
|
||||
border-left-width: 0;
|
||||
@@ -1167,7 +1167,9 @@ background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */
|
||||
.openerp .oe-m2o-disabled-cm {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.parent_top {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
.openerp .oe-dialog-warning p {
|
||||
padding-left: 1em;
|
||||
font-size: 1.2em;
|
||||
@@ -1180,3 +1182,30 @@ background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.openerp .oe-treeview-table {
|
||||
width: 100%;
|
||||
}
|
||||
.treeview-tr, .treeview-td {
|
||||
cursor: pointer;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
.treeview-tr span, .treeview-td span {
|
||||
display: block;
|
||||
}
|
||||
.treeview-tr:first-of-type {
|
||||
background: transparent url(/base/static/src/img/expand.gif) 0 50% no-repeat;
|
||||
}
|
||||
.oe-open .treeview-tr:first-of-type {
|
||||
background-image: url(/base/static/src/img/collapse.gif);
|
||||
}
|
||||
.treeview-tr:first-of-type span,
|
||||
.treeview-td:first-of-type span {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.treeview-header {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//---------------------------------------------------------
|
||||
// OpenERP Web Boostrap
|
||||
//---------------------------------------------------------
|
||||
/*---------------------------------------------------------
|
||||
* OpenERP Web Boostrap Code
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @name openerp
|
||||
@@ -14,13 +14,8 @@
|
||||
|
||||
/** @lends openerp */
|
||||
var openerp = this.openerp = {
|
||||
/**
|
||||
* Debug flag turns on logging
|
||||
*/
|
||||
// debug flag
|
||||
debug: true,
|
||||
// element_ids registry linked to all controllers on the page
|
||||
// TODO rename to elements, or keep gtk naming?
|
||||
screen: {},
|
||||
// Per session namespace
|
||||
// openerp.<module> will map to
|
||||
// openerp.sessions.sessionname.<module> using a closure
|
||||
@@ -40,8 +35,6 @@
|
||||
// this unique id will be replaced by hostname_databasename by
|
||||
// openerp.base.Connection on the first connection
|
||||
_session_id: "session" + session_counter++,
|
||||
screen: openerp.screen,
|
||||
sessions: openerp.sessions,
|
||||
base: {},
|
||||
web_mobile: {}
|
||||
};
|
||||
@@ -51,16 +44,17 @@
|
||||
}
|
||||
return new_instance;
|
||||
}
|
||||
// TODO add initrpc to init core only for RPC
|
||||
};
|
||||
})();
|
||||
|
||||
//---------------------------------------------------------
|
||||
// OpenERP base module split
|
||||
//---------------------------------------------------------
|
||||
/*---------------------------------------------------------
|
||||
* OpenERP Web base module split
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.base = function(instance) {
|
||||
openerp.base.core(instance);
|
||||
openerp.base.dates(instance);
|
||||
openerp.base.formats(instance);
|
||||
openerp.base.chrome(instance);
|
||||
openerp.base.data(instance);
|
||||
if (openerp.base.views) {
|
||||
|
||||
@@ -1,285 +1,9 @@
|
||||
/*---------------------------------------------------------
|
||||
* OpenERP base library
|
||||
* OpenERP Web chrome
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.base.chrome = function(openerp) {
|
||||
|
||||
openerp.base.Session = openerp.base.Widget.extend( /** @lends openerp.base.Session# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @param element_id to use for exception reporting
|
||||
* @param server
|
||||
* @param port
|
||||
*/
|
||||
init: function(parent, element_id, server, port) {
|
||||
this._super(parent, element_id);
|
||||
this.server = (server == undefined) ? location.hostname : server;
|
||||
this.port = (port == undefined) ? location.port : port;
|
||||
this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp";
|
||||
this.debug = true;
|
||||
this.db = "";
|
||||
this.login = "";
|
||||
this.password = "";
|
||||
this.uid = false;
|
||||
this.session_id = false;
|
||||
this.module_list = [];
|
||||
this.module_loaded = {"base": true};
|
||||
this.context = {};
|
||||
},
|
||||
start: function() {
|
||||
this.session_restore();
|
||||
},
|
||||
/**
|
||||
* Executes an RPC call, registering the provided callbacks.
|
||||
*
|
||||
* Registers a default error callback if none is provided, and handles
|
||||
* setting the correct session id and session context in the parameter
|
||||
* objects
|
||||
*
|
||||
* @param {String} url RPC endpoint
|
||||
* @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
|
||||
* @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;
|
||||
|
||||
// Call using the rpc_mode
|
||||
var deferred = $.Deferred();
|
||||
this.rpc_ajax(url, {
|
||||
jsonrpc: "2.0",
|
||||
method: "call",
|
||||
params: params,
|
||||
id:null
|
||||
}).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) {
|
||||
var self = this;
|
||||
this.on_rpc_request();
|
||||
// url can be an $.ajax option object
|
||||
if (_.isString(url)) {
|
||||
url = {
|
||||
url: url
|
||||
}
|
||||
}
|
||||
var ajax = _.extend({
|
||||
type: "POST",
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(payload),
|
||||
processData: false
|
||||
}, url);
|
||||
var deferred = $.Deferred();
|
||||
$.ajax(ajax).done(function(response, textStatus, jqXHR) {
|
||||
self.on_rpc_response();
|
||||
if (!response.error) {
|
||||
deferred.resolve(response["result"], textStatus, jqXHR);
|
||||
return;
|
||||
}
|
||||
if (response.error.data.type !== "session_invalid") {
|
||||
deferred.reject(response.error);
|
||||
return;
|
||||
}
|
||||
self.uid = false;
|
||||
self.on_session_invalid(function() {
|
||||
self.rpc(url, payload.params,
|
||||
function() {
|
||||
deferred.resolve.apply(deferred, arguments);
|
||||
},
|
||||
function(error, event) {
|
||||
event.preventDefault();
|
||||
deferred.reject.apply(deferred, arguments);
|
||||
});
|
||||
});
|
||||
}).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] }
|
||||
};
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise();
|
||||
},
|
||||
on_rpc_request: function() {
|
||||
},
|
||||
on_rpc_response: function() {
|
||||
},
|
||||
on_rpc_error: function(error) {
|
||||
},
|
||||
/**
|
||||
* The session is validated either by login or by restoration of a previous session
|
||||
*/
|
||||
on_session_valid: function() {
|
||||
if(!openerp._modules_loaded)
|
||||
this.load_modules();
|
||||
},
|
||||
on_session_invalid: function(contination) {
|
||||
},
|
||||
session_is_valid: function() {
|
||||
return this.uid;
|
||||
},
|
||||
session_login: function(db, login, password, success_callback) {
|
||||
var self = this;
|
||||
this.db = db;
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
var params = { db: this.db, login: this.login, password: this.password };
|
||||
this.rpc("/base/session/login", params, function(result) {
|
||||
self.session_id = result.session_id;
|
||||
self.uid = result.uid;
|
||||
self.session_save();
|
||||
self.on_session_valid();
|
||||
if (success_callback)
|
||||
success_callback();
|
||||
});
|
||||
},
|
||||
session_logout: function() {
|
||||
this.uid = false;
|
||||
},
|
||||
/**
|
||||
* Reloads uid and session_id from local storage, if they exist
|
||||
*/
|
||||
session_restore: function () {
|
||||
this.uid = this.get_cookie('uid');
|
||||
this.session_id = this.get_cookie('session_id');
|
||||
this.db = this.get_cookie('db');
|
||||
this.login = this.get_cookie('login');
|
||||
// we should do an rpc to confirm that this session_id is valid and if it is retrieve the information about db and login
|
||||
// then call on_session_valid
|
||||
this.on_session_valid();
|
||||
},
|
||||
/**
|
||||
* Saves the session id and uid locally
|
||||
*/
|
||||
session_save: function () {
|
||||
this.set_cookie('uid', this.uid);
|
||||
this.set_cookie('session_id', this.session_id);
|
||||
this.set_cookie('db', this.db);
|
||||
this.set_cookie('login', this.login);
|
||||
},
|
||||
logout: function() {
|
||||
delete this.uid;
|
||||
delete this.session_id;
|
||||
delete this.db;
|
||||
delete this.login;
|
||||
this.set_cookie('uid', '');
|
||||
this.set_cookie('session_id', '');
|
||||
this.set_cookie('db', '');
|
||||
this.set_cookie('login', '');
|
||||
this.on_session_invalid(function() {});
|
||||
},
|
||||
/**
|
||||
* Fetches a cookie stored by an openerp session
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
*/
|
||||
get_cookie: function (name) {
|
||||
var nameEQ = this.element_id + '|' + name + '=';
|
||||
var cookies = document.cookie.split(';');
|
||||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Create a new cookie with the provided name and value
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
* @param value the cookie's value
|
||||
* @param ttl the cookie's time to live, 1 year by default, set to -1 to delete
|
||||
*/
|
||||
set_cookie: function (name, value, ttl) {
|
||||
ttl = ttl || 24*60*60*365;
|
||||
document.cookie = [
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
|
||||
'max-age=' + ttl,
|
||||
'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
|
||||
].join(';');
|
||||
},
|
||||
/**
|
||||
* Load additional web addons of that instance and init them
|
||||
*/
|
||||
load_modules: function() {
|
||||
var self = this;
|
||||
this.rpc('/base/session/modules', {}, function(result) {
|
||||
self.module_list = result;
|
||||
var modules = self.module_list.join(',');
|
||||
if(self.debug || true) {
|
||||
self.rpc('/base/webclient/csslist', {"mods": modules}, self.do_load_css);
|
||||
self.rpc('/base/webclient/jslist', {"mods": modules}, self.do_load_js);
|
||||
} else {
|
||||
self.do_load_css(["/base/webclient/css?mods="+modules]);
|
||||
self.do_load_js(["/base/webclient/js?mods="+modules]);
|
||||
}
|
||||
openerp._modules_loaded = true;
|
||||
});
|
||||
},
|
||||
do_load_css: function (files) {
|
||||
_.each(files, function (file) {
|
||||
$('head').append($('<link>', {
|
||||
'href': file,
|
||||
'rel': 'stylesheet',
|
||||
'type': 'text/css'
|
||||
}));
|
||||
});
|
||||
},
|
||||
do_load_js: function(files) {
|
||||
var self = this;
|
||||
if(files.length != 0) {
|
||||
var file = files.shift();
|
||||
var tag = document.createElement('script');
|
||||
tag.type = 'text/javascript';
|
||||
tag.src = file;
|
||||
tag.onload = tag.onreadystatechange = function() {
|
||||
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
|
||||
return;
|
||||
tag.onload_done = true;
|
||||
self.do_load_js(files);
|
||||
};
|
||||
document.head.appendChild(tag);
|
||||
} else {
|
||||
this.on_modules_loaded();
|
||||
}
|
||||
},
|
||||
on_modules_loaded: function() {
|
||||
for(var j=0; j<this.module_list.length; j++) {
|
||||
var mod = this.module_list[j];
|
||||
if(this.module_loaded[mod])
|
||||
continue;
|
||||
openerp[mod] = {};
|
||||
// init module mod
|
||||
if(openerp._openerp[mod] != undefined) {
|
||||
openerp._openerp[mod](openerp);
|
||||
this.module_loaded[mod] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Notification = openerp.base.Widget.extend({
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
@@ -318,9 +42,7 @@ openerp.base.Dialog = openerp.base.OldWidget.extend({
|
||||
max_height: '100%',
|
||||
autoOpen: false,
|
||||
buttons: {},
|
||||
beforeClose: function () {
|
||||
self.on_close();
|
||||
}
|
||||
beforeClose: function () { self.on_close(); }
|
||||
};
|
||||
for (var f in this) {
|
||||
if (f.substr(0, 10) == 'on_button_') {
|
||||
@@ -368,12 +90,10 @@ openerp.base.Dialog = openerp.base.OldWidget.extend({
|
||||
return parseInt(val, 10);
|
||||
}
|
||||
},
|
||||
start: function (auto_open) {
|
||||
start: function () {
|
||||
this.$dialog = $('<div id="' + this.element_id + '"></div>').dialog(this.dialog_options);
|
||||
if (auto_open !== false) {
|
||||
this.open();
|
||||
}
|
||||
this._super();
|
||||
return this;
|
||||
},
|
||||
open: function(dialog_options) {
|
||||
// TODO fme: bind window on resize
|
||||
@@ -949,12 +669,10 @@ openerp.base.Homepage = openerp.base.Widget.extend({
|
||||
openerp.base.Preferences = openerp.base.Widget.extend({
|
||||
});
|
||||
|
||||
openerp.base.ImportExport = openerp.base.Widget.extend({
|
||||
});
|
||||
|
||||
openerp.base.WebClient = openerp.base.Widget.extend({
|
||||
init: function(element_id) {
|
||||
this._super(null, element_id);
|
||||
openerp.webclient = this;
|
||||
|
||||
QWeb.add_template("/base/static/src/xml/base.xml");
|
||||
var params = {};
|
||||
@@ -966,7 +684,7 @@ openerp.base.WebClient = openerp.base.Widget.extend({
|
||||
this.session = new openerp.base.Session(this,"oe_errors");
|
||||
this.loading = new openerp.base.Loading(this,"oe_loading");
|
||||
this.crashmanager = new openerp.base.CrashManager(this);
|
||||
this.crashmanager.start(false);
|
||||
this.crashmanager.start();
|
||||
|
||||
// Do you autorize this ? will be replaced by notify() in controller
|
||||
openerp.base.Widget.prototype.notification = new openerp.base.Notification(this, "oe_notification");
|
||||
@@ -991,8 +709,10 @@ openerp.base.WebClient = openerp.base.Widget.extend({
|
||||
this.notification.notify("OpenERP Client", "The openerp client has been initialized.");
|
||||
},
|
||||
on_logged: function() {
|
||||
this.action_manager = new openerp.base.ActionManager(this, "oe_app");
|
||||
this.action_manager.start();
|
||||
if(this.action_manager)
|
||||
this.action_manager.stop();
|
||||
this.action_manager = new openerp.base.ActionManager(this);
|
||||
this.action_manager.appendTo($("#oe_app"));
|
||||
|
||||
// if using saved actions, load the action and give it to action manager
|
||||
var parameters = jQuery.deparam(jQuery.param.querystring());
|
||||
@@ -1032,7 +752,8 @@ openerp.base.WebClient = openerp.base.Widget.extend({
|
||||
self.execute_home_action(home_action[0], ds);
|
||||
})
|
||||
},
|
||||
default_home: function () { },
|
||||
default_home: function () {
|
||||
},
|
||||
/**
|
||||
* Bundles the execution of the home action
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*---------------------------------------------------------
|
||||
* OpenERP controller framework
|
||||
* OpenERP Web core
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
openerp.base.core = function(openerp) {
|
||||
@@ -373,59 +373,6 @@ openerp.base.SessionAware = openerp.base.Class.extend({
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Base class for all visual components. Provides a lot of functionalities helpful
|
||||
* for the management of a part of the DOM.
|
||||
*
|
||||
* Widget handles:
|
||||
* - Rendering with QWeb.
|
||||
* - Life-cycle management and parenting (when a parent is destroyed, all its children are
|
||||
* destroyed too).
|
||||
* - Insertion in DOM.
|
||||
*
|
||||
* Widget also extends SessionAware for ease of use.
|
||||
*
|
||||
* Guide to create implementations of the Widget class:
|
||||
* ==============================================
|
||||
*
|
||||
* Here is a sample child class:
|
||||
*
|
||||
* MyWidget = openerp.base.Widget.extend({
|
||||
* // the name of the QWeb template to use for rendering
|
||||
* template: "MyQWebTemplate",
|
||||
* // identifier prefix, it is useful to put an obvious one for debugging
|
||||
* identifier_prefix: 'my-id-prefix-',
|
||||
*
|
||||
* init: function(parent) {
|
||||
* this._super(parent);
|
||||
* // stuff that you want to init before the rendering
|
||||
* },
|
||||
* start: function() {
|
||||
* this._super();
|
||||
* // stuff you want to make after the rendering, `this.$element` holds a correct value
|
||||
* this.$element.find(".my_button").click(/* an example of event binding * /);
|
||||
*
|
||||
* // if you have some asynchronous operations, it's a good idea to return
|
||||
* // a promise in start()
|
||||
* var promise = this.rpc(...);
|
||||
* return promise;
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Now this class can simply be used with the following syntax:
|
||||
*
|
||||
* var my_widget = new MyWidget(this);
|
||||
* my_widget.appendTo($(".some-div"));
|
||||
*
|
||||
* With these two lines, the MyWidget instance was inited, rendered, it was inserted into the
|
||||
* DOM inside the ".some-div" div and its events were binded.
|
||||
*
|
||||
* And of course, when you don't need that widget anymore, just do:
|
||||
*
|
||||
* my_widget.stop();
|
||||
*
|
||||
* That will kill the widget in a clean way and erase its content from the dom.
|
||||
*/
|
||||
openerp.base.Widget = openerp.base.SessionAware.extend({
|
||||
/**
|
||||
* The name of the QWeb template that will be used for rendering. Must be
|
||||
@@ -574,6 +521,18 @@ openerp.base.Widget = openerp.base.SessionAware.extend({
|
||||
}
|
||||
return false;
|
||||
},
|
||||
do_notify: function() {
|
||||
if (this.widget_parent) {
|
||||
return this.widget_parent.do_notify.apply(this,arguments);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
do_warn: function() {
|
||||
if (this.widget_parent) {
|
||||
return this.widget_parent.do_warn.apply(this,arguments);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
rpc: function(url, data, success, error) {
|
||||
var def = $.Deferred().then(success, error);
|
||||
var self = this;
|
||||
@@ -599,5 +558,282 @@ openerp.base.OldWidget = openerp.base.Widget.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Session = openerp.base.Widget.extend( /** @lends openerp.base.Session# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @param element_id to use for exception reporting
|
||||
* @param server
|
||||
* @param port
|
||||
*/
|
||||
init: function(parent, element_id, server, port) {
|
||||
this._super(parent, element_id);
|
||||
this.server = (server == undefined) ? location.hostname : server;
|
||||
this.port = (port == undefined) ? location.port : port;
|
||||
this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp";
|
||||
this.debug = true;
|
||||
this.db = "";
|
||||
this.login = "";
|
||||
this.password = "";
|
||||
this.uid = false;
|
||||
this.session_id = false;
|
||||
this.module_list = [];
|
||||
this.module_loaded = {"base": true};
|
||||
this.context = {};
|
||||
},
|
||||
start: function() {
|
||||
this.session_restore();
|
||||
},
|
||||
/**
|
||||
* Executes an RPC call, registering the provided callbacks.
|
||||
*
|
||||
* Registers a default error callback if none is provided, and handles
|
||||
* setting the correct session id and session context in the parameter
|
||||
* objects
|
||||
*
|
||||
* @param {String} url RPC endpoint
|
||||
* @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
|
||||
* @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;
|
||||
|
||||
// Call using the rpc_mode
|
||||
var deferred = $.Deferred();
|
||||
this.rpc_ajax(url, {
|
||||
jsonrpc: "2.0",
|
||||
method: "call",
|
||||
params: params,
|
||||
id:null
|
||||
}).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) {
|
||||
var self = this;
|
||||
this.on_rpc_request();
|
||||
// url can be an $.ajax option object
|
||||
if (_.isString(url)) {
|
||||
url = {
|
||||
url: url
|
||||
}
|
||||
}
|
||||
var ajax = _.extend({
|
||||
type: "POST",
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(payload),
|
||||
processData: false
|
||||
}, url);
|
||||
var deferred = $.Deferred();
|
||||
$.ajax(ajax).done(function(response, textStatus, jqXHR) {
|
||||
self.on_rpc_response();
|
||||
if (!response.error) {
|
||||
deferred.resolve(response["result"], textStatus, jqXHR);
|
||||
return;
|
||||
}
|
||||
if (response.error.data.type !== "session_invalid") {
|
||||
deferred.reject(response.error);
|
||||
return;
|
||||
}
|
||||
self.uid = false;
|
||||
self.on_session_invalid(function() {
|
||||
self.rpc(url, payload.params,
|
||||
function() {
|
||||
deferred.resolve.apply(deferred, arguments);
|
||||
},
|
||||
function(error, event) {
|
||||
event.preventDefault();
|
||||
deferred.reject.apply(deferred, arguments);
|
||||
});
|
||||
});
|
||||
}).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] }
|
||||
};
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise();
|
||||
},
|
||||
on_rpc_request: function() {
|
||||
},
|
||||
on_rpc_response: function() {
|
||||
},
|
||||
on_rpc_error: function(error) {
|
||||
},
|
||||
/**
|
||||
* The session is validated either by login or by restoration of a previous session
|
||||
*/
|
||||
on_session_valid: function() {
|
||||
if(!openerp._modules_loaded)
|
||||
this.load_modules();
|
||||
},
|
||||
on_session_invalid: function(contination) {
|
||||
},
|
||||
session_is_valid: function() {
|
||||
return this.uid;
|
||||
},
|
||||
session_login: function(db, login, password, success_callback) {
|
||||
var self = this;
|
||||
this.db = db;
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
var params = { db: this.db, login: this.login, password: this.password };
|
||||
this.rpc("/base/session/login", params, function(result) {
|
||||
self.session_id = result.session_id;
|
||||
self.uid = result.uid;
|
||||
self.session_save();
|
||||
self.on_session_valid();
|
||||
if (success_callback)
|
||||
success_callback();
|
||||
});
|
||||
},
|
||||
session_logout: function() {
|
||||
this.uid = false;
|
||||
},
|
||||
/**
|
||||
* Reloads uid and session_id from local storage, if they exist
|
||||
*/
|
||||
session_restore: function () {
|
||||
this.uid = this.get_cookie('uid');
|
||||
this.session_id = this.get_cookie('session_id');
|
||||
this.db = this.get_cookie('db');
|
||||
this.login = this.get_cookie('login');
|
||||
// we should do an rpc to confirm that this session_id is valid and if it is retrieve the information about db and login
|
||||
// then call on_session_valid
|
||||
this.on_session_valid();
|
||||
},
|
||||
/**
|
||||
* Saves the session id and uid locally
|
||||
*/
|
||||
session_save: function () {
|
||||
this.set_cookie('uid', this.uid);
|
||||
this.set_cookie('session_id', this.session_id);
|
||||
this.set_cookie('db', this.db);
|
||||
this.set_cookie('login', this.login);
|
||||
},
|
||||
logout: function() {
|
||||
delete this.uid;
|
||||
delete this.session_id;
|
||||
delete this.db;
|
||||
delete this.login;
|
||||
this.set_cookie('uid', '');
|
||||
this.set_cookie('session_id', '');
|
||||
this.set_cookie('db', '');
|
||||
this.set_cookie('login', '');
|
||||
this.on_session_invalid(function() {});
|
||||
},
|
||||
/**
|
||||
* Fetches a cookie stored by an openerp session
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
*/
|
||||
get_cookie: function (name) {
|
||||
var nameEQ = this.element_id + '|' + name + '=';
|
||||
var cookies = document.cookie.split(';');
|
||||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Create a new cookie with the provided name and value
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
* @param value the cookie's value
|
||||
* @param ttl the cookie's time to live, 1 year by default, set to -1 to delete
|
||||
*/
|
||||
set_cookie: function (name, value, ttl) {
|
||||
ttl = ttl || 24*60*60*365;
|
||||
document.cookie = [
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
|
||||
'max-age=' + ttl,
|
||||
'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
|
||||
].join(';');
|
||||
},
|
||||
/**
|
||||
* Load additional web addons of that instance and init them
|
||||
*/
|
||||
load_modules: function() {
|
||||
var self = this;
|
||||
this.rpc('/base/session/modules', {}, function(result) {
|
||||
self.module_list = result;
|
||||
var modules = self.module_list.join(',');
|
||||
if(self.debug || true) {
|
||||
self.rpc('/base/webclient/csslist', {"mods": modules}, self.do_load_css);
|
||||
self.rpc('/base/webclient/jslist', {"mods": modules}, self.do_load_js);
|
||||
} else {
|
||||
self.do_load_css(["/base/webclient/css?mods="+modules]);
|
||||
self.do_load_js(["/base/webclient/js?mods="+modules]);
|
||||
}
|
||||
openerp._modules_loaded = true;
|
||||
});
|
||||
},
|
||||
do_load_css: function (files) {
|
||||
_.each(files, function (file) {
|
||||
$('head').append($('<link>', {
|
||||
'href': file,
|
||||
'rel': 'stylesheet',
|
||||
'type': 'text/css'
|
||||
}));
|
||||
});
|
||||
},
|
||||
do_load_js: function(files) {
|
||||
var self = this;
|
||||
if(files.length != 0) {
|
||||
var file = files.shift();
|
||||
var tag = document.createElement('script');
|
||||
tag.type = 'text/javascript';
|
||||
tag.src = file;
|
||||
tag.onload = tag.onreadystatechange = function() {
|
||||
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
|
||||
return;
|
||||
tag.onload_done = true;
|
||||
self.do_load_js(files);
|
||||
};
|
||||
document.head.appendChild(tag);
|
||||
} else {
|
||||
this.on_modules_loaded();
|
||||
}
|
||||
},
|
||||
on_modules_loaded: function() {
|
||||
for(var j=0; j<this.module_list.length; j++) {
|
||||
var mod = this.module_list[j];
|
||||
if(this.module_loaded[mod])
|
||||
continue;
|
||||
openerp[mod] = {};
|
||||
// init module mod
|
||||
if(openerp._openerp[mod] != undefined) {
|
||||
openerp._openerp[mod](openerp);
|
||||
this.module_loaded[mod] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
||||
@@ -268,9 +268,13 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
},
|
||||
/**
|
||||
* Read records.
|
||||
*
|
||||
* @param {Array} ids identifiers of the records to read
|
||||
* @param {Array} fields fields to read and return, by default all fields are returned
|
||||
* @param {Function} callback function called with read result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_ids: function (ids, fields, callback) {
|
||||
var self = this;
|
||||
return this.rpc('/base/dataset/get', {
|
||||
model: this.model,
|
||||
ids: ids,
|
||||
@@ -282,13 +286,20 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
* Read a slice of the records represented by this DataSet, based on its
|
||||
* domain and context.
|
||||
*
|
||||
* @param {Number} [offset=0] The index from which selected records should be returned
|
||||
* @param {Number} [limit=null] The maximum number of records to return
|
||||
* @params {Object} options
|
||||
* @param {Array} [options.fields] fields to read and return, by default all fields are returned
|
||||
* @param {Number} [options.offset=0] The index from which selected records should be returned
|
||||
* @param {Number} [options.limit=null] The maximum number of records to return
|
||||
* @param {Function} callback function called with read_slice result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_slice: function (fields, offset, limit, callback) {
|
||||
},
|
||||
read_slice: function (options, callback) { return null; },
|
||||
/**
|
||||
* Read the indexed record.
|
||||
* Reads the current dataset record (from its index)
|
||||
*
|
||||
* @params {Array} [fields] fields to read and return, by default all fields are returned
|
||||
* @params {Function} callback function called with read_index result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_index: function (fields, callback) {
|
||||
var def = $.Deferred().then(callback);
|
||||
@@ -304,6 +315,13 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
}
|
||||
return def.promise();
|
||||
},
|
||||
/**
|
||||
* Reads default values for the current model
|
||||
*
|
||||
* @param {Array} [fields] fields to get default values for, by default all defaults are read
|
||||
* @param {Function} callback function called with default_get result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
default_get: function(fields, callback) {
|
||||
return this.rpc('/base/dataset/default_get', {
|
||||
model: this.model,
|
||||
@@ -311,6 +329,14 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
context: this.get_context()
|
||||
}, callback);
|
||||
},
|
||||
/**
|
||||
* Creates a new record in db
|
||||
*
|
||||
* @param {Object} data field values to set on the new record
|
||||
* @param {Function} callback function called with operation result
|
||||
* @param {Function} error_callback function called in case of creation error
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
create: function(data, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/create', {
|
||||
model: this.model,
|
||||
@@ -318,6 +344,15 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
context: this.get_context()
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Saves the provided data in an existing db record
|
||||
*
|
||||
* @param {Number|String} id identifier for the record to alter
|
||||
* @param {Object} data field values to write into the record
|
||||
* @param {Function} callback function called with operation result
|
||||
* @param {Function} error_callback function called in case of write error
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
write: function (id, data, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/save', {
|
||||
model: this.model,
|
||||
@@ -326,11 +361,27 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
context: this.get_context()
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Deletes an existing record from the database
|
||||
*
|
||||
* @param {Number|String} ids identifier of the record to delete
|
||||
* @param {Function} callback function called with operation result
|
||||
* @param {Function} error_callback function called in case of deletion error
|
||||
*/
|
||||
unlink: function(ids, callback, error_callback) {
|
||||
var self = this;
|
||||
return this.call_and_eval("unlink", [ids, this.get_context()], null, 1,
|
||||
callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Calls an arbitrary RPC method
|
||||
*
|
||||
* @param {String} method name of the method (on the current model) to call
|
||||
* @param {Array} [args] arguments to pass to the method
|
||||
* @param {Function} callback
|
||||
* @param {Function} error_callback
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
call: function (method, args, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/call', {
|
||||
model: this.model,
|
||||
@@ -338,6 +389,17 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Calls an arbitrary method, with more crazy
|
||||
*
|
||||
* @param {String} method
|
||||
* @param {Array} [args]
|
||||
* @param {Number} [domain_id] index of a domain to evaluate in the args array
|
||||
* @param {Number} [context_id] index of a context to evaluate in the args array
|
||||
* @param {Function} callback
|
||||
* @param {Function }error_callback
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
call_and_eval: function (method, args, domain_id, context_id, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/call', {
|
||||
model: this.model,
|
||||
@@ -347,6 +409,15 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Calls a button method, usually returning some sort of action
|
||||
*
|
||||
* @param {String} method
|
||||
* @param {Array} [args]
|
||||
* @param {Function} callback
|
||||
* @param {Function} error_callback
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
call_button: function (method, args, callback, error_callback) {
|
||||
return this.rpc('/base/dataset/call_button', {
|
||||
model: this.model,
|
||||
@@ -356,17 +427,34 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
args: args || []
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
* Fetches the "readable name" for records, based on intrinsic rules
|
||||
*
|
||||
* @param {Array} ids
|
||||
* @param {Function} callback
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
name_get: function(ids, callback) {
|
||||
return this.call_and_eval('name_get', [ids, this.get_context()], null, 1, callback);
|
||||
},
|
||||
/*
|
||||
* args = domain
|
||||
/**
|
||||
*
|
||||
* @param {String} name name to perform a search for/on
|
||||
* @param {Array} [domain=[]] filters for the objects returned, OpenERP domain
|
||||
* @param {String} [operator='ilike'] matching operator to use with the provided name value
|
||||
* @param {Number} [limit=100] maximum number of matches to return
|
||||
* @param {Function} callback function to call with name_search result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
name_search: function (name, args, operator, limit, callback) {
|
||||
name_search: function (name, domain, operator, limit, callback) {
|
||||
return this.call_and_eval('name_search',
|
||||
[name || '', args || false, operator || 'ilike', this.get_context(), limit || 100],
|
||||
[name || '', domain || false, operator || 'ilike', this.get_context(), limit || 100],
|
||||
1, 3, callback);
|
||||
},
|
||||
/**
|
||||
* @param name
|
||||
* @param callback
|
||||
*/
|
||||
name_create: function(name, callback) {
|
||||
return this.call_and_eval('name_create', [name, this.get_context()], null, 1, callback);
|
||||
},
|
||||
@@ -377,7 +465,10 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
signal: signal
|
||||
}, callback);
|
||||
},
|
||||
get_context: function() {
|
||||
get_context: function(request_context) {
|
||||
if (request_context) {
|
||||
return new openerp.base.CompoundContext(this.context, request_context);
|
||||
}
|
||||
return this.context;
|
||||
}
|
||||
});
|
||||
@@ -387,9 +478,11 @@ openerp.base.DataSetStatic = openerp.base.DataSet.extend({
|
||||
// all local records
|
||||
this.ids = ids || [];
|
||||
},
|
||||
read_slice: function (fields, offset, limit, callback) {
|
||||
var self = this;
|
||||
offset = offset || 0;
|
||||
read_slice: function (options, callback) {
|
||||
var self = this,
|
||||
offset = options.offset || 0,
|
||||
limit = options.limit || false,
|
||||
fields = options.fields || false;
|
||||
var end_pos = limit && limit !== -1 ? offset + limit : undefined;
|
||||
return this.read_ids(this.ids.slice(offset, end_pos), fields, callback);
|
||||
},
|
||||
@@ -426,25 +519,30 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
||||
// is it necessary ?
|
||||
this.ids = [];
|
||||
},
|
||||
read_slice: function (fields, offset, limit, callback) {
|
||||
/**
|
||||
* Read a slice of the records represented by this DataSet, based on its
|
||||
* domain and context.
|
||||
*
|
||||
* @params {Object} options
|
||||
* @param {Array} [options.fields] fields to read and return, by default all fields are returned
|
||||
* @param {Object} [options.context] context data to add to the request payload, on top of the DataSet's own context
|
||||
* @param {Array} [options.domain] domain data to add to the request payload, ANDed with the dataset's domain
|
||||
* @param {Number} [options.offset=0] The index from which selected records should be returned
|
||||
* @param {Number} [options.limit=null] The maximum number of records to return
|
||||
* @param {Function} callback function called with read_slice result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_slice: function (options, callback) {
|
||||
var self = this;
|
||||
offset = offset || 0;
|
||||
// cached search, not sure it's a good idea
|
||||
if(this.offset <= offset) {
|
||||
var start = offset - this.offset;
|
||||
if(this.ids.length - start >= limit) {
|
||||
// TODO: check if this could work do only read if possible
|
||||
// return read_ids(ids.slice(start,start+limit),fields,callback)
|
||||
}
|
||||
}
|
||||
var offset = options.offset || 0;
|
||||
return this.rpc('/base/dataset/search_read', {
|
||||
model: this.model,
|
||||
fields: fields,
|
||||
domain: this.domain,
|
||||
context: this.get_context(),
|
||||
fields: options.fields || false,
|
||||
domain: this.get_domain(options.domain),
|
||||
context: this.get_context(options.context),
|
||||
sort: this.sort(),
|
||||
offset: offset,
|
||||
limit: limit
|
||||
limit: options.limit || false
|
||||
}, function (result) {
|
||||
self.ids = result.ids;
|
||||
self.offset = offset;
|
||||
@@ -453,6 +551,12 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
get_domain: function (other_domain) {
|
||||
if (other_domain) {
|
||||
return new openerp.base.CompoundDomain(this.domain, other_domain);
|
||||
}
|
||||
return this.domain;
|
||||
},
|
||||
/**
|
||||
* Reads or changes sort criteria on the dataset.
|
||||
*
|
||||
@@ -628,48 +732,51 @@ openerp.base.ReadOnlyDataSetSearch = openerp.base.DataSetSearch.extend({
|
||||
on_unlink: function(ids) {}
|
||||
});
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
};
|
||||
openerp.base.CompoundContext = openerp.base.Class.extend({
|
||||
init: function () {
|
||||
this.__ref = "compound_context";
|
||||
this.__contexts = [];
|
||||
this.__eval_context = null;
|
||||
var self = this;
|
||||
_.each(arguments, function(x) {
|
||||
self.add(x);
|
||||
});
|
||||
},
|
||||
add: function (context) {
|
||||
this.__contexts.push(context);
|
||||
return this;
|
||||
},
|
||||
set_eval_context: function (eval_context) {
|
||||
this.__eval_context = eval_context;
|
||||
return this;
|
||||
},
|
||||
get_eval_context: function () {
|
||||
return this.__eval_context;
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.CompoundDomain = openerp.base.Class.extend({
|
||||
init: function () {
|
||||
this.__ref = "compound_domain";
|
||||
this.__domains = [];
|
||||
this.__eval_context = null;
|
||||
var self = this;
|
||||
_.each(arguments, function(x) {
|
||||
self.add(x);
|
||||
});
|
||||
},
|
||||
add: function(domain) {
|
||||
this.__domains.push(domain);
|
||||
return this;
|
||||
},
|
||||
set_eval_context: function(eval_context) {
|
||||
this.__eval_context = eval_context;
|
||||
return this;
|
||||
},
|
||||
get_eval_context: function() {
|
||||
return this.__eval_context;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
|
||||
openerp.base.dates = function(openerp) {
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone is assumed to be UTC (standard for OpenERP 6.1)
|
||||
* and will be converted to the browser's timezone.
|
||||
*
|
||||
* @param {String} str A string representing a datetime.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_datetime = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
var obj = Date.parse(str + " GMT");
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {String} str A string representing a date.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_date = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {String} str A string representing a time.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_time = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/*
|
||||
* Just a simple function to add some '0' if an integer it too small.
|
||||
*/
|
||||
var fts = function(str, size) {
|
||||
str = "" + str;
|
||||
var to_add = "";
|
||||
_.each(_.range(size - str.length), function() {
|
||||
to_add = to_add + "0";
|
||||
});
|
||||
return to_add + str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone of the Date object is assumed to be the one of the
|
||||
* browser and it will be converted to UTC (standard for OpenERP 6.1).
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a datetime.
|
||||
*/
|
||||
openerp.base.format_datetime = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return fts(obj.getUTCFullYear(),4) + "-" + fts(obj.getUTCMonth() + 1,2) + "-"
|
||||
+ fts(obj.getUTCDate(),2) + " " + fts(obj.getUTCHours(),2) + ":"
|
||||
+ fts(obj.getUTCMinutes(),2) + ":" + fts(obj.getUTCSeconds(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a date.
|
||||
*/
|
||||
openerp.base.format_date = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return fts(obj.getFullYear(),4) + "-" + fts(obj.getMonth() + 1,2) + "-"
|
||||
+ fts(obj.getDate(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a time.
|
||||
*/
|
||||
openerp.base.format_time = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return fts(obj.getHours(),2) + ":" + fts(obj.getMinutes(),2) + ":"
|
||||
+ fts(obj.getSeconds(),2);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -451,12 +451,14 @@ openerp.base.form.SidebarAttachments = openerp.base.Widget.extend({
|
||||
this.on_attachments_loaded([]);
|
||||
} else {
|
||||
(new openerp.base.DataSetSearch(
|
||||
this, 'ir.attachment', this.view.dataset.get_context(),
|
||||
[['res_model', '=', this.view.dataset.model],
|
||||
['res_id', '=', this.view.datarecord.id],
|
||||
['type', 'in', ['binary', 'url']]])).read_slice(
|
||||
['name', 'url', 'type'], false, false,
|
||||
this.on_attachments_loaded);
|
||||
this, 'ir.attachment', this.view.dataset.get_context(),
|
||||
[
|
||||
['res_model', '=', this.view.dataset.model],
|
||||
['res_id', '=', this.view.datarecord.id],
|
||||
['type', 'in', ['binary', 'url']]
|
||||
])).read_slice(
|
||||
{fields: ['name', 'url', 'type']},
|
||||
this.on_attachments_loaded);
|
||||
}
|
||||
},
|
||||
on_attachments_loaded: function(attachments) {
|
||||
@@ -510,36 +512,40 @@ openerp.base.form.compute_domain = function(expr, fields) {
|
||||
}
|
||||
}
|
||||
|
||||
var field = fields[ex[0]].get_value ? fields[ex[0]].get_value() : fields[ex[0]].value;
|
||||
var field = fields[ex[0]];
|
||||
if (!field) {
|
||||
throw new Error("Domain references unknown field : " + ex[0]);
|
||||
}
|
||||
var field_value = field.get_value ? fields[ex[0]].get_value() : fields[ex[0]].value;
|
||||
var op = ex[1];
|
||||
var val = ex[2];
|
||||
|
||||
switch (op.toLowerCase()) {
|
||||
case '=':
|
||||
case '==':
|
||||
stack.push(field == val);
|
||||
stack.push(field_value == val);
|
||||
break;
|
||||
case '!=':
|
||||
case '<>':
|
||||
stack.push(field != val);
|
||||
stack.push(field_value != val);
|
||||
break;
|
||||
case '<':
|
||||
stack.push(field < val);
|
||||
stack.push(field_value < val);
|
||||
break;
|
||||
case '>':
|
||||
stack.push(field > val);
|
||||
stack.push(field_value > val);
|
||||
break;
|
||||
case '<=':
|
||||
stack.push(field <= val);
|
||||
stack.push(field_value <= val);
|
||||
break;
|
||||
case '>=':
|
||||
stack.push(field >= val);
|
||||
stack.push(field_value >= val);
|
||||
break;
|
||||
case 'in':
|
||||
stack.push(_(val).contains(field));
|
||||
stack.push(_(val).contains(field_value));
|
||||
break;
|
||||
case 'not in':
|
||||
stack.push(!_(val).contains(field));
|
||||
stack.push(!_(val).contains(field_value));
|
||||
break;
|
||||
default:
|
||||
this.log("Unsupported operator in modifiers :", op);
|
||||
@@ -767,8 +773,7 @@ openerp.base.form.WidgetButton = openerp.base.form.Widget.extend({
|
||||
var self = this;
|
||||
|
||||
this.view.execute_action(
|
||||
this.node.attrs, this.view.dataset, this.session.action_manager,
|
||||
this.view.datarecord.id, function () {
|
||||
this.node.attrs, this.view.dataset, this.view.datarecord.id, function () {
|
||||
self.view.reload();
|
||||
});
|
||||
}
|
||||
@@ -803,7 +808,7 @@ openerp.base.form.WidgetLabel = openerp.base.form.Widget.extend({
|
||||
var self = this;
|
||||
this.$element.find("label").dblclick(function() {
|
||||
var widget = self['for'] || self;
|
||||
console.log(widget.element_id , widget);
|
||||
self.log(widget.element_id , widget);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1315,7 +1320,7 @@ openerp.base.form.dialog = function(content, options) {
|
||||
}, options || {});
|
||||
options.autoOpen = true;
|
||||
var dialog = new openerp.base.Dialog(null, options);
|
||||
dialog.$dialog = $(content).dialog(dialog.options);
|
||||
dialog.$dialog = $(content).dialog(dialog.dialog_options);
|
||||
return dialog.$dialog;
|
||||
}
|
||||
|
||||
@@ -1501,7 +1506,6 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
var dataset = new openerp.base.DataSetStatic(self, self.field.relation, self.build_context());
|
||||
dataset.name_get([element_ids[0]], function(data) {
|
||||
self._change_int_ext_value(data[0]);
|
||||
pop.stop();
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -1648,7 +1652,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
});
|
||||
this.views = views;
|
||||
|
||||
this.viewmanager = new openerp.base.ViewManager(this, this.element_id, this.dataset, views);
|
||||
this.viewmanager = new openerp.base.ViewManager(this, this.dataset, views);
|
||||
this.viewmanager.registry = openerp.base.views.clone({
|
||||
list: 'openerp.base.form.One2ManyListView',
|
||||
form: 'openerp.base.form.One2ManyFormView'
|
||||
@@ -1674,7 +1678,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
self.save_form_view();
|
||||
});
|
||||
setTimeout(function () {
|
||||
self.viewmanager.start();
|
||||
self.viewmanager.appendTo(self.$element);
|
||||
}, 0);
|
||||
},
|
||||
reload_current_view: function() {
|
||||
@@ -1837,16 +1841,16 @@ 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,
|
||||
create_function: function(data) {
|
||||
return self.o2m.dataset.create(data, function(r) {
|
||||
self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r.result]));
|
||||
self.o2m.dataset.on_change();
|
||||
});
|
||||
},
|
||||
parent_view: self.o2m.view
|
||||
}, self.o2m.build_domain(), self.o2m.build_context());
|
||||
pop.on_create.add(function(data) {
|
||||
self.o2m.dataset.create(data, function(r) {
|
||||
self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r.result]));
|
||||
self.o2m.dataset.on_change();
|
||||
pop.stop();
|
||||
self.o2m.reload_current_view();
|
||||
});
|
||||
pop.on_select_elements.add_last(function() {
|
||||
self.o2m.reload_current_view();
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -1885,7 +1889,7 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
||||
self.on_ui_change();
|
||||
});
|
||||
|
||||
this.list_view = new openerp.base.form.Many2ManyListView(new openerp.base.NullViewManager(this), this.list_id, this.dataset, false, {
|
||||
this.list_view = new openerp.base.form.Many2ManyListView(this, this.list_id, this.dataset, false, {
|
||||
'addable': 'Add',
|
||||
'selectable': self.multi_selection
|
||||
});
|
||||
@@ -1941,7 +1945,6 @@ openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
||||
self.reload_content();
|
||||
}
|
||||
});
|
||||
pop.stop();
|
||||
});
|
||||
},
|
||||
do_activate_record: function(index, id) {
|
||||
@@ -1963,16 +1966,22 @@ openerp.base.form.SelectCreatePopup = openerp.base.OldWidget.extend({
|
||||
* - initial_view: form or search (default search)
|
||||
* - disable_multiple_selection
|
||||
* - alternative_form_view
|
||||
* - auto_create (default true)
|
||||
* - create_function (defaults to a naive saving behavior)
|
||||
* - parent_view
|
||||
*/
|
||||
select_element: function(model, options, domain, context) {
|
||||
var self = this;
|
||||
this.model = model;
|
||||
this.domain = domain || [];
|
||||
this.context = context || {};
|
||||
this.options = _.defaults(options || {}, {"initial_view": "search", "auto_create": true});
|
||||
this.options = _.defaults(options || {}, {"initial_view": "search", "create_function": function() {
|
||||
return self.create_row.apply(self, arguments);
|
||||
}});
|
||||
this.initial_ids = this.options.initial_ids;
|
||||
openerp.base.form.dialog(this.render());
|
||||
this.created_elements = [];
|
||||
openerp.base.form.dialog(this.render(), {close:function() {
|
||||
self.check_exit();
|
||||
}});
|
||||
this.start();
|
||||
},
|
||||
start: function() {
|
||||
@@ -2018,6 +2027,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.OldWidget.extend({
|
||||
}
|
||||
$sbutton.click(function() {
|
||||
self.on_select_elements(self.selected_ids);
|
||||
self.stop();
|
||||
});
|
||||
self.view_list = new openerp.base.form.SelectCreateListView(self,
|
||||
self.element_id + "_view_list", self.dataset, false,
|
||||
@@ -2030,15 +2040,11 @@ openerp.base.form.SelectCreatePopup = openerp.base.OldWidget.extend({
|
||||
});
|
||||
this.searchview.start();
|
||||
},
|
||||
on_create: function(data) {
|
||||
if (!this.options.auto_create)
|
||||
return;
|
||||
create_row: function(data) {
|
||||
var self = this;
|
||||
var wdataset = new openerp.base.DataSetSearch(this, this.model, this.context, this.domain);
|
||||
wdataset.parent_view = this.options.parent_view;
|
||||
wdataset.create(data, function(r) {
|
||||
self.on_select_elements([r.result]);
|
||||
});
|
||||
return wdataset.create(data);
|
||||
},
|
||||
on_select_elements: function(element_ids) {
|
||||
},
|
||||
@@ -2066,18 +2072,43 @@ openerp.base.form.SelectCreatePopup = openerp.base.OldWidget.extend({
|
||||
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("SelectCreatePopup.form.buttons"));
|
||||
$buttons.html(QWeb.render("SelectCreatePopup.form.buttons", {widget:self}));
|
||||
var $nbutton = $buttons.find(".oe_selectcreatepopup-form-save-new");
|
||||
$nbutton.click(function() {
|
||||
self._created = $.Deferred().then(function() {
|
||||
self._created = undefined;
|
||||
self.view_form.on_button_new();
|
||||
});
|
||||
self.view_form.do_save();
|
||||
});
|
||||
var $nbutton = $buttons.find(".oe_selectcreatepopup-form-save");
|
||||
$nbutton.click(function() {
|
||||
self._created = $.Deferred().then(function() {
|
||||
self._created = undefined;
|
||||
self.check_exit();
|
||||
});
|
||||
self.view_form.do_save();
|
||||
});
|
||||
var $cbutton = $buttons.find(".oe_selectcreatepopup-form-close");
|
||||
$cbutton.click(function() {
|
||||
self.stop();
|
||||
self.check_exit();
|
||||
});
|
||||
});
|
||||
this.dataset.on_create.add(function(data) {
|
||||
self.options.create_function(data).then(function(r) {
|
||||
self.created_elements.push(r.result);
|
||||
if (self._created) {
|
||||
self._created.resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
this.dataset.on_create.add(this.on_create);
|
||||
this.view_form.do_show();
|
||||
},
|
||||
check_exit: function() {
|
||||
if (this.created_elements.length > 0) {
|
||||
this.on_select_elements(this.created_elements);
|
||||
}
|
||||
this.stop();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2087,6 +2118,7 @@ openerp.base.form.SelectCreateListView = openerp.base.ListView.extend({
|
||||
},
|
||||
select_record: function(index) {
|
||||
this.popup.on_select_elements([this.dataset.ids[index]]);
|
||||
this.popup.stop();
|
||||
},
|
||||
do_select: function(ids, records) {
|
||||
this._super(ids, records);
|
||||
@@ -2210,8 +2242,8 @@ openerp.base.form.FieldBinary = openerp.base.form.Field.extend({
|
||||
delete(window[this.iframe]);
|
||||
if (size === false) {
|
||||
this.notification.warn("File Upload", "There was a problem while uploading your file");
|
||||
// TODO: use openerp web exception handler
|
||||
console.log("Error while uploading file : ", name);
|
||||
// TODO: use openerp web crashmanager
|
||||
this.log("Error while uploading file : ", name);
|
||||
} else {
|
||||
this.on_file_uploaded_and_valid.apply(this, arguments);
|
||||
this.on_ui_change();
|
||||
@@ -2320,10 +2352,8 @@ openerp.base.form.widgets = new openerp.base.Registry({
|
||||
'url' : 'openerp.base.form.FieldUrl',
|
||||
'text' : 'openerp.base.form.FieldText',
|
||||
'text_wiki' : 'openerp.base.form.FieldText',
|
||||
// 'date' : 'openerp.base.form.FieldDate',
|
||||
// 'datetime' : 'openerp.base.form.FieldDatetime',
|
||||
'date' : 'openerp.base.form.FieldChar',
|
||||
'datetime' : 'openerp.base.form.FieldChar',
|
||||
'date' : 'openerp.base.form.FieldDate',
|
||||
'datetime' : 'openerp.base.form.FieldDatetime',
|
||||
'selection' : 'openerp.base.form.FieldSelection',
|
||||
'many2one' : 'openerp.base.form.FieldMany2One',
|
||||
'many2many' : 'openerp.base.form.FieldMany2Many',
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
|
||||
openerp.base.formats = function(openerp) {
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone is assumed to be UTC (standard for OpenERP 6.1)
|
||||
* and will be converted to the browser's timezone.
|
||||
*
|
||||
* @param {String} str A string representing a datetime.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_datetime = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
var obj = Date.parse(str + " GMT");
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {String} str A string representing a date.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_date = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {String} str A string representing a time.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_time = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/*
|
||||
* Left-pad provided arg 1 with zeroes until reaching size provided by second
|
||||
* argument.
|
||||
*
|
||||
* @param {Number|String} str value to pad
|
||||
* @param {Number} size size to reach on the final padded value
|
||||
* @returns {String} padded string
|
||||
*/
|
||||
var zpad = function(str, size) {
|
||||
str = "" + str;
|
||||
return new Array(size - str.length + 1).join('0') + str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone of the Date object is assumed to be the one of the
|
||||
* browser and it will be converted to UTC (standard for OpenERP 6.1).
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a datetime.
|
||||
*/
|
||||
openerp.base.format_datetime = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getUTCFullYear(),4) + "-" + zpad(obj.getUTCMonth() + 1,2) + "-"
|
||||
+ zpad(obj.getUTCDate(),2) + " " + zpad(obj.getUTCHours(),2) + ":"
|
||||
+ zpad(obj.getUTCMinutes(),2) + ":" + zpad(obj.getUTCSeconds(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a date.
|
||||
*/
|
||||
openerp.base.format_date = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getFullYear(),4) + "-" + zpad(obj.getMonth() + 1,2) + "-"
|
||||
+ zpad(obj.getDate(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a time.
|
||||
*/
|
||||
openerp.base.format_time = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getHours(),2) + ":" + zpad(obj.getMinutes(),2) + ":"
|
||||
+ zpad(obj.getSeconds(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a single atomic value based on a field descriptor
|
||||
*
|
||||
* @param {Object} value read from OpenERP
|
||||
* @param {Object} descriptor union of orm field and view field
|
||||
* @param {Object} [descriptor.widget] widget to use to display the value
|
||||
* @param {Object} descriptor.type fallback if no widget is provided, or if the provided widget is unknown
|
||||
* @param {Object} [descriptor.digits] used for the formatting of floats
|
||||
* @param {String} [value_if_empty=''] returned if the ``value`` argument is considered empty
|
||||
*/
|
||||
openerp.base.format_value = function (value, descriptor, value_if_empty) {
|
||||
// If NaN value, display as with a `false` (empty cell)
|
||||
if (typeof value === 'number' && isNaN(value)) {
|
||||
value = false;
|
||||
}
|
||||
switch (value) {
|
||||
case false:
|
||||
case Infinity:
|
||||
case -Infinity:
|
||||
return value_if_empty === undefined ? '' : value_if_empty;
|
||||
}
|
||||
switch (descriptor.widget || descriptor.type) {
|
||||
case 'integer':
|
||||
return _.sprintf('%d', value);
|
||||
case 'float':
|
||||
var precision = descriptor.digits ? descriptor.digits[1] : 2;
|
||||
return _.sprintf('%.' + precision + 'f', value);
|
||||
case 'float_time':
|
||||
return _.sprintf("%02d:%02d",
|
||||
Math.floor(value),
|
||||
Math.round((value % 1) * 60));
|
||||
case 'progressbar':
|
||||
return _.sprintf(
|
||||
'<progress value="%.2f" max="100.0">%.2f%%</progress>',
|
||||
value, value);
|
||||
case 'many2one':
|
||||
// name_get value format
|
||||
return value[1];
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a provided cell based on its field type
|
||||
*
|
||||
* @param {Object} row_data record whose values should be displayed in the cell
|
||||
* @param {Object} column column descriptor
|
||||
* @param {"button"|"field"} column.tag base control type
|
||||
* @param {String} column.type widget type for a field control
|
||||
* @param {String} [column.string] button label
|
||||
* @param {String} [column.icon] button icon
|
||||
* @param {String} [value_if_empty=''] what to display if the field's value is ``false``
|
||||
*/
|
||||
openerp.base.format_cell = function (row_data, column, value_if_empty) {
|
||||
var attrs = column.modifiers_for(row_data);
|
||||
if (attrs.invisible) { return ''; }
|
||||
if (column.tag === 'button') {
|
||||
return [
|
||||
'<button type="button" title="', column.string || '', '">',
|
||||
'<img src="/base/static/src/img/icons/', column.icon, '.png"',
|
||||
' alt="', column.string || '', '"/>',
|
||||
'</button>'
|
||||
].join('')
|
||||
}
|
||||
|
||||
return openerp.base.format_value(
|
||||
row_data[column.id].value, column, value_if_empty);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,63 +1,5 @@
|
||||
openerp.base.list = function (openerp) {
|
||||
openerp.base.views.add('list', 'openerp.base.ListView');
|
||||
openerp.base.list = {
|
||||
/**
|
||||
* Formats the rendring of a given value based on its field type
|
||||
*
|
||||
* @param {Object} row_data record whose values should be displayed in the cell
|
||||
* @param {Object} column column descriptor
|
||||
* @param {"button"|"field"} column.tag base control type
|
||||
* @param {String} column.type widget type for a field control
|
||||
* @param {String} [column.string] button label
|
||||
* @param {String} [column.icon] button icon
|
||||
* @param {String} [value_if_empty=''] what to display if the field's value is ``false``
|
||||
*/
|
||||
render_cell: function (row_data, column, value_if_empty) {
|
||||
var attrs = column.modifiers_for(row_data);
|
||||
if (attrs.invisible) { return ''; }
|
||||
if (column.tag === 'button') {
|
||||
return [
|
||||
'<button type="button" title="', column.string || '', '">',
|
||||
'<img src="/base/static/src/img/icons/', column.icon, '.png"',
|
||||
' alt="', column.string || '', '"/>',
|
||||
'</button>'
|
||||
].join('')
|
||||
}
|
||||
|
||||
var value = row_data[column.id].value;
|
||||
|
||||
// If NaN value, display as with a `false` (empty cell)
|
||||
if (typeof value === 'number' && isNaN(value)) {
|
||||
value = false;
|
||||
}
|
||||
switch (value) {
|
||||
case false:
|
||||
case Infinity:
|
||||
case -Infinity:
|
||||
return value_if_empty === undefined ? '' : value_if_empty;
|
||||
}
|
||||
switch (column.widget || column.type) {
|
||||
case 'integer':
|
||||
return _.sprintf('%d', value);
|
||||
case 'float':
|
||||
var precision = column.digits ? column.digits[1] : 2;
|
||||
return _.sprintf('%.' + precision + 'f', value);
|
||||
case 'float_time':
|
||||
return _.sprintf("%02d:%02d",
|
||||
Math.floor(value),
|
||||
Math.round((value % 1) * 60));
|
||||
case 'progressbar':
|
||||
return _.sprintf(
|
||||
'<progress value="%.2f" max="100.0">%.2f%%</progress>',
|
||||
value, value);
|
||||
case 'many2one':
|
||||
// name_get value format
|
||||
return value[1];
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
};
|
||||
openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListView# */ {
|
||||
defaults: {
|
||||
// records can be selected one by one
|
||||
@@ -119,7 +61,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
/**
|
||||
* Retrieves the view's number of records per page (|| section)
|
||||
*
|
||||
* options > defaults > indefinite
|
||||
* options > defaults > parent.action.limit > indefinite
|
||||
*
|
||||
* @returns {Number|null}
|
||||
*/
|
||||
@@ -127,6 +69,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
if (this._limit === undefined) {
|
||||
this._limit = (this.options.limit
|
||||
|| this.defaults.limit
|
||||
|| (this.widget_parent.action || {}).limit
|
||||
|| null);
|
||||
}
|
||||
return this._limit;
|
||||
@@ -152,7 +95,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
self.do_delete(ids);
|
||||
},
|
||||
'action': function (e, action_name, id, callback) {
|
||||
self.do_action(action_name, id, callback);
|
||||
self.do_button_action(action_name, id, callback);
|
||||
},
|
||||
'row_link': function (e, id, dataset) {
|
||||
self.do_activate_record(dataset.index, id, dataset);
|
||||
@@ -409,8 +352,9 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
* Reloads the list view based on the current settings (dataset & al)
|
||||
*
|
||||
* @param {Boolean} [grouped] Should the list be displayed grouped
|
||||
* @param {Object} [context] context to send the server while loading the view
|
||||
*/
|
||||
reload_view: function (grouped) {
|
||||
reload_view: function (grouped, context) {
|
||||
var self = this;
|
||||
var callback = function (field_view_get) {
|
||||
self.on_loaded(field_view_get, grouped);
|
||||
@@ -421,7 +365,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
return this.rpc('/base/listview/load', {
|
||||
model: this.model,
|
||||
view_id: this.view_id,
|
||||
context: this.dataset.get_context(),
|
||||
context: this.dataset.get_context(context),
|
||||
toolbar: this.options.sidebar
|
||||
}, callback);
|
||||
}
|
||||
@@ -457,11 +401,10 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
* @param {Object} results results of evaluating domain and process for a search
|
||||
*/
|
||||
do_actual_search: function (results) {
|
||||
this.dataset.context = results.context;
|
||||
this.dataset.domain = results.domain;
|
||||
this.groups.datagroup = new openerp.base.DataGroup(
|
||||
this, this.model,
|
||||
results.domain, results.context,
|
||||
this.dataset.get_domain(results.domain),
|
||||
this.dataset.get_context(results.context),
|
||||
results.group_by);
|
||||
this.groups.datagroup.sort = this.dataset._sort;
|
||||
|
||||
@@ -469,7 +412,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
results.group_by = null;
|
||||
}
|
||||
|
||||
this.reload_view(!!results.group_by).then(
|
||||
this.reload_view(!!results.group_by, results.context).then(
|
||||
$.proxy(this, 'reload_content'));
|
||||
},
|
||||
/**
|
||||
@@ -512,17 +455,16 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
* @param {Object} id id of the record the action should be called on
|
||||
* @param {Function} callback should be called after the action is executed, if non-null
|
||||
*/
|
||||
do_action: function (name, id, callback) {
|
||||
do_button_action: function (name, id, callback) {
|
||||
var self = this,
|
||||
action = _.detect(this.columns, function (field) {
|
||||
return field.name === name;
|
||||
});
|
||||
if (!action) { return; }
|
||||
this.execute_action(
|
||||
action, this.dataset, this.session.action_manager, id, function () {
|
||||
$.when(callback.apply(this, arguments).then(function () {
|
||||
self.compute_aggregates();
|
||||
}));
|
||||
this.execute_action(action, this.dataset, id, function () {
|
||||
$.when(callback.apply(this, arguments).then(function () {
|
||||
self.compute_aggregates();
|
||||
}));
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -534,11 +476,11 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
*/
|
||||
do_activate_record: function (index, id, dataset) {
|
||||
var self = this;
|
||||
_.extend(this.dataset, {
|
||||
domain: dataset.domain,
|
||||
context: dataset.get_context()
|
||||
}).read_slice([], 0, false, function () {
|
||||
self.select_record(index);
|
||||
this.dataset.read_slice({
|
||||
context: dataset.get_context(),
|
||||
domain: dataset.get_domain()
|
||||
}, function () {
|
||||
self.select_record(index);
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -637,7 +579,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
}
|
||||
|
||||
$footer_cells.filter(_.sprintf('[data-field=%s]', column.id))
|
||||
.html(openerp.base.list.render_cell(aggregation, column));
|
||||
.html(openerp.base.format_cell(aggregation, column));
|
||||
});
|
||||
}
|
||||
// TODO: implement reorder (drag and drop rows)
|
||||
@@ -725,7 +667,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
||||
this.$current = this.$_element.clone(true);
|
||||
this.$current.empty().append(
|
||||
QWeb.render('ListView.rows', _.extend({
|
||||
render_cell: openerp.base.list.render_cell}, this)));
|
||||
render_cell: openerp.base.format_cell}, this)));
|
||||
},
|
||||
/**
|
||||
* Gets the ids of all currently selected records, if any
|
||||
@@ -830,7 +772,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
||||
var old_index = this.dataset.index;
|
||||
this.dataset.index = record_index;
|
||||
read_p = this.dataset.read_index(
|
||||
_.filter(_.pluck(this.columns, 'name'), _.identity),
|
||||
_.pluck(_(this.columns).filter(function (r) {return r.tag === 'field';}), 'name'),
|
||||
function (record) {
|
||||
var form_record = self.transform_record(record);
|
||||
self.rows.splice(record_index, 1, form_record);
|
||||
@@ -856,7 +798,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
||||
row: this.rows[record_index],
|
||||
row_parity: (record_index % 2 === 0) ? 'even' : 'odd',
|
||||
row_index: record_index,
|
||||
render_cell: openerp.base.list.render_cell
|
||||
render_cell: openerp.base.format_cell
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -1016,7 +958,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
|
||||
row_data[group.grouped_on] = group;
|
||||
var group_column = _(self.columns).detect(function (column) {
|
||||
return column.id === group.grouped_on; });
|
||||
$group_column.html(openerp.base.list.render_cell(
|
||||
$group_column.html(openerp.base.format_cell(
|
||||
row_data, group_column, "Undefined"
|
||||
));
|
||||
if (group.openable) {
|
||||
@@ -1092,10 +1034,11 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
|
||||
d = new $.Deferred(),
|
||||
page = this.datagroup.openable ? this.page : view.page;
|
||||
|
||||
dataset.read_slice(
|
||||
_.filter(_.pluck(_.select(this.columns, function(x) {return x.tag == "field";}), 'name'), _.identity),
|
||||
page * limit, limit,
|
||||
function (records) {
|
||||
dataset.read_slice({
|
||||
fields: _.pluck(_.select(this.columns, function(x) {return x.tag == "field"}), 'name'),
|
||||
offset: page * limit,
|
||||
limit: limit
|
||||
}, function (records) {
|
||||
if (!self.datagroup.openable) {
|
||||
view.configure_pager(dataset);
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,6 @@ openerp.base.search = function(openerp) {
|
||||
openerp.base.SearchView = openerp.base.Widget.extend({
|
||||
init: function(parent, element_id, dataset, view_id, defaults) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
@@ -362,9 +361,9 @@ openerp.base.search.fields = new openerp.base.Registry({
|
||||
'selection': 'openerp.base.search.SelectionField',
|
||||
'datetime': 'openerp.base.search.DateTimeField',
|
||||
'date': 'openerp.base.search.DateField',
|
||||
'one2many': 'openerp.base.search.OneToManyField',
|
||||
'many2one': 'openerp.base.search.ManyToOneField',
|
||||
'many2many': 'openerp.base.search.ManyToManyField'
|
||||
'many2many': 'openerp.base.search.CharField',
|
||||
'one2many': 'openerp.base.search.CharField'
|
||||
});
|
||||
openerp.base.search.Invalid = openerp.base.Class.extend( /** @lends openerp.base.search.Invalid# */{
|
||||
/**
|
||||
@@ -624,39 +623,6 @@ openerp.base.search.CharField = openerp.base.search.Field.extend( /** @lends ope
|
||||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
openerp.base.search.BooleanField = openerp.base.search.Field.extend({
|
||||
template: 'SearchView.field.selection',
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.attrs.selection = [
|
||||
['true', 'Yes'],
|
||||
['false', 'No']
|
||||
];
|
||||
},
|
||||
/**
|
||||
* Search defaults likely to be boolean values (for a boolean field).
|
||||
*
|
||||
* In the HTML, we only get strings, and our strings here are
|
||||
* <code>'true'</code> and <code>'false'</code>, so ensure we get only
|
||||
* those by truth-testing the default value.
|
||||
*
|
||||
* @param {Object} defaults default values for this search view
|
||||
*/
|
||||
render: function (defaults) {
|
||||
var name = this.attrs.name;
|
||||
if (name in defaults) {
|
||||
defaults[name] = defaults[name] ? "true" : "false";
|
||||
}
|
||||
return this._super(defaults);
|
||||
},
|
||||
get_value: function () {
|
||||
switch (this.$element.val()) {
|
||||
case 'false': return false;
|
||||
case 'true': return true;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
openerp.base.search.NumberField = openerp.base.search.Field.extend(/** @lends openerp.base.search.NumberField# */{
|
||||
get_value: function () {
|
||||
if (!this.$element.val()) {
|
||||
@@ -693,93 +659,73 @@ openerp.base.search.FloatField = openerp.base.search.NumberField.extend(/** @len
|
||||
return parseFloat(value);
|
||||
}
|
||||
});
|
||||
openerp.base.search.SelectionField = openerp.base.search.Field.extend({
|
||||
/**
|
||||
* @class
|
||||
* @extends openerp.base.search.Field
|
||||
*/
|
||||
openerp.base.search.SelectionField = openerp.base.search.Field.extend(/** @lends openerp.base.search.SelectionField# */{
|
||||
template: 'SearchView.field.selection',
|
||||
get_value: function () {
|
||||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
openerp.base.search.BooleanField = openerp.base.search.SelectionField.extend(/** @lends openerp.base.search.BooleanField# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @extends openerp.base.search.BooleanField
|
||||
*/
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.attrs.selection = [
|
||||
['true', 'Yes'],
|
||||
['false', 'No']
|
||||
];
|
||||
},
|
||||
/**
|
||||
* Search defaults likely to be boolean values (for a boolean field).
|
||||
*
|
||||
* In the HTML, we only want/get strings, and our strings here are ``true``
|
||||
* and ``false``, so ensure we use precisely those by truth-testing the
|
||||
* default value (iif there is one in the view's defaults).
|
||||
*
|
||||
* @param {Object} defaults default values for this search view
|
||||
* @returns {String} rendered boolean field
|
||||
*/
|
||||
render: function (defaults) {
|
||||
var name = this.attrs.name;
|
||||
if (name in defaults) {
|
||||
defaults[name] = defaults[name] ? "true" : "false";
|
||||
}
|
||||
return this._super(defaults);
|
||||
},
|
||||
get_value: function () {
|
||||
switch (this.$element.val()) {
|
||||
case 'false': return false;
|
||||
case 'true': return true;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
openerp.base.search.DateField = openerp.base.search.Field.extend( /** @lends openerp.base.search.DateField# */{
|
||||
template: 'SearchView.fields.date',
|
||||
/**
|
||||
* enables date picker on the HTML widgets
|
||||
*/
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.find('input').datepicker({
|
||||
this.$element.addClass('field_date').datepicker({
|
||||
dateFormat: 'yy-mm-dd'
|
||||
});
|
||||
},
|
||||
stop: function () {
|
||||
this.$element.find('input').datepicker('destroy');
|
||||
this.$element.datepicker('destroy');
|
||||
},
|
||||
/**
|
||||
* Returns an object with two optional keys ``from`` and ``to`` providing
|
||||
* the values for resp. the from and to sections of the date widget.
|
||||
*
|
||||
* If a key is absent, then the corresponding field was not filled.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
get_values: function () {
|
||||
var values_array = this.$element.find('input').serializeArray();
|
||||
|
||||
if (!values_array || !values_array[0]) {
|
||||
throw new openerp.base.search.Invalid(
|
||||
this.attrs.name, null, "widget not ready");
|
||||
}
|
||||
var from = values_array[0].value,
|
||||
to = values_array[1].value;
|
||||
|
||||
var field_values = {};
|
||||
if (from) {
|
||||
field_values.from = from;
|
||||
}
|
||||
if (to) {
|
||||
field_values.to = to;
|
||||
}
|
||||
return field_values;
|
||||
},
|
||||
get_context: function () {
|
||||
var values = this.get_values();
|
||||
if (!this.attrs.context || _.isEmpty(values)) {
|
||||
return null;
|
||||
}
|
||||
return _.extend(
|
||||
{}, this.attrs.context,
|
||||
{own_values: {self: values}});
|
||||
},
|
||||
get_domain: function () {
|
||||
var values = this.get_values();
|
||||
if (_.isEmpty(values)) {
|
||||
return null;
|
||||
}
|
||||
var domain = this.attrs['filter_domain'];
|
||||
if (!domain) {
|
||||
domain = [];
|
||||
if (values.from) {
|
||||
domain.push([this.attrs.name, '>=', values.from]);
|
||||
}
|
||||
if (values.to) {
|
||||
domain.push([this.attrs.name, '<=', values.to]);
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
|
||||
return _.extend(
|
||||
{}, domain,
|
||||
{own_values: {self: values}});
|
||||
get_value: function () {
|
||||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
openerp.base.search.DateTimeField = openerp.base.search.DateField.extend({
|
||||
// TODO: time?
|
||||
});
|
||||
openerp.base.search.OneToManyField = openerp.base.search.CharField.extend({
|
||||
// TODO: .relation, .context, .domain
|
||||
});
|
||||
openerp.base.search.ManyToOneField = openerp.base.search.CharField.extend({
|
||||
// TODO: @widget
|
||||
// TODO: .selection, .context, .domain
|
||||
init: function (view_section, field, view) {
|
||||
this._super(view_section, field, view);
|
||||
var self = this;
|
||||
@@ -847,9 +793,6 @@ openerp.base.search.ManyToOneField = openerp.base.search.CharField.extend({
|
||||
return this._super();
|
||||
}
|
||||
});
|
||||
openerp.base.search.ManyToManyField = openerp.base.search.CharField.extend({
|
||||
// TODO: .related_columns (Array), .context, .domain
|
||||
});
|
||||
|
||||
openerp.base.search.ExtendedSearch = openerp.base.OldWidget.extend({
|
||||
template: 'SearchView.extended_search',
|
||||
@@ -932,11 +875,10 @@ openerp.base.search.ExtendedSearchGroup = openerp.base.OldWidget.extend({
|
||||
this._super();
|
||||
var _this = this;
|
||||
this.add_prop();
|
||||
this.$element.find('.searchview_extended_add_proposition').click(function (e) {
|
||||
this.$element.find('.searchview_extended_add_proposition').click(function () {
|
||||
_this.add_prop();
|
||||
});
|
||||
var delete_btn = this.$element.find('.searchview_extended_delete_group');
|
||||
delete_btn.click(function (e) {
|
||||
this.$element.find('.searchview_extended_delete_group').click(function () {
|
||||
_this.stop();
|
||||
});
|
||||
},
|
||||
@@ -946,7 +888,7 @@ openerp.base.search.ExtendedSearchGroup = openerp.base.OldWidget.extend({
|
||||
}).compact().value();
|
||||
var choice = this.$element.find(".searchview_extended_group_choice").val();
|
||||
var op = choice == "all" ? "&" : "|";
|
||||
return [].concat(choice == "none" ? ['!'] : [],
|
||||
return choice == "none" ? ['!'] : [].concat(
|
||||
_.map(_.range(_.max([0,props.length - 1])), function() { return op; }),
|
||||
props);
|
||||
},
|
||||
@@ -958,10 +900,7 @@ openerp.base.search.ExtendedSearchGroup = openerp.base.OldWidget.extend({
|
||||
parent.check_last_element();
|
||||
},
|
||||
set_last_group: function(is_last) {
|
||||
if(is_last)
|
||||
this.$element.addClass("last_group");
|
||||
else
|
||||
this.$element.removeClass("last_group");
|
||||
this.$element.toggleClass('last_group', is_last);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -984,8 +923,7 @@ openerp.base.search.ExtendedSearchProposition = openerp.base.OldWidget.extend({
|
||||
this.$element.find(".searchview_extended_prop_field").change(function() {
|
||||
_this.changed();
|
||||
});
|
||||
var delete_btn = this.$element.find('.searchview_extended_delete_prop');
|
||||
delete_btn.click(function (e) {
|
||||
this.$element.find('.searchview_extended_delete_prop').click(function () {
|
||||
_this.stop();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -5,22 +5,202 @@
|
||||
openerp.base.view_tree = function(openerp) {
|
||||
|
||||
openerp.base.views.add('tree', 'openerp.base.TreeView');
|
||||
openerp.base.TreeView = openerp.base.Widget.extend({
|
||||
/**
|
||||
* Genuine tree view (the one displayed as a tree, not the list)
|
||||
*/
|
||||
openerp.base.TreeView = openerp.base.View.extend({
|
||||
/**
|
||||
* Indicates that this view is not searchable, and thus that no search
|
||||
* view should be displayed (if there is one active).
|
||||
*/
|
||||
searchable : false,
|
||||
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
|
||||
this.records = {};
|
||||
|
||||
this.options = _.extend({}, this.defaults, options || {});
|
||||
},
|
||||
|
||||
start: function () {
|
||||
this._super();
|
||||
this.$element.append('Tree view');
|
||||
return this.rpc("/base/treeview/load", {
|
||||
model: this.model,
|
||||
view_id: this.view_id,
|
||||
toolbar: this.view_manager ? !!this.view_manager.sidebar : false
|
||||
}, this.on_loaded);
|
||||
},
|
||||
/**
|
||||
* Returns the list of fields needed to correctly read objects.
|
||||
*
|
||||
* Gathers the names of all fields in fields_view_get, and adds the
|
||||
* field_parent (children_field in the tree view) if it's not already one
|
||||
* of the fields to fetch
|
||||
*
|
||||
* @returns {Array} an array of fields which can be provided to DataSet.read_slice and others
|
||||
*/
|
||||
fields_list: function () {
|
||||
var fields = _.keys(this.fields);
|
||||
if (!_(fields).contains(this.children_field)) {
|
||||
fields.push(this.children_field);
|
||||
}
|
||||
return fields;
|
||||
},
|
||||
on_loaded: function (fields_view) {
|
||||
var self = this;
|
||||
var has_toolbar = !!fields_view.arch.attrs.toolbar;
|
||||
// field name in OpenERP is kinda stupid: this is the name of the field
|
||||
// holding the ids to the children of the current node, why call it
|
||||
// field_parent?
|
||||
this.children_field = fields_view['field_parent'];
|
||||
this.fields_view = fields_view;
|
||||
_(this.fields_view.arch.children).each(function (field) {
|
||||
if (field.attrs.modifiers) {
|
||||
field.attrs.modifiers = JSON.parse(field.attrs.modifiers);
|
||||
}
|
||||
});
|
||||
this.fields = fields_view.fields;
|
||||
this.hook_row_click();
|
||||
this.$element.html(QWeb.render('TreeView', {
|
||||
'title': this.fields_view.arch.attrs.string,
|
||||
'fields_view': this.fields_view.arch.children,
|
||||
'fields': this.fields,
|
||||
'toolbar': has_toolbar
|
||||
}));
|
||||
|
||||
this.dataset.read_slice({fields: this.fields_list()}, function (records) {
|
||||
if (!has_toolbar) {
|
||||
// WARNING: will do a second read on the same ids, but only on
|
||||
// first load so not very important
|
||||
self.getdata(null, _(records).pluck('id'));
|
||||
return;
|
||||
}
|
||||
|
||||
var $select = self.$element.find('select')
|
||||
.change(function () {
|
||||
var $option = $(this).find(':selected');
|
||||
self.getdata($option.val(), $option.data('children'));
|
||||
});
|
||||
_(records).each(function (record) {
|
||||
self.records[record.id] = record;
|
||||
$('<option>')
|
||||
.val(record.id)
|
||||
.text(record.name)
|
||||
.data('children', record[self.children_field])
|
||||
.appendTo($select);
|
||||
});
|
||||
|
||||
if (!_.isEmpty(records)) {
|
||||
$select.change();
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Sets up opening a row
|
||||
*/
|
||||
hook_row_click: function () {
|
||||
var self = this;
|
||||
this.$element.delegate('.treeview-td span, .treeview-tr span', 'click', function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
self.activate($(this).closest('tr').data('id'));
|
||||
});
|
||||
|
||||
this.$element.delegate('.treeview-tr', 'click', function () {
|
||||
var is_loaded = 0,
|
||||
$this = $(this),
|
||||
record_id = $this.data('id'),
|
||||
record = self.records[record_id],
|
||||
children_ids = record[self.children_field];
|
||||
|
||||
_(children_ids).each(function(childid) {
|
||||
if (self.$element.find('#treerow_' + childid).length) {
|
||||
if (self.$element.find('#treerow_' + childid).is(':hidden')) {
|
||||
is_loaded = -1;
|
||||
} else {
|
||||
is_loaded++;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (is_loaded === 0) {
|
||||
if (!$this.parent().hasClass('oe-open')) {
|
||||
self.getdata(record_id, children_ids);
|
||||
}
|
||||
} else {
|
||||
self.showcontent(record_id, is_loaded < 0);
|
||||
}
|
||||
});
|
||||
},
|
||||
// get child data of selected value
|
||||
getdata: function (id, children_ids) {
|
||||
var self = this;
|
||||
|
||||
self.dataset.read_ids(children_ids, this.fields_list(), function (records) {
|
||||
_(records).each(function (record) {
|
||||
self.records[record.id] = record;
|
||||
});
|
||||
|
||||
var $curr_node = self.$element.find('#treerow_' + id);
|
||||
var children_rows = QWeb.render('TreeView.rows', {
|
||||
'records': records,
|
||||
'children_field': self.children_field,
|
||||
'fields_view': self.fields_view.arch.children,
|
||||
'fields': self.fields,
|
||||
'level': $curr_node.data('level') || 0,
|
||||
'render': openerp.base.format_value
|
||||
});
|
||||
|
||||
if ($curr_node.length) {
|
||||
$curr_node.addClass('oe-open');
|
||||
$curr_node.after(children_rows);
|
||||
} else {
|
||||
self.$element.find('tbody').html(children_rows);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Get details in listview
|
||||
activate: function(id) {
|
||||
var self = this;
|
||||
this.rpc('/base/treeview/action', {
|
||||
id: id,
|
||||
model: this.dataset.model,
|
||||
context: new openerp.base.CompoundContext(
|
||||
this.dataset.get_context(), {
|
||||
active_model: this.dataset.model,
|
||||
active_id: id,
|
||||
active_ids: [id]})
|
||||
}, function (actions) {
|
||||
if (!actions.length) { return; }
|
||||
var action = actions[0][2];
|
||||
self.do_action(action);
|
||||
});
|
||||
},
|
||||
|
||||
// show & hide the contents
|
||||
showcontent: function (record_id, show) {
|
||||
this.$element.find('#treerow_' + record_id)
|
||||
.toggleClass('oe-open', show);
|
||||
|
||||
_(this.records[record_id][this.children_field]).each(function (child_id) {
|
||||
var $child_row = this.$element.find('#treerow_' + child_id);
|
||||
if ($child_row.hasClass('oe-open')) {
|
||||
this.showcontent(child_id, false);
|
||||
}
|
||||
$child_row.toggle(show);
|
||||
}, this);
|
||||
},
|
||||
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
this.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
||||
+103
-178
@@ -4,72 +4,83 @@
|
||||
|
||||
openerp.base.views = function(openerp) {
|
||||
|
||||
/**
|
||||
* Registry for all the client actions key: tag value: widget
|
||||
*/
|
||||
openerp.base.client_actions = new openerp.base.Registry();
|
||||
|
||||
openerp.base.ActionManager = openerp.base.Widget.extend({
|
||||
// process all kind of actions
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.viewmanager = null;
|
||||
this.current_dialog = null;
|
||||
// Temporary linking view_manager to session.
|
||||
// Will use parent to find it when implementation will be done.
|
||||
this.session.action_manager = this;
|
||||
identifier_prefix: "actionmanager",
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
this.inner_viewmanager = null;
|
||||
this.dialog = null;
|
||||
this.dialog_viewmanager = null;
|
||||
this.client_widget = null;
|
||||
},
|
||||
do_action: function(action, on_closed) {
|
||||
render: function() {
|
||||
return "<div id='"+this.element_id+"'></div>";
|
||||
},
|
||||
dialog_stop: function () {
|
||||
if (this.dialog) {
|
||||
this.dialog_viewmanager.stop();
|
||||
this.dialog_viewmanager = null;
|
||||
this.dialog.stop();
|
||||
this.dialog = null;
|
||||
}
|
||||
},
|
||||
inner_stop: function () {
|
||||
if (this.inner_viewmanager) {
|
||||
this.inner_viewmanager.stop();
|
||||
this.inner_viewmanager = null;
|
||||
}
|
||||
},
|
||||
do_action: function(action, on_close) {
|
||||
var type = action.type.replace(/\./g,'_');
|
||||
var popup = action.target === 'new';
|
||||
action.flags = _.extend({
|
||||
sidebar : action.target != 'new',
|
||||
search_view : action.target != 'new',
|
||||
new_window : false,
|
||||
views_switcher : action.target != 'new',
|
||||
action_buttons : action.target != 'new',
|
||||
pager : action.target != 'new'
|
||||
views_switcher : !popup,
|
||||
search_view : !popup,
|
||||
action_buttons : !popup,
|
||||
sidebar : !popup,
|
||||
pager : !popup
|
||||
}, action.flags || {});
|
||||
// instantiate the right controllers by understanding the action
|
||||
if (!(action.type in this)) {
|
||||
console.log("Action manager can't handle action of type " + action.type, action);
|
||||
if (!(type in this)) {
|
||||
this.log("Action manager can't handle action of type " + action.type, action);
|
||||
return;
|
||||
}
|
||||
this[action.type](action, on_closed);
|
||||
this[type](action, on_close);
|
||||
},
|
||||
|
||||
'ir.actions.act_window': function (action, on_closed) {
|
||||
if (!action.target && this.current_dialog) {
|
||||
action.flags.new_window = true;
|
||||
}
|
||||
if (action.target == 'new') {
|
||||
var dialog = this.current_dialog = new openerp.base.ActionDialog(this, {
|
||||
title: action.name,
|
||||
width: '50%'
|
||||
});
|
||||
if (on_closed) {
|
||||
dialog.close_callback = on_closed;
|
||||
ir_actions_act_window: function (action, on_close) {
|
||||
if (action.target === 'new') {
|
||||
if (this.dialog == null) {
|
||||
this.dialog = new openerp.base.Dialog(this, { title: action.name, width: '80%' });
|
||||
if(on_close)
|
||||
this.dialog.on_close.add(on_close);
|
||||
this.dialog.start();
|
||||
} else {
|
||||
this.dialog_viewmanager.stop();
|
||||
}
|
||||
dialog.start(false);
|
||||
var viewmanager = dialog.viewmanager = new openerp.base.ViewManagerAction(this, dialog.element_id, action);
|
||||
viewmanager.start();
|
||||
dialog.open();
|
||||
} else if (action.flags.new_window) {
|
||||
action.flags.new_window = false;
|
||||
this.dialog_viewmanager = new openerp.base.ViewManagerAction(this, action);
|
||||
this.dialog_viewmanager.appendTo(this.dialog.$element);
|
||||
this.dialog.open();
|
||||
} else {
|
||||
this.dialog_stop();
|
||||
this.inner_stop();
|
||||
this.inner_viewmanager = new openerp.base.ViewManagerAction(this, action);
|
||||
this.inner_viewmanager.appendTo(this.$element);
|
||||
}
|
||||
/* new window code
|
||||
this.rpc("/base/session/save_session_action", { the_action : action}, function(key) {
|
||||
var url = window.location.protocol + "//" + window.location.host +
|
||||
window.location.pathname + "?" + jQuery.param({ s_action : "" + key });
|
||||
window.open(url);
|
||||
if (on_closed) {
|
||||
on_closed();
|
||||
}
|
||||
var url = window.location.protocol + "//" + window.location.host + window.location.pathname + "?" + jQuery.param({ s_action : "" + key });
|
||||
window.open(url,'_blank');
|
||||
});
|
||||
} else {
|
||||
if (this.viewmanager) {
|
||||
this.viewmanager.stop();
|
||||
}
|
||||
this.viewmanager = new openerp.base.ViewManagerAction(this, this.element_id, action);
|
||||
this.viewmanager.start();
|
||||
}
|
||||
*/
|
||||
},
|
||||
'ir.actions.act_window_close': function (action, on_closed) {
|
||||
this.close_dialog();
|
||||
ir_actions_act_window_close: function (action, on_closed) {
|
||||
this.dialog_stop();
|
||||
},
|
||||
'ir.actions.server': function (action, on_closed) {
|
||||
ir_actions_server: function (action, on_closed) {
|
||||
var self = this;
|
||||
this.rpc('/base/action/run', {
|
||||
action_id: action.id,
|
||||
@@ -78,47 +89,28 @@ openerp.base.ActionManager = openerp.base.Widget.extend({
|
||||
self.do_action(action, on_closed)
|
||||
});
|
||||
},
|
||||
'ir.actions.client': function (action) {
|
||||
var Handler = openerp.base.client_actions.get_object(action.tag);
|
||||
new Handler(this, this.element_id, action.params).start();
|
||||
ir_actions_client: function (action) {
|
||||
this.client_widget = openerp.base.client_actions.get_object(action.tag);
|
||||
new this.client_widget(this, this.element_id, action.params).start();
|
||||
},
|
||||
close_dialog: function () {
|
||||
if (this.current_dialog) {
|
||||
this.current_dialog.stop();
|
||||
this.current_dialog = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ActionDialog = openerp.base.Dialog.extend({
|
||||
identifier_prefix: 'action_dialog',
|
||||
on_close: function() {
|
||||
this._super(this, arguments);
|
||||
if (this.close_callback) {
|
||||
this.close_callback();
|
||||
}
|
||||
},
|
||||
stop: function() {
|
||||
this._super(this, arguments);
|
||||
if (this.viewmanager) {
|
||||
this.viewmanager.stop();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ViewManager = openerp.base.Widget.extend({
|
||||
init: function(parent, element_id, dataset, views) {
|
||||
this._super(parent, element_id);
|
||||
identifier_prefix: "viewmanager",
|
||||
init: function(parent, dataset, views) {
|
||||
this._super(parent);
|
||||
this.model = dataset.model;
|
||||
this.dataset = dataset;
|
||||
this.searchview = null;
|
||||
this.active_view = null;
|
||||
this.views_src = _.map(views, function(x)
|
||||
{return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
|
||||
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.registry = openerp.base.views;
|
||||
},
|
||||
render: function() {
|
||||
return QWeb.render("ViewManager", {"prefix": this.element_id, views: this.views_src})
|
||||
},
|
||||
/**
|
||||
* @returns {jQuery.Deferred} initial view loading promise
|
||||
*/
|
||||
@@ -126,7 +118,6 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
||||
this._super();
|
||||
var self = this;
|
||||
this.dataset.start();
|
||||
this.$element.html(QWeb.render("ViewManager", {"prefix": this.element_id, views: this.views_src}));
|
||||
this.$element.find('.oe_vm_switch button').click(function() {
|
||||
self.on_mode_switch($(this).data('view-type'));
|
||||
});
|
||||
@@ -148,8 +139,6 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
||||
// switch to the first one in sequence
|
||||
return this.on_mode_switch(this.views_src[0].view_type);
|
||||
},
|
||||
stop: function() {
|
||||
},
|
||||
/**
|
||||
* Asks the view manager to switch visualization mode.
|
||||
*
|
||||
@@ -219,11 +208,12 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
||||
},
|
||||
/**
|
||||
* Event launched when a controller has been inited.
|
||||
*
|
||||
*
|
||||
* @param {String} view_type type of view
|
||||
* @param {String} view the inited controller
|
||||
*/
|
||||
on_controller_inited: function(view_type, view) {},
|
||||
on_controller_inited: function(view_type, view) {
|
||||
},
|
||||
/**
|
||||
* Sets up the current viewmanager's search view.
|
||||
*
|
||||
@@ -240,9 +230,8 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
||||
this.searchview.hide();
|
||||
}
|
||||
this.searchview.on_search.add(function(domains, contexts, groupbys) {
|
||||
self.views[self.active_view].controller.do_search.call(
|
||||
self, domains.concat(self.domains()),
|
||||
contexts.concat(self.contexts()), groupbys);
|
||||
var controller = self.views[self.active_view].controller;
|
||||
controller.do_search.call(controller, domains, contexts, groupbys);
|
||||
});
|
||||
return this.searchview.start();
|
||||
},
|
||||
@@ -256,50 +245,22 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
|
||||
on_remove: function() {
|
||||
},
|
||||
on_edit: function() {
|
||||
},
|
||||
/**
|
||||
* Domains added on searches by the view manager, to override in subsequent
|
||||
* view manager in order to add new pieces of domains to searches
|
||||
*
|
||||
* @returns an empty list
|
||||
*/
|
||||
domains: function () {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Contexts added on searches by the view manager.
|
||||
*
|
||||
* @returns an empty list
|
||||
*/
|
||||
contexts: function () {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.NullViewManager = openerp.base.generate_null_object_class(openerp.base.ViewManager, {
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
if(parent)
|
||||
this.session = parent.session;
|
||||
this.action = {flags: {}};
|
||||
}
|
||||
});
|
||||
|
||||
// TODO Will move to action Manager
|
||||
openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
init: function(parent, element_id, action) {
|
||||
init: function(parent, action) {
|
||||
this.session = parent.session;
|
||||
this.action = action;
|
||||
var dataset;
|
||||
if (!action.res_id) {
|
||||
dataset = new openerp.base.DataSetSearch(this, action.res_model, action.context || null);
|
||||
dataset = new openerp.base.DataSetSearch(this, action.res_model, action.context, action.domain);
|
||||
} else {
|
||||
dataset = new openerp.base.DataSetStatic(this, 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.action.flags.search_view = false;
|
||||
dataset = new openerp.base.DataSetStatic(this, action.res_model, action.context, [action.res_id]);
|
||||
dataset.index = 0;
|
||||
}
|
||||
this._super(parent, element_id, dataset, action.views);
|
||||
this._super(parent, dataset, action.views);
|
||||
this.action = action;
|
||||
this.flags = this.action.flags || {};
|
||||
if (action.res_model == 'board.board' && action.views.length == 1 && action.views) {
|
||||
@@ -331,32 +292,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
.then(this.searchview.do_search);
|
||||
}
|
||||
}
|
||||
},
|
||||
stop: function() {
|
||||
// should be replaced by automatic destruction implemented in Widget
|
||||
this._super();
|
||||
},
|
||||
/**
|
||||
* adds action domain to the search domains
|
||||
*
|
||||
* @returns the action's domain
|
||||
*/
|
||||
domains: function () {
|
||||
if (!this.action.domain) {
|
||||
return [];
|
||||
}
|
||||
return [this.action.domain];
|
||||
},
|
||||
/**
|
||||
* adds action context to the search contexts
|
||||
*
|
||||
* @returns the action's context
|
||||
*/
|
||||
contexts: function () {
|
||||
if (!this.action.context) {
|
||||
return [];
|
||||
}
|
||||
return [this.action.context];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -466,17 +401,12 @@ openerp.base.View = openerp.base.Widget.extend({
|
||||
* @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'``
|
||||
* @param {Object} [action_data.context=null] additional action context, to add to the current context
|
||||
* @param {openerp.base.DataSet} dataset a dataset object used to communicate with the server
|
||||
* @param {openerp.base.ActionManager} action_manager object able to actually execute the action, if any is fetched
|
||||
* @param {Object} [record_id] the identifier of the object on which the action is to be applied
|
||||
* @param {Function} on_closed callback to execute when dialog is closed or when the action does not generate any result (no new action)
|
||||
*/
|
||||
execute_action: function (action_data, dataset, action_manager, record_id, on_closed) {
|
||||
execute_action: function (action_data, dataset, record_id, on_closed) {
|
||||
var self = this;
|
||||
if (action_manager.current_dialog) {
|
||||
on_closed = action_manager.current_dialog.close_callback;
|
||||
}
|
||||
var handler = function (r) {
|
||||
action_manager.close_dialog();
|
||||
var action = r.result;
|
||||
if (action && action.constructor == Object) {
|
||||
action.context = action.context || {};
|
||||
@@ -485,34 +415,29 @@ openerp.base.View = openerp.base.Widget.extend({
|
||||
active_ids: [record_id || false],
|
||||
active_model: dataset.model
|
||||
});
|
||||
action.flags = {
|
||||
new_window: true
|
||||
};
|
||||
action_manager.do_action(action, on_closed);
|
||||
self.do_action(action, on_closed);
|
||||
} else if (on_closed) {
|
||||
on_closed(action);
|
||||
}
|
||||
};
|
||||
|
||||
if (!action_data.special) {
|
||||
var context = new openerp.base.CompoundContext(dataset.get_context(), action_data.context || {});
|
||||
switch(action_data.type) {
|
||||
case 'object':
|
||||
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:
|
||||
return dataset.exec_workflow(record_id, action_data.name, handler);
|
||||
}
|
||||
} else {
|
||||
action_manager.close_dialog();
|
||||
}
|
||||
var context = new openerp.base.CompoundContext(dataset.get_context(), action_data.context || {});
|
||||
|
||||
if (action_data.special) {
|
||||
handler({result: {"type":"ir.actions.act_window_close"}});
|
||||
} else if (action_data.type=="object") {
|
||||
return dataset.call_button(action_data.name, [[record_id], context], handler);
|
||||
} else if (action_data.type=="action") {
|
||||
return this.rpc('/base/action/load', { action_id: parseInt(action_data.name, 10), context: context }, handler);
|
||||
} else {
|
||||
return dataset.exec_workflow(record_id, action_data.name, handler);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Directly set a view to use instead of calling fields_view_get. This method must
|
||||
* be called before start(). When an embedded view is set, underlying implementations
|
||||
* of openerp.base.View must use the provided view instead of any other one.
|
||||
*
|
||||
*
|
||||
* @param embedded_view A view.
|
||||
*/
|
||||
set_embedded_view: function(embedded_view) {
|
||||
@@ -564,10 +489,10 @@ openerp.base.View = openerp.base.Widget.extend({
|
||||
}
|
||||
},
|
||||
on_sidebar_edit_workflow: function() {
|
||||
console.log('Todo');
|
||||
this.log('Todo');
|
||||
},
|
||||
on_sidebar_customize_object: function() {
|
||||
console.log('Todo');
|
||||
this.log('Todo');
|
||||
},
|
||||
on_sidebar_import: function() {
|
||||
var import_view = new openerp.base.DataImport(this, this.dataset);
|
||||
@@ -575,7 +500,7 @@ openerp.base.View = openerp.base.Widget.extend({
|
||||
},
|
||||
on_sidebar_export: function() {
|
||||
var export_view = new openerp.base.DataExport(this, this.dataset);
|
||||
export_view.start(false);
|
||||
export_view.start();
|
||||
},
|
||||
on_sidebar_translate: function() {
|
||||
},
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
</td>
|
||||
<td valign="top">
|
||||
<div id="oe_app" class="oe-application">
|
||||
<div style="width: 100%;">&nbsp;</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -79,7 +78,7 @@
|
||||
</table>
|
||||
<table align="center" class="db_option_table">
|
||||
<tr>
|
||||
<td><label for="super_admin_pwd">Super admin password:</label></td>
|
||||
<td><label for="super_admin_pwd">Master password:</label></td>
|
||||
<td><input type="password" name="super_admin_pwd"
|
||||
class="required" autofocus="autofocus"/></td>
|
||||
</tr>
|
||||
@@ -104,7 +103,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="create_admin_pwd">Super admin password:</label></td>
|
||||
<td><label for="create_admin_pwd">Admin password:</label></td>
|
||||
<td><input type="password" name="create_admin_pwd" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -139,7 +138,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="drop_password">Password:</label></td>
|
||||
<td><label for="drop_password">Master Password:</label></td>
|
||||
<td><input type="password" name="drop_pwd" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -171,7 +170,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="backup_pwd">Password:</label></td>
|
||||
<td><label for="backup_pwd">Master Password:</label></td>
|
||||
<td><input type="password" name="backup_pwd" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -196,7 +195,7 @@
|
||||
autofocus="autofocus"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="restore_pwd">Password:</label></td>
|
||||
<td><label for="restore_pwd">Master Password:</label></td>
|
||||
<td><input type="password" name="restore_pwd" class="required"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -214,23 +213,23 @@
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td class="option_string">
|
||||
CHANGE DATABASE PASSWORD
|
||||
CHANGE MASTER PASSWORD
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table align="center" class="db_option_table">
|
||||
<tr>
|
||||
<td><label for="old_pwd">Old password:</label></td>
|
||||
<td><label for="old_pwd">Master password:</label></td>
|
||||
<td><input type="password" name="old_pwd" class="required"
|
||||
minlength="1" autofocus="autofocus"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="new_pwd">New password:</label></td>
|
||||
<td><label for="new_pwd">New master password:</label></td>
|
||||
<td><input type="password" name="new_pwd" class="required"
|
||||
minlength="1"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="confirm_pwd">Confirm password:</label></td>
|
||||
<td><label for="confirm_pwd">Confirm new master password:</label></td>
|
||||
<td><input type="password" name="confirm_pwd" class="required"
|
||||
equalTo="input[name=new_pwd]" minlength="1"/></td>
|
||||
</tr>
|
||||
@@ -449,6 +448,41 @@
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="TreeView">
|
||||
<h2 class="oe_view_title"><t t-esc="title"/></h2>
|
||||
<select t-if="toolbar" style="width: 30%">
|
||||
</select>
|
||||
<table class="oe-treeview-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th t-foreach="fields_view" t-as="field"
|
||||
t-if="!field.attrs.modifiers.tree_invisible"
|
||||
class="treeview-header">
|
||||
<t t-esc="fields[field.attrs.name].string" />
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
<tr t-name="TreeView.rows"
|
||||
t-foreach="records" t-as="record"
|
||||
t-att-id="'treerow_' + record.id"
|
||||
t-att-data-id="record.id" t-att-data-level="level + 1">
|
||||
<t t-set="children" t-value="record[children_field]"/>
|
||||
<t t-set="has_children" t-value="children and children.length"/>
|
||||
|
||||
<td t-foreach="fields_view" t-as="field"
|
||||
t-if="!field.attrs.modifiers.tree_invisible"
|
||||
t-att-data-id="record.id"
|
||||
t-att-style="!field_index ? 'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px' : undefined"
|
||||
t-att-class="!field_index and has_children ? 'treeview-tr' : 'treeview-td'">
|
||||
<span t-if="!field.attrs.modifiers.invisible">
|
||||
<t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" />
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<table t-name="ListView" class="oe-listview-content">
|
||||
<t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/>
|
||||
<thead class="ui-widget-header">
|
||||
@@ -513,14 +547,9 @@
|
||||
</tfoot>
|
||||
</table>
|
||||
<t t-name="ListView.rows" t-foreach="rows" t-as="row">
|
||||
<t t-call="ListView.row">
|
||||
<t t-set="style" t-value="null"/>
|
||||
<t-if test="row.color">
|
||||
<t t-set="style" t-value="'color: ' + row.color"/>
|
||||
</t-if>
|
||||
</t>
|
||||
<t t-call="ListView.row"/>
|
||||
</t>
|
||||
<tr t-name="ListView.row" t-att-style="style" t-att-class="row_parity"
|
||||
<tr t-name="ListView.row" t-att-class="row_parity"
|
||||
t-att-data-index="row_index">
|
||||
<t t-foreach="columns" t-as="column">
|
||||
<td t-if="column.meta">
|
||||
@@ -934,22 +963,6 @@
|
||||
<t t-if="filters.length" t-raw="filters.render(defaults)"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="SearchView.fields.date">
|
||||
<label style="display: block" t-att-title="attrs.help"
|
||||
t-att-for="element_id">
|
||||
<t t-esc="attrs.string || attrs.name"/>
|
||||
<span t-if="attrs.help">(?)</span>
|
||||
</label>
|
||||
<div style="white-space: nowrap;" t-att-id="element_id">
|
||||
<input t-att-name="attrs.name" type="text" class="field_date"
|
||||
t-att-value="defaults[attrs.name] || ''"
|
||||
t-att-autofocus="attrs.default_focus === '1' ? 'autofocus' : undefined"/>
|
||||
to
|
||||
<input t-att-name="attrs.name" type="text" class="field_date"
|
||||
t-att-value="defaults[attrs.name] || ''"/>
|
||||
<t t-if="filters.length" t-raw="filters.render(defaults)"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="SearchView.field.selection">
|
||||
<label style="display: block" t-att-title="attrs.help"
|
||||
t-att-for="element_id">
|
||||
@@ -1101,11 +1114,17 @@
|
||||
</t>
|
||||
<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>
|
||||
<button type="button" class="oe_selectcreatepopup-search-close">Cancel</button>
|
||||
</t>
|
||||
<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-if="widget.options.disable_multiple_selection">
|
||||
<button type="button" class="oe_selectcreatepopup-form-save">Save</button>
|
||||
</t>
|
||||
<t t-if="! widget.options.disable_multiple_selection">
|
||||
<button type="button" class="oe_selectcreatepopup-form-save-new">Save & New</button>
|
||||
<button type="button" class="oe_selectcreatepopup-form-save">Save & Close</button>
|
||||
</t>
|
||||
<button type="button" class="oe_selectcreatepopup-form-close">Cancel</button>
|
||||
</t>
|
||||
<t t-name="FormOpenPopup">
|
||||
<div t-att-id="element_id">
|
||||
@@ -1114,7 +1133,7 @@
|
||||
</t>
|
||||
<t t-name="FormOpenPopup.form.buttons">
|
||||
<button type="button" class="oe_formopenpopup-form-save">Save</button>
|
||||
<button type="button" class="oe_formopenpopup-form-close">Close</button>
|
||||
<button type="button" class="oe_formopenpopup-form-close">Cancel</button>
|
||||
</t>
|
||||
<t t-name="ListView.row.frame" t-extend="WidgetFrame">
|
||||
<t t-jquery="tr">
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
$(document).ready(function () {
|
||||
var openerp;
|
||||
function get_widget(attrs) {
|
||||
var widget = new openerp.base.search.DateField(
|
||||
{attrs: attrs}, {name: 'foo'}, {inputs: []});
|
||||
$('#qunit-fixture').html(widget.render({}));
|
||||
widget.start();
|
||||
return widget;
|
||||
}
|
||||
|
||||
module('search-date', {
|
||||
setup: function () {
|
||||
openerp = window.openerp.init(true);
|
||||
window.openerp.base.core(openerp);
|
||||
window.openerp.base.chrome(openerp);
|
||||
window.openerp.base.views(openerp);
|
||||
window.openerp.base.search(openerp);
|
||||
}
|
||||
});
|
||||
test('no values', function () {
|
||||
var widget = get_widget();
|
||||
deepEqual(widget.get_values(), {});
|
||||
strictEqual(widget.get_context(), null);
|
||||
strictEqual(widget.get_domain(), null);
|
||||
});
|
||||
test('filled from', function () {
|
||||
var widget = get_widget();
|
||||
widget.$element.find('input:eq(0)').val('1912-06-23');
|
||||
|
||||
deepEqual(widget.get_values(), {from: '1912-06-23'});
|
||||
strictEqual(widget.get_context(), null);
|
||||
deepEqual(widget.get_domain(), [['foo', '>=', '1912-06-23']]);
|
||||
});
|
||||
test('filled to', function () {
|
||||
var widget = get_widget();
|
||||
widget.$element.find('input:eq(1)').val('1954-06-07');
|
||||
|
||||
deepEqual(widget.get_values(), {to: '1954-06-07'});
|
||||
strictEqual(widget.get_context(), null);
|
||||
deepEqual(widget.get_domain(), [['foo', '<=', '1954-06-07']]);
|
||||
});
|
||||
test('filled both', function () {
|
||||
var widget = get_widget();
|
||||
widget.$element.find('input:eq(0)').val('1912-06-23');
|
||||
widget.$element.find('input:eq(1)').val('1954-06-07');
|
||||
|
||||
deepEqual(widget.get_values(), {from: '1912-06-23', to: '1954-06-07'});
|
||||
strictEqual(widget.get_context(), null);
|
||||
deepEqual(widget.get_domain(),
|
||||
[['foo', '>=', '1912-06-23'], ['foo', '<=', '1954-06-07']]);
|
||||
});
|
||||
test('custom context', function () {
|
||||
var widget = get_widget({context: {__id: -1}});
|
||||
widget.$element.find('input:eq(0)').val('1912-06-23');
|
||||
widget.$element.find('input:eq(1)').val('1954-06-07');
|
||||
|
||||
deepEqual(
|
||||
widget.get_context(),
|
||||
{__id: -1,
|
||||
own_values: {
|
||||
self: {from: '1912-06-23', to: '1954-06-07'}}});
|
||||
});
|
||||
test('custom filter_domain', function () {
|
||||
var widget = get_widget({filter_domain: {__id: -42}});
|
||||
widget.$element.find('input:eq(0)').val('1912-06-23');
|
||||
widget.$element.find('input:eq(1)').val('1954-06-07');
|
||||
|
||||
deepEqual(
|
||||
widget.get_domain(),
|
||||
{__id: -42,
|
||||
own_values: {
|
||||
self: {from: '1912-06-23', to: '1954-06-07'}}});
|
||||
});
|
||||
});
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<script src="/base/static/src/js/boot.js"></script>
|
||||
<script src="/base/static/src/js/core.js"></script>
|
||||
<script src="/base/static/src/js/dates.js"></script>
|
||||
<script src="/base/static/src/js/formats.js"></script>
|
||||
<script src="/base/static/src/js/chrome.js"></script>
|
||||
<script src="/base/static/src/js/data.js"></script>
|
||||
<script src="/base/static/src/js/views.js"></script>
|
||||
@@ -39,6 +39,5 @@
|
||||
</body>
|
||||
<script type="text/javascript" src="/base/static/test/class.js"></script>
|
||||
<script type="text/javascript" src="/base/static/test/registry.js"></script>
|
||||
<script type="text/javascript" src="/base/static/test/search-date.js"></script>
|
||||
<script type="text/javascript" src="/base/static/test/form.js"></script>
|
||||
</html>
|
||||
|
||||
@@ -16,7 +16,16 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
this.domain = this.dataset.domain || [];
|
||||
this.context = this.dataset.context || {};
|
||||
this.has_been_loaded = $.Deferred();
|
||||
this.options = options || {};
|
||||
this.creating_event_id = null;
|
||||
this.dataset_events = [];
|
||||
if (this.options.action_views_ids.form) {
|
||||
this.form_dialog = new openerp.base_calendar.CalendarFormDialog(this, {}, this.options.action_views_ids.form, dataset);
|
||||
this.form_dialog.start();
|
||||
}
|
||||
this.COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400',
|
||||
'#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f',
|
||||
'#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00',
|
||||
'#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900' ];
|
||||
},
|
||||
start: function() {
|
||||
this.rpc("/base_calendar/calendarview/load", {"model": this.model, "view_id": this.view_id, 'toolbar': true}, this.on_loaded);
|
||||
@@ -44,14 +53,19 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
this.fields = this.fields_view.fields;
|
||||
|
||||
//* Calendar Fields *
|
||||
this.calendar_fields['date_start'] = {'name': this.date_start, 'kind': this.fields[this.date_start]['type']};
|
||||
this.calendar_fields.date_start = {'name': this.date_start, 'kind': this.fields[this.date_start].type};
|
||||
|
||||
if (this.date_delay) {
|
||||
this.calendar_fields['date_delay'] = {'name': this.date_delay, 'kind': this.fields[this.date_delay]['type']};
|
||||
if (this.fields[this.date_delay].type != 'float') {
|
||||
throw new Error("Calendar view has a 'date_delay' type != float");
|
||||
}
|
||||
this.calendar_fields.date_delay = {'name': this.date_delay, 'kind': this.fields[this.date_delay].type};
|
||||
}
|
||||
|
||||
if (this.date_stop) {
|
||||
this.calendar_fields['date_stop'] = {'name': this.date_stop, 'kind': this.fields[this.date_stop]['type']};
|
||||
this.calendar_fields.date_stop = {'name': this.date_stop, 'kind': this.fields[this.date_stop].type};
|
||||
}
|
||||
if (!this.date_delay && !this.date_stop) {
|
||||
throw new Error("Calendar view has none of the following attributes : 'date_stop', 'date_delay'");
|
||||
}
|
||||
|
||||
for (var fld = 0; fld < this.fields_view.arch.children.length; fld++) {
|
||||
@@ -90,7 +104,8 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
scheduler.config.multi_day = true; //Multi day events are not rendered in daily and weekly views
|
||||
scheduler.config.start_on_monday = true;
|
||||
scheduler.config.scroll_hour = 8;
|
||||
scheduler.config.drag_resize = scheduler.config.drag_create = !!this.date_stop;
|
||||
scheduler.config.drag_resize = true;
|
||||
scheduler.config.drag_create = true;
|
||||
|
||||
// Initialize Sceduler
|
||||
this.mode = this.mode || 'month';
|
||||
@@ -100,6 +115,8 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
scheduler.attachEvent('onEventAdded', this.do_create_event);
|
||||
scheduler.attachEvent('onEventDeleted', this.do_delete_event);
|
||||
scheduler.attachEvent('onEventChanged', this.do_save_event);
|
||||
scheduler.attachEvent('onDblClick', this.do_edit_event);
|
||||
scheduler.attachEvent('onBeforeLightbox', this.do_edit_event);
|
||||
|
||||
this.mini_calendar = scheduler.renderCalendar({
|
||||
container: this.sidebar.navigator.element_id,
|
||||
@@ -116,25 +133,15 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
refresh_minical: function() {
|
||||
scheduler.updateCalendar(this.mini_calendar);
|
||||
},
|
||||
load_scheduler: function() {
|
||||
var self = this;
|
||||
this.dataset.read_slice([], 0, false, function(events) {
|
||||
if (self.session.locale_code) {
|
||||
// TODO: replace $LAB
|
||||
$LAB.setOptions({AlwaysPreserveOrder: true}).script([
|
||||
'/base_calendar/static/lib/dhtmlxScheduler/sources/locale_' + self.session.locale_code + '.js',
|
||||
'/base_calendar/static/lib/dhtmlxScheduler/sources/locale_recurring_' + self.session.locale_code + '.js'
|
||||
]).wait(function() {
|
||||
self.on_events_loaded(events);
|
||||
});
|
||||
} else {
|
||||
self.on_events_loaded(events);
|
||||
}
|
||||
});
|
||||
reload_event: function(id) {
|
||||
this.dataset.read_ids([id], _.keys(this.fields), this.on_events_loaded);
|
||||
},
|
||||
on_events_loaded: function(events) {
|
||||
get_color: function(index) {
|
||||
index = index % this.COLOR_PALETTE.length;
|
||||
return this.COLOR_PALETTE[index];
|
||||
},
|
||||
on_events_loaded: function(events, fn_filter, no_filter_reload) {
|
||||
var self = this;
|
||||
scheduler.clearAll();
|
||||
|
||||
//To parse Events we have to convert date Format
|
||||
var res_events = [],
|
||||
@@ -147,111 +154,81 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.color_field) {
|
||||
var filter = evt[this.color_field];
|
||||
if (filter) {
|
||||
var filter_item = {
|
||||
value: (typeof filter === 'object') ? filter[0] : filter,
|
||||
label: (typeof filter === 'object') ? filter[1] : filter
|
||||
}
|
||||
if (typeof(fn_filter) === 'function' && !fn_filter(filter_item.value)) {
|
||||
continue;
|
||||
}
|
||||
var filter_index = _.indexOf(sidebar_ids, filter_item.value);
|
||||
if (filter_index === -1) {
|
||||
evt.color = filter_item.color = this.get_color(sidebar_ids.length);
|
||||
sidebar_items.push(filter_item);
|
||||
sidebar_ids.push(filter_item.value);
|
||||
} else {
|
||||
evt.color = this.get_color(filter_index);
|
||||
}
|
||||
evt.textColor = '#ffffff';
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fields[this.date_start]['type'] == 'date') {
|
||||
evt[this.date_start] = openerp.base.parse_date(evt[this.date_start]).set({hour: 9}).toString('yyyy-MM-dd HH:mm:ss');
|
||||
}
|
||||
if (this.date_stop && evt[this.date_stop] && this.fields[this.date_stop]['type'] == 'date') {
|
||||
evt[this.date_stop] = openerp.base.parse_date(evt[this.date_stop]).set({hour: 17}).toString('yyyy-MM-dd HH:mm:ss');
|
||||
}
|
||||
if (this.color_field) {
|
||||
var user = evt[this.color_field];
|
||||
if (user) {
|
||||
if (_.indexOf(sidebar_ids, user[0]) === -1) {
|
||||
sidebar_items.push({
|
||||
id: user[0],
|
||||
name: user[1],
|
||||
// TODO: use color table
|
||||
color: '#dddddd'
|
||||
});
|
||||
sidebar_ids.push(user[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
res_events.push(this.convert_event(evt));
|
||||
}
|
||||
scheduler.parse(res_events, 'json');
|
||||
this.refresh_scheduler();
|
||||
this.refresh_minical();
|
||||
this.sidebar.responsible.on_events_loaded(sidebar_items);
|
||||
if (!no_filter_reload) {
|
||||
this.sidebar.responsible.on_events_loaded(sidebar_items);
|
||||
}
|
||||
},
|
||||
convert_event: function(event) {
|
||||
var starts = event[this.date_start],
|
||||
ends = event[this.date_delay] || 1,
|
||||
span = 0,
|
||||
convert_event: function(evt) {
|
||||
var date_start = openerp.base.parse_datetime(evt[this.date_start]),
|
||||
date_stop = this.date_stop ? openerp.base.parse_datetime(evt[this.date_stop]) : null,
|
||||
date_delay = evt[this.date_delay] || null,
|
||||
res_text = '',
|
||||
res_description = [];
|
||||
|
||||
var parse_start_date = openerp.base.parse_datetime(starts);
|
||||
if (event[this.date_stop]) {
|
||||
var parse_end_date = openerp.base.parse_datetime(event[this.date_stop]);
|
||||
}
|
||||
if (this.info_fields) {
|
||||
var fld = event[this.info_fields[0]];
|
||||
|
||||
if (typeof fld == 'object') {
|
||||
res_text = fld[fld.length -1];
|
||||
} else {
|
||||
res_text = fld;
|
||||
}
|
||||
var fld = evt[this.info_fields[0]];
|
||||
res_text = (typeof fld == 'object') ? fld[fld.length -1] : res_text = fld;
|
||||
|
||||
var sliced_info_fields = this.info_fields.slice(1);
|
||||
for (sl_fld in sliced_info_fields) {
|
||||
var slc_fld = event[sliced_info_fields[sl_fld]];
|
||||
|
||||
for (var sl_fld in sliced_info_fields) {
|
||||
var slc_fld = evt[sliced_info_fields[sl_fld]];
|
||||
if (typeof slc_fld == 'object') {
|
||||
res_description.push(slc_fld[slc_fld.length - 1]);
|
||||
} else {
|
||||
if(slc_fld) res_description.push(slc_fld);
|
||||
} else if (slc_fld) {
|
||||
res_description.push(slc_fld);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (starts && ends) {
|
||||
var n = 0,
|
||||
h = ends;
|
||||
if (ends == this.day_length) {
|
||||
span = 1;
|
||||
} else if (ends > this.day_length) {
|
||||
n = ends / this.day_length;
|
||||
h = ends % this.day_length;
|
||||
n = parseInt(Math.floor(n));
|
||||
|
||||
if (h > 0) {
|
||||
span = n + 1;
|
||||
} else {
|
||||
span = n;
|
||||
}
|
||||
}
|
||||
var start = parse_start_date.setTime((parse_start_date.getTime() + (h * 60 * 60) + (n * 24 * 60 * 60)));
|
||||
ends = parse_start_date;
|
||||
if (!date_stop && date_delay) {
|
||||
date_stop = date_start.clone().addHours(date_delay);
|
||||
}
|
||||
|
||||
if (starts && this.date_stop) {
|
||||
ends = parse_end_date;
|
||||
if (event[this.date_stop] == undefined) {
|
||||
var start = parse_start_date.setTime((parse_start_date.getTime() + (h * 60 * 60) + (n * 24 * 60 * 60)));
|
||||
ends = parse_start_date;
|
||||
}
|
||||
var tds = parse_start_date.getTime(),
|
||||
tde = parse_end_date.getTime();
|
||||
|
||||
if (tds >= tde) {
|
||||
tde = tds + 60 * 60;
|
||||
parse_end_date.setTime(tde);
|
||||
ends = parse_end_date;
|
||||
}
|
||||
n = (tde - tds) / (60 * 60);
|
||||
if (n >= this.day_length) {
|
||||
span = Math.ceil(n / 24);
|
||||
}
|
||||
}
|
||||
return {
|
||||
'start_date': parse_start_date.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'end_date': ends.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
var r = {
|
||||
'start_date': date_start.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'end_date': date_stop.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'text': res_text,
|
||||
'id': event['id'],
|
||||
'id': evt.id,
|
||||
'title': res_description.join()
|
||||
}
|
||||
if (evt.color) {
|
||||
r.color = evt.color;
|
||||
}
|
||||
if (evt.textColor) {
|
||||
r.textColor = evt.textColor;
|
||||
}
|
||||
return r;
|
||||
},
|
||||
do_create_event: function(event_id, event_obj) {
|
||||
var self = this,
|
||||
@@ -262,8 +239,10 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
scheduler.changeEventId(event_id, id);
|
||||
self.refresh_minical();
|
||||
}, function(r, event) {
|
||||
// TODO: open form view
|
||||
self.notification.warn(self.name, "Could not create event");
|
||||
self.creating_event_id = event_id;
|
||||
self.form_dialog.form.on_record_loaded(data);
|
||||
self.form_dialog.open();
|
||||
event.preventDefault();
|
||||
});
|
||||
},
|
||||
do_save_event: function(event_id, event_obj) {
|
||||
@@ -274,6 +253,7 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
});
|
||||
},
|
||||
do_delete_event: function(event_id, event_obj) {
|
||||
var self = this;
|
||||
// dhtmlx sends this event even when it does not exist in openerp.
|
||||
// Eg: use cancel in dhtmlx new event dialog
|
||||
if (_.indexOf(this.dataset.ids, parseInt(event_id, 10)) > -1) {
|
||||
@@ -282,39 +262,53 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
});
|
||||
}
|
||||
},
|
||||
do_edit_event: function(event_id) {
|
||||
event_id = parseInt(event_id, 10);
|
||||
var index = _.indexOf(this.dataset.ids, event_id);
|
||||
if (index > -1) {
|
||||
this.dataset.index = index;
|
||||
this.form_dialog.form.do_show();
|
||||
this.form_dialog.open();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
get_event_data: function(event_obj) {
|
||||
var data = {
|
||||
name: event_obj.text
|
||||
};
|
||||
var date_format = this.calendar_fields.date_start.kind == 'time' ? 'HH:mm:ss' : 'yyyy-MM-dd HH:mm:ss';
|
||||
data[this.date_start] = event_obj.start_date.toString(date_format);
|
||||
data[this.date_start] = openerp.base.format_datetime(event_obj.start_date);
|
||||
if (this.date_stop) {
|
||||
data[this.date_stop] = event_obj.end_date.toString(date_format);
|
||||
data[this.date_stop] = openerp.base.format_datetime(event_obj.end_date);
|
||||
}
|
||||
if (this.date_delay) {
|
||||
var tds = (event_obj.start_date.getOrdinalNumber() / 1e3 >> 0) - (event_obj.start_date.getOrdinalNumber() < 0);
|
||||
var tde = (event_obj.end_date.getOrdinalNumber() / 1e3 >> 0) - (event_obj.end_date.getOrdinalNumber() < 0);
|
||||
var n = (tde - tds) / (60 * 60);
|
||||
if (n > this.day_length) {
|
||||
var d = Math.floor(n / 24),
|
||||
h = n % 24;
|
||||
n = d * this.day_length + h;
|
||||
}
|
||||
data[this.date_delay] = n;
|
||||
var diff_seconds = Math.round((event_obj.end_date.getTime() - event_obj.start_date.getTime()) / 1000);
|
||||
data[this.date_delay] = diff_seconds / 3600;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
do_search: function(domains, contexts, groupbys) {
|
||||
var self = this;
|
||||
this.rpc('/base/session/eval_domain_and_context', {
|
||||
domains: domains,
|
||||
contexts: contexts,
|
||||
group_by_seq: groupbys
|
||||
}, function (results) {
|
||||
// TODO: handle non-empty results.group_by with read_group
|
||||
self.dataset.context = self.context = results.context;
|
||||
self.dataset.domain = self.domain = results.domain;
|
||||
self.dataset.read_slice(_.keys(self.fields), 0, self.limit, self.on_events_loaded);
|
||||
scheduler.clearAll();
|
||||
$.when(this.has_been_loaded).then(function() {
|
||||
self.rpc('/base/session/eval_domain_and_context', {
|
||||
domains: domains,
|
||||
contexts: contexts,
|
||||
group_by_seq: groupbys
|
||||
}, function (results) {
|
||||
// TODO: handle non-empty results.group_by with read_group
|
||||
self.dataset.context = self.context = results.context;
|
||||
self.dataset.domain = self.domain = results.domain;
|
||||
self.dataset.read_slice({
|
||||
fields: _.keys(self.fields),
|
||||
offset:0,
|
||||
limit: self.limit
|
||||
}, function(events) {
|
||||
self.dataset_events = events;
|
||||
self.on_events_loaded(events);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
do_show: function () {
|
||||
@@ -331,53 +325,39 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
if (this.sidebar) {
|
||||
this.sidebar.$element.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base_calendar.CalendarFormDialog = openerp.base.Dialog.extend({
|
||||
init: function(view, options, view_id, dataset) {
|
||||
this._super(view, options);
|
||||
this.dataset = dataset;
|
||||
this.view_id = view_id;
|
||||
this.view = view;
|
||||
},
|
||||
popup_event: function(event_id) {
|
||||
var self = this;
|
||||
if (event_id) event_id = parseInt(event_id, 10);
|
||||
var action = {
|
||||
res_model: this.dataset.model,
|
||||
res_id: event_id,
|
||||
views: [[false, 'form']],
|
||||
type: 'ir.actions.act_window',
|
||||
view_type: 'form',
|
||||
view_mode: 'form',
|
||||
flags : {
|
||||
search_view: false,
|
||||
sidebar : false,
|
||||
views_switcher : false,
|
||||
action_buttons : false,
|
||||
pager: false
|
||||
}
|
||||
}
|
||||
var element_id = _.uniqueId("act_window_dialog");
|
||||
var dialog = $('<div>', {
|
||||
'id': element_id
|
||||
}).dialog({
|
||||
modal: true,
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
buttons: {
|
||||
Cancel: function() {
|
||||
$(this).dialog("destroy");
|
||||
},
|
||||
Save: function() {
|
||||
var view_manager = action_manager.viewmanager;
|
||||
var _dialog = this;
|
||||
view_manager.views[view_manager.active_view].controller.do_save(function(r) {
|
||||
$(_dialog).dialog("destroy");
|
||||
// self.start();
|
||||
self.load_scheduler();
|
||||
})
|
||||
}
|
||||
}
|
||||
start: function() {
|
||||
this._super();
|
||||
this.form = new openerp.base.FormView(this, this.element_id, this.dataset, this.view_id, {
|
||||
sidebar: false,
|
||||
pager: false
|
||||
});
|
||||
var action_manager = new openerp.base.ActionManager(this, element_id);
|
||||
action_manager.start();
|
||||
action_manager.do_action(action);
|
||||
//Default_get
|
||||
if (!event_id) {
|
||||
this.dataset.index = null;
|
||||
this.form.start();
|
||||
this.form.on_created.add_last(this.on_form_dialog_saved);
|
||||
this.form.on_saved.add_last(this.on_form_dialog_saved);
|
||||
},
|
||||
on_form_dialog_saved: function() {
|
||||
var id = this.dataset.ids[this.dataset.index];
|
||||
if (this.view.creating_event_id) {
|
||||
scheduler.changeEventId(this.view.creating_event_id, id);
|
||||
this.view.creating_event_id = null;
|
||||
}
|
||||
this.view.reload_event(id);
|
||||
this.close();
|
||||
},
|
||||
on_close: function() {
|
||||
if (this.view.creating_event_id) {
|
||||
scheduler.deleteEvent(this.view.creating_event_id);
|
||||
this.view.creating_event_id = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -386,10 +366,25 @@ openerp.base_calendar.SidebarResponsible = openerp.base.Widget.extend({
|
||||
init: function(parent, element_id, view) {
|
||||
this._super(parent, element_id);
|
||||
this.view = view;
|
||||
this.$element.delegate('input:checkbox', 'change', this.on_filter_click);
|
||||
},
|
||||
on_events_loaded: function(users) {
|
||||
this.$element.html(QWeb.render('CalendarView.sidebar.responsible', { users : users }));
|
||||
// TODO: bind checkboxes reload sheduler
|
||||
on_events_loaded: function(filters) {
|
||||
this.$element.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters }));
|
||||
},
|
||||
on_filter_click: function(e) {
|
||||
var responsibles = [],
|
||||
$e = $(e.target);
|
||||
this.$element.find('div.oe_calendar_responsible input:checked').each(function() {
|
||||
responsibles.push($(this).val());
|
||||
});
|
||||
scheduler.clearAll();
|
||||
if (responsibles.length) {
|
||||
this.view.on_events_loaded(this.view.dataset_events, function(filter_value) {
|
||||
return _.indexOf(responsibles, filter_value.toString()) > -1;
|
||||
}, true);
|
||||
} else {
|
||||
this.view.on_events_loaded(this.view.dataset_events, false, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -401,7 +396,6 @@ openerp.base_calendar.SidebarNavigator = openerp.base.Widget.extend({
|
||||
on_events_loaded: function(events) {
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// DEBUG_RPC:rpc.request:('execute', 'addons-dsh-l10n_us', 1, '*', ('ir.filters', 'get_filters', u'res.partner'))
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="CalendarView.sidebar.responsible">
|
||||
<div t-foreach="users" t-as="user" class="oe_calendar_responsible" t-attf-style="background: #{user.color}">
|
||||
<input type="checkbox" name="selection" t-att-value="user.id"/>
|
||||
<span><t t-esc="user.name"/></span>
|
||||
<div t-foreach="filters" t-as="filter" class="oe_calendar_responsible" t-attf-style="background: #{filter.color}">
|
||||
<input type="checkbox" name="selection" t-att-value="filter.value"/>
|
||||
<span><t t-esc="filter.label"/></span>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
@@ -228,9 +228,9 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
action_buttons : false,
|
||||
pager: false
|
||||
};
|
||||
new openerp.base.ActionManager(
|
||||
this, this.view.element_id + '_action_' + action.id)
|
||||
.do_action(action);
|
||||
var am = new openerp.base.ActionManager(this);
|
||||
am.appendTo($("#"+this.view.element_id + '_action_' + action.id));
|
||||
am.do_action(action);
|
||||
},
|
||||
render: function() {
|
||||
// We should start with three columns available
|
||||
@@ -290,7 +290,7 @@ openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({
|
||||
this.dataset.domain = [['type', '=', 'manual']];
|
||||
},
|
||||
start: function () {
|
||||
$.when(this.dataset.read_slice(['state', 'action_id', 'category_id']),
|
||||
$.when(this.dataset.read_slice({fields: ['state', 'action_id', 'category_id']}),
|
||||
this.dataset.call('progress'))
|
||||
.then(this.on_records_loaded);
|
||||
},
|
||||
@@ -333,7 +333,6 @@ openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({
|
||||
type: 'object',
|
||||
name: 'action_launch'
|
||||
}, self.dataset,
|
||||
self.session.action_manager,
|
||||
$(this).data('id'), function () {
|
||||
// after action popup closed, refresh configuration
|
||||
// thingie
|
||||
@@ -354,8 +353,8 @@ openerp.base_dashboard.ApplicationTiles = openerp.base.View.extend({
|
||||
start: function () {
|
||||
var self = this;
|
||||
this.dataset.read_slice(
|
||||
['name', 'web_icon_data', 'web_icon_hover_data'],
|
||||
null, null, function (applications) {
|
||||
{fields: ['name', 'web_icon_data', 'web_icon_hover_data']},
|
||||
function (applications) {
|
||||
// Create a matrix of 3*x applications
|
||||
var rows = [];
|
||||
while (applications.length) {
|
||||
@@ -385,7 +384,8 @@ openerp.base_dashboard.Widgets = openerp.base.View.extend({
|
||||
this.widgets = new openerp.base.DataSetSearch(this, 'res.widget');
|
||||
},
|
||||
start: function () {
|
||||
this.user_widgets.read_slice(['widget_id', 'user_id'], null, null,
|
||||
this.user_widgets.read_slice(
|
||||
{fields: ['widget_id', 'user_id']},
|
||||
this.on_widgets_list_loaded);
|
||||
},
|
||||
on_widgets_list_loaded: function (user_widgets) {
|
||||
|
||||
@@ -86,7 +86,7 @@ openerp.base_default_home = function (openerp) {
|
||||
$.blockUI({
|
||||
message: '<img src="/base_default_home/static/src/img/throbber.gif">'
|
||||
});
|
||||
Modules.read_slice(['id'], null, null, function (records) {
|
||||
Modules.read_slice({fields: ['id']}, function (records) {
|
||||
if (!(records.length === 1)) { return; }
|
||||
Modules.call('state_update',
|
||||
[_.pluck(records, 'id'), 'to install', ['uninstalled']],
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/*---------------------------------------------------------
|
||||
* OpenERP base_gantt
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.base_gantt = function (openerp) {
|
||||
QWeb.add_template('/base_gantt/static/src/xml/base_gantt.xml');
|
||||
openerp.base.views.add('gantt', 'openerp.base_gantt.GanttView');
|
||||
openerp.base_gantt.GanttView = openerp.base.Widget.extend({
|
||||
openerp.base_gantt.GanttView = openerp.base.View.extend({
|
||||
|
||||
init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
|
||||
this._super(session, element_id);
|
||||
this.view_manager = view_manager;
|
||||
init: function(parent, element_id, dataset, view_id) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
@@ -29,7 +27,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
this.calendar_fields = {};
|
||||
this.info_fields = [];
|
||||
this.domain = this.dataset._domain ? this.dataset._domain: [];
|
||||
this.context = {};
|
||||
this.context = this.dataset.context || {};
|
||||
},
|
||||
|
||||
start: function() {
|
||||
@@ -52,8 +50,8 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
this.color_field = this.fields_view.arch.attrs.color;
|
||||
this.day_length = this.fields_view.arch.attrs.day_length || 8;
|
||||
this.colors = this.fields_view.arch.attrs.colors;
|
||||
|
||||
this.text = this.fields_view.arch.children[0].children[0].attrs.name;
|
||||
var arch_children = this.fields_view.arch.children[0];
|
||||
this.text = arch_children.children[0] ? arch_children.children[0].attrs.name : arch_children.attrs.name;
|
||||
this.parent = this.fields_view.arch.children[0].attrs.link;
|
||||
|
||||
this.format = "yyyy-MM-dd";
|
||||
@@ -81,7 +79,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
get_events: function() {
|
||||
|
||||
var self = this;
|
||||
this.dataset.read_slice(false, false, false, function(result) {
|
||||
this.dataset.read_slice({}, function(result) {
|
||||
self.load_event(result);
|
||||
});
|
||||
|
||||
@@ -100,7 +98,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
|
||||
if (result.length != 0){
|
||||
var show_event = [];
|
||||
for (i in result){
|
||||
for (var i in result){
|
||||
var res = result[i];
|
||||
if (res[this.date_start] != false){
|
||||
|
||||
@@ -132,7 +130,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
var child_event = {};
|
||||
var temp_id = "";
|
||||
var final_events = [];
|
||||
for (i in show_event) {
|
||||
for (var i in show_event) {
|
||||
|
||||
var res = show_event[i];
|
||||
|
||||
@@ -161,11 +159,8 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
if (duration == false)
|
||||
duration = 0
|
||||
|
||||
if (self.grp.length == 0){
|
||||
self.grp.push({'group_by' : this.parent})
|
||||
}
|
||||
if (self.grp != undefined){
|
||||
for (j in self.grp){
|
||||
if (self.grp.length){
|
||||
for (var j in self.grp){
|
||||
var grp_key = res[self.grp[j]['group_by']];
|
||||
if (typeof(grp_key) == "object"){
|
||||
grp_key = res[self.grp[j]['group_by']][1];
|
||||
@@ -175,7 +170,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
}
|
||||
|
||||
if (grp_key == false){
|
||||
grp_key = "False";
|
||||
grp_key = "Undefined";
|
||||
}
|
||||
|
||||
if (j == 0){
|
||||
@@ -207,9 +202,17 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
all_events[id] = {'parent': temp_id, 'evt':[id , text, start_date, duration, 100, "", color_box[color]]};
|
||||
final_events.push(id);
|
||||
}
|
||||
else {
|
||||
if (i == 0) {
|
||||
var mod_id = "_" + i;
|
||||
all_events[mod_id] = {'parent': "", 'evt': [mod_id, this.name, start_date, start_date, 100, "", "white"]};
|
||||
}
|
||||
all_events[id] = {'parent': mod_id, 'evt':[id , text, start_date, duration, 100, "", color_box[color]]};
|
||||
final_events.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (i in final_events){
|
||||
for (var i in final_events){
|
||||
var evt_id = final_events[i];
|
||||
var evt_date = all_events[evt_id]['evt'][2];
|
||||
while (all_events[evt_id]['parent'] != "") {
|
||||
@@ -225,7 +228,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
var evt_duration = "";
|
||||
var evt_end_date = "";
|
||||
|
||||
for (i in final_events){
|
||||
for (var i in final_events){
|
||||
evt_id = final_events[i];
|
||||
evt_date = all_events[evt_id]['evt'][2];
|
||||
evt_duration = all_events[evt_id]['evt'][3];
|
||||
@@ -242,42 +245,27 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
}
|
||||
}
|
||||
|
||||
for (j in self.grp){
|
||||
for (i in all_events){
|
||||
res = all_events[i];
|
||||
if ((typeof(res['evt'][3])) == "object"){
|
||||
res['evt'][3] = self.hours_between(res['evt'][2],res['evt'][3]);
|
||||
}
|
||||
|
||||
k = res['evt'][0].toString().indexOf('_');
|
||||
if (k != -1){
|
||||
if (res['evt'][0].substring(k) == "_"+j){
|
||||
if (j == 0){
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
project.addTask(task);
|
||||
} else {
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
prt = project.getTaskById(res['parent']);
|
||||
prt.addChildTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var j in self.grp) {
|
||||
self.render_events(all_events, j);
|
||||
}
|
||||
for (i in final_events){
|
||||
|
||||
if (!self.grp.length) {
|
||||
self.render_events(all_events, 0);
|
||||
}
|
||||
|
||||
for (var i in final_events){
|
||||
evt_id = final_events[i];
|
||||
res = all_events[evt_id];
|
||||
|
||||
task=new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
prt = project.getTaskById(res['parent']);
|
||||
prt.addChildTask(task);
|
||||
}
|
||||
|
||||
oth_hgt = 264;
|
||||
min_hgt = 150;
|
||||
name_min_wdt = 150;
|
||||
gantt_hgt = jQuery(window).height() - oth_hgt;
|
||||
search_wdt = jQuery("#oe_app_search").width();
|
||||
var oth_hgt = 264;
|
||||
var min_hgt = 150;
|
||||
var name_min_wdt = 150;
|
||||
var gantt_hgt = jQuery(window).height() - oth_hgt;
|
||||
var search_wdt = jQuery("#oe_app_search").width();
|
||||
|
||||
if (gantt_hgt > min_hgt){
|
||||
jQuery('#GanttDiv').height(gantt_hgt).width(search_wdt);
|
||||
@@ -291,13 +279,13 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
ganttChartControl.attachEvent("onTaskEndDrag", function(task) {self.on_resize_drag_end(task, "drag");});
|
||||
ganttChartControl.attachEvent("onTaskDblClick", function(task) {self.open_popup(task);});
|
||||
|
||||
taskdiv = jQuery("div.taskPanel").parent();
|
||||
var taskdiv = jQuery("div.taskPanel").parent();
|
||||
taskdiv.addClass('ganttTaskPanel');
|
||||
taskdiv.prev().addClass('ganttDayPanel');
|
||||
$gantt_panel = jQuery(".ganttTaskPanel , .ganttDayPanel");
|
||||
var $gantt_panel = jQuery(".ganttTaskPanel , .ganttDayPanel");
|
||||
|
||||
ganttrow = jQuery('.taskPanel').closest('tr');
|
||||
gtd = ganttrow.children(':first-child');
|
||||
var ganttrow = jQuery('.taskPanel').closest('tr');
|
||||
var gtd = ganttrow.children(':first-child');
|
||||
gtd.children().addClass('task-name');
|
||||
|
||||
jQuery(".toggle-sidebar").click(function(e) {
|
||||
@@ -319,9 +307,8 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
$gantt_panel.width(1);
|
||||
jQuery(".ganttTaskPanel").parent().width(1);
|
||||
|
||||
search_wdt = jQuery("#oe_app_search").width();
|
||||
day_wdt = jQuery(".ganttDayPanel").children().children().width();
|
||||
name_wdt = jQuery('.task-name').width();
|
||||
var search_wdt = jQuery("#oe_app_search").width();
|
||||
var day_wdt = jQuery(".ganttDayPanel").children().children().width();
|
||||
jQuery('#GanttDiv').css('width','100%');
|
||||
|
||||
if (search_wdt - day_wdt <= name_min_wdt){
|
||||
@@ -345,7 +332,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
|
||||
var self = this;
|
||||
|
||||
dat = this.convert_str_date(dat);
|
||||
var dat = this.convert_str_date(dat);
|
||||
|
||||
var day = Math.floor(duration/self.day_length);
|
||||
var hrs = duration % self.day_length;
|
||||
@@ -356,47 +343,98 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
return dat;
|
||||
},
|
||||
|
||||
hours_between: function(date1, date2) {
|
||||
hours_between: function(date1, date2, parent_task) {
|
||||
|
||||
var ONE_DAY = 1000 * 60 * 60 * 24;
|
||||
var date1_ms = date1.getTime();
|
||||
var date2_ms = date2.getTime();
|
||||
var difference_ms = Math.abs(date1_ms - date2_ms);
|
||||
|
||||
d = Math.floor(difference_ms / ONE_DAY);
|
||||
h = (difference_ms % ONE_DAY)/(1000 * 60 * 60);
|
||||
num = (d * this.day_length) + h;
|
||||
var d = parent_task? Math.ceil(difference_ms / ONE_DAY) : Math.floor(difference_ms / ONE_DAY);
|
||||
var h = (difference_ms % ONE_DAY)/(1000 * 60 * 60);
|
||||
var num = (d * this.day_length) + h;
|
||||
return parseFloat(num.toFixed(2));
|
||||
|
||||
},
|
||||
|
||||
render_events : function(all_events, j) {
|
||||
|
||||
var self = this;
|
||||
for (var i in all_events){
|
||||
var res = all_events[i];
|
||||
if ((typeof(res['evt'][3])) == "object"){
|
||||
res['evt'][3] = self.hours_between(res['evt'][2],res['evt'][3], true);
|
||||
}
|
||||
|
||||
k = res['evt'][0].toString().indexOf('_');
|
||||
|
||||
if (k != -1) {
|
||||
if (res['evt'][0].substring(k) == "_"+j){
|
||||
if (j == 0){
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
project.addTask(task);
|
||||
} else {
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
prt = project.getTaskById(res['parent']);
|
||||
prt.addChildTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
open_popup : function(task) {
|
||||
var event_id = task.getId();
|
||||
|
||||
if(event_id.toString().search("_") != -1)
|
||||
return;
|
||||
if (event_id) {
|
||||
event_id = parseInt(event_id, 10);
|
||||
var dataset_event_index = jQuery.inArray(event_id, this.ids);
|
||||
} else {
|
||||
var dataset_event_index = null;
|
||||
if(event_id) event_id = parseInt(event_id, 10);
|
||||
|
||||
var action = {
|
||||
"res_model": this.dataset.model,
|
||||
"res_id": event_id,
|
||||
"views":[[false,"form"]],
|
||||
"type":"ir.actions.act_window",
|
||||
"view_type":"form",
|
||||
"view_mode":"form"
|
||||
}
|
||||
this.dataset.index = dataset_event_index;
|
||||
|
||||
action.flags = {
|
||||
search_view: false,
|
||||
sidebar : false,
|
||||
views_switcher : false,
|
||||
pager: false
|
||||
}
|
||||
var element_id = _.uniqueId("act_window_dialog");
|
||||
var dialog = jQuery('<div>',
|
||||
{'id': element_id
|
||||
}).dialog({
|
||||
title: 'Gantt Chart',
|
||||
modal: true,
|
||||
minWidth: 800,
|
||||
position: 'top'
|
||||
});
|
||||
var event_form = new openerp.base.FormView(this.view_manager, this.session, element_id, this.dataset, false);
|
||||
event_form.start();
|
||||
var dialog = jQuery('<div>', {
|
||||
'id': element_id
|
||||
}).dialog({
|
||||
modal: true,
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
buttons: {
|
||||
Cancel: function() {
|
||||
$(this).dialog("destroy");
|
||||
},
|
||||
Save: function() {
|
||||
var view_manager = action_manager.viewmanager;
|
||||
var _dialog = this;
|
||||
view_manager.views[view_manager.active_view].controller.do_save(function(r) {
|
||||
$(_dialog).dialog("destroy");
|
||||
self.reload_gantt();
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
var action_manager = new openerp.base.ActionManager(this, element_id);
|
||||
action_manager.start();
|
||||
action_manager.do_action(action);
|
||||
|
||||
//Default_get
|
||||
if(!event_id) action_manager.viewmanager.dataset.index = null;
|
||||
},
|
||||
|
||||
on_drag_start : function(task){
|
||||
st_date = task.getEST();
|
||||
var st_date = task.getEST();
|
||||
if(st_date.getHours()){
|
||||
self.hh = st_date.getHours();
|
||||
self.mm = st_date.getMinutes();
|
||||
@@ -460,7 +498,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
|
||||
reload_gantt: function() {
|
||||
var self = this;
|
||||
this.dataset.read_slice(false, false, false, function(response) {
|
||||
this.dataset.read_slice({}, function(response) {
|
||||
ganttChartControl.clearAll();
|
||||
jQuery("#GanttDiv").children().remove();
|
||||
self.load_event(response);
|
||||
|
||||
@@ -89,7 +89,7 @@ openerp.base_graph.GraphView = openerp.base.View.extend({
|
||||
}
|
||||
this.dataset.domain = domain;
|
||||
this.dataset.context = this.view_manager.dataset.context;
|
||||
this.dataset.read_slice(_(this.fields).keys(), 0, false, function(res) {
|
||||
this.dataset.read_slice({fields: _(this.fields).keys()}, function(res) {
|
||||
self.schedule_chart(res);
|
||||
});
|
||||
}
|
||||
@@ -442,7 +442,7 @@ openerp.base_graph.GraphView = openerp.base.View.extend({
|
||||
}
|
||||
views.push(view);
|
||||
});
|
||||
this.session.action_manager.do_action({
|
||||
this.do_action({
|
||||
"res_model" : this.dataset.model,
|
||||
"domain" : this.dataset.domain,
|
||||
"views" : views,
|
||||
@@ -468,9 +468,7 @@ openerp.base_graph.GraphView = openerp.base.View.extend({
|
||||
}
|
||||
self.dataset.context = results.context;
|
||||
self.dataset.domain = results.domain;
|
||||
self.dataset.read_slice([], 0, false,function(response){
|
||||
self.load_chart(response);
|
||||
});
|
||||
self.dataset.read_slice({}, $.proxy(self, 'load_chart'));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -12,7 +12,7 @@ openerp.web_mobile.FormView = openerp.base.Widget.extend({
|
||||
view_id = this.action.views[1][0];
|
||||
|
||||
this.dataset = new openerp.base.DataSetSearch(this.session, this.action.res_model, null, null);
|
||||
this.dataset.read_slice(false, false, false, function (result) {
|
||||
this.dataset.read_slice({}, function (result) {
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
if (result[i].id == id) {
|
||||
@@ -101,4 +101,4 @@ openerp.web_mobile.FormView = openerp.base.Widget.extend({
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
<script type="text/javascript" src="/base/static/src/js/base.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/chrome.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/data.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/dates.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/formats.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/web_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/chrome_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/web_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/chrome_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/list_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/form_mobile.js"></script>
|
||||
|
||||
|
||||
+104
-187
@@ -113,6 +113,98 @@ initializing the addon.
|
||||
Creating new standard roles
|
||||
---------------------------
|
||||
|
||||
Widget
|
||||
++++++
|
||||
|
||||
This is the base class for all visual components. It provides a number of
|
||||
services for the management of a DOM subtree:
|
||||
|
||||
* Rendering with QWeb
|
||||
|
||||
* Parenting-child relations
|
||||
|
||||
* Life-cycle management (including facilitating children destruction when a
|
||||
parent object is removed)
|
||||
|
||||
* DOM insertion, via jQuery-powered insertion methods. Insertion targets can
|
||||
be anything the corresponding jQuery method accepts (generally selectors,
|
||||
DOM nodes and jQuery objects):
|
||||
|
||||
:js:func:`~openerp.base.Widget.appendTo`
|
||||
Renders the widget and inserts it as the last child of the target, uses
|
||||
`.appendTo()`_
|
||||
|
||||
:js:func:`~openerp.base.Widget.prependTo`
|
||||
Renders the widget and inserts it as the first child of the target, uses
|
||||
`.prependTo()`_
|
||||
|
||||
:js:func:`~openerp.base.Widget.insertAfter`
|
||||
Renders the widget and inserts it as the preceding sibling of the target,
|
||||
uses `.insertAfter()`_
|
||||
|
||||
:js:func:`~openerp.base.Widget.insertBefore`
|
||||
Renders the widget and inserts it as the following sibling of the target,
|
||||
uses `.insertBefore()`_
|
||||
|
||||
:js:class:`~openerp.base.Widget` inherits from
|
||||
:js:class:`~openerp.base.SessionAware`, so subclasses can easily access the
|
||||
RPC layers.
|
||||
|
||||
Subclassing Widget
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:js:class:`~openerp.base.Widget` is subclassed in the standard manner (via the
|
||||
:js:func:`~openerp.base.Class.extend` method), and provides a number of
|
||||
abstract properties and concrete methods (which you may or may not want to
|
||||
override). Creating a subclass looks like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
var MyWidget = openerp.base.Widget.extend({
|
||||
// QWeb template to use when rendering the object
|
||||
template: "MyQWebTemplate",
|
||||
// autogenerated id prefix, specificity helps when debugging
|
||||
identifier_prefix: 'my-id-prefix-',
|
||||
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
// insert code to execute before rendering, for object
|
||||
// initialization
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
// post-rendering initialization code, at this point
|
||||
// ``this.$element`` has been initialized
|
||||
this.$element.find(".my_button").click(/* an example of event binding * /);
|
||||
|
||||
// if ``start`` is asynchronous, return a promise object so callers
|
||||
// know when the object is done initializing
|
||||
return this.rpc(/* … */)
|
||||
}
|
||||
});
|
||||
|
||||
The new class can then be used in the following manner:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// Create the instance
|
||||
var my_widget = new MyWidget(this);
|
||||
// Render and insert into DOM
|
||||
my_widget.appendTo(".some-div");
|
||||
|
||||
After these two lines have executed (and any promise returned by ``appendTo``
|
||||
has been resolved if needed), the widget is ready to be used.
|
||||
|
||||
If the widget is not needed anymore (because it's transient), simply terminate
|
||||
it:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
my_widget.stop();
|
||||
|
||||
will unbind all DOM events, remove the widget's content from the DOM and
|
||||
destroy all widget data.
|
||||
|
||||
Views
|
||||
+++++
|
||||
|
||||
@@ -236,193 +328,6 @@ replace ``addons`` by the directory in which your own addon lives.
|
||||
and run ``nosetests addons`` instead of the ``unit2`` command,
|
||||
the result should be exactly the same.
|
||||
|
||||
APIs
|
||||
----
|
||||
|
||||
Javascript
|
||||
++++++++++
|
||||
|
||||
.. js:class:: openerp.base.Widget(view, node)
|
||||
|
||||
:param openerp.base.Controller view: The view to which the widget belongs
|
||||
:param Object node: the ``fields_view_get`` descriptor for the widget
|
||||
|
||||
.. js:attribute:: $element
|
||||
|
||||
The widget's root element as jQuery object
|
||||
|
||||
.. js:class:: openerp.base.DataSet(session, model)
|
||||
|
||||
:param openerp.base.Session session: the RPC session object
|
||||
:param String model: the model managed by this dataset
|
||||
|
||||
The DataSet is the abstraction for a sequence of records stored in
|
||||
database.
|
||||
|
||||
It provides interfaces for reading records based on search
|
||||
criteria, and for selecting and fetching records based on
|
||||
activated ids.
|
||||
|
||||
.. js:function:: fetch([offset][, limit])
|
||||
|
||||
:param Number offset: the index from which records should start
|
||||
being returned (section)
|
||||
:param Number limit: the maximum number of records to return
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Asynchronously fetches the records selected by the DataSet's
|
||||
domain and context, in the provided sort order if any.
|
||||
|
||||
Only fetches the fields selected by the DataSet.
|
||||
|
||||
On success, triggers :js:func:`on_fetch`
|
||||
|
||||
.. js:function:: on_fetch(records, event)
|
||||
|
||||
:param Array records: an array of
|
||||
:js:class:`openerp.base.DataRecord`
|
||||
matching the DataSet's selection
|
||||
:param event: a data holder letting the event handler fetch
|
||||
meta-informations about the event.
|
||||
:type event: OnFetchEvent
|
||||
|
||||
Fired after :js:func:`fetch` is done fetching the records
|
||||
selected by the DataSet.
|
||||
|
||||
.. js:function:: active_ids
|
||||
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Asynchronously fetches the active records for this DataSet.
|
||||
|
||||
On success, triggers :js:func:`on_active_ids`
|
||||
|
||||
.. js:function:: on_active_ids(records)
|
||||
|
||||
:param Array records: an array of
|
||||
:js:class:`openerp.base.DataRecord`
|
||||
matching the currently active ids
|
||||
|
||||
Fired after :js:func:`active_ids` fetched the records matching
|
||||
the DataSet's active ids.
|
||||
|
||||
.. js:function:: active_id
|
||||
|
||||
:returns: the dataset instance in was called on
|
||||
|
||||
Asynchronously fetches the current active record.
|
||||
|
||||
On success, triggers :js:func:`on_active_id`
|
||||
|
||||
.. js:function:: on_active_id(record)
|
||||
|
||||
:param Object record: the record fetched by
|
||||
:js:func:`active_id`, or ``null``
|
||||
:type record: openerp.base.DataRecord
|
||||
|
||||
Fired after :js:func:`active_id` fetched the record matching
|
||||
the dataset's active id
|
||||
|
||||
.. js:function:: set(options)
|
||||
|
||||
:param Object options: the options to set on the dataset
|
||||
:type options: DataSetOptions
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Configures the data set by setting various properties on it
|
||||
|
||||
.. js:function:: prev
|
||||
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Activates the id preceding the current one in the active ids
|
||||
sequence of the dataset.
|
||||
|
||||
If the current active id is at the start of the sequence,
|
||||
wraps back to the last id of the sequence.
|
||||
|
||||
.. js:function:: next
|
||||
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Activates the id following the current one in the active ids
|
||||
sequence.
|
||||
|
||||
If the current active id is the last of the sequence, wraps
|
||||
back to the beginning of the active ids sequence.
|
||||
|
||||
.. js:function:: select(ids)
|
||||
|
||||
:param Array ids: the identifiers to activate on the dataset
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Activates all the ids specified in the dataset, resets the
|
||||
current active id to be the first id of the new sequence.
|
||||
|
||||
The internal order will be the same as the ids list provided.
|
||||
|
||||
.. js:function:: get_active_ids
|
||||
|
||||
:returns: the list of current active ids for the dataset
|
||||
|
||||
.. js:function:: activate(id)
|
||||
|
||||
:param Number id: the id to activate
|
||||
:returns: the dataset instance it was called on
|
||||
|
||||
Activates the id provided in the dataset. If no ids are
|
||||
selected, selects the id in the dataset.
|
||||
|
||||
If ids are already selected and the provided id is not in that
|
||||
selection, raises an error.
|
||||
|
||||
.. js:function:: get_active_id
|
||||
|
||||
:returns: the dataset's current active id
|
||||
|
||||
Ad-hoc objects and structural types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These objects are not associated with any specific class, they're
|
||||
generally literal objects created on the spot. Names are merely
|
||||
convenient ways to refer to them and their properties.
|
||||
|
||||
.. js:class:: OnFetchEvent
|
||||
|
||||
.. js:attribute:: context
|
||||
|
||||
The context used for the :js:func:`fetch` call (domain set on
|
||||
the :js:class:`openerp.base.DataSet` when ``fetch`` was
|
||||
called)
|
||||
|
||||
.. js:attribute:: domain
|
||||
|
||||
The domain used for the :js:func:`fetch` call
|
||||
|
||||
.. js:attribute:: limit
|
||||
|
||||
The limit with which the original :js:func:`fetch` call was
|
||||
performed
|
||||
|
||||
.. js:attribute:: offset
|
||||
|
||||
The offset with which the original :js:func:`fetch` call was
|
||||
performed
|
||||
|
||||
.. js:attribute:: sort
|
||||
|
||||
The sorting criteria active on the
|
||||
:js:class:`openerp.base.DataSet` when :js:func:`fetch` was
|
||||
called
|
||||
|
||||
.. js:class:: DataSetOptions
|
||||
|
||||
.. js:attribute:: context
|
||||
|
||||
.. js:attribute:: domain
|
||||
|
||||
.. js:attribute:: sort
|
||||
|
||||
Python
|
||||
++++++
|
||||
|
||||
@@ -499,3 +404,15 @@ Python
|
||||
|
||||
.. _promise object:
|
||||
http://api.jquery.com/deferred.promise/
|
||||
|
||||
.. _.appendTo():
|
||||
http://api.jquery.com/appendTo/
|
||||
|
||||
.. _.prependTo():
|
||||
http://api.jquery.com/prependTo/
|
||||
|
||||
.. _.insertAfter():
|
||||
http://api.jquery.com/insertAfter/
|
||||
|
||||
.. _.insertBefore():
|
||||
http://api.jquery.com/insertBefore/
|
||||
|
||||
@@ -374,11 +374,13 @@ Deletion can be overridden by replacing the
|
||||
calls :js:func:`~openerp.base.DataSet.unlink` in order to remove the records
|
||||
entirely.
|
||||
|
||||
.. note:: the list-wise deletion button (next to the record addition button)
|
||||
simply proxies to :js:func:`~openerp.base.ListView.do_delete` after
|
||||
obtaining all selected record ids, but it is possible to override it
|
||||
alone by replacing
|
||||
:js:func:`~openerp.base.ListView.do_delete_selected`.
|
||||
.. note::
|
||||
|
||||
the list-wise deletion button (next to the record addition button)
|
||||
simply proxies to :js:func:`~openerp.base.ListView.do_delete` after
|
||||
obtaining all selected record ids, but it is possible to override it
|
||||
alone by replacing
|
||||
:js:func:`~openerp.base.ListView.do_delete_selected`.
|
||||
|
||||
Internal API Doc
|
||||
----------------
|
||||
|
||||
Reference in New Issue
Block a user