[MERGE] Merge with trunk upto revision no 790.

bzr revid: ysa@tinyerp.com-20110811094854-m93w506cch3hihgj
This commit is contained in:
Yogesh (OpenERP)
2011-08-11 15:18:54 +05:30
20 changed files with 678 additions and 774 deletions
+6 -7
View File
@@ -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/
+8 -14
View File
@@ -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,12 +44,13 @@
}
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);
+8 -285
View File
@@ -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
@@ -952,6 +672,7 @@ openerp.base.Preferences = 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 = {};
@@ -963,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");
@@ -988,6 +709,8 @@ openerp.base.WebClient = openerp.base.Widget.extend({
this.notification.notify("OpenERP Client", "The openerp client has been initialized.");
},
on_logged: function() {
if(this.action_manager)
this.action_manager.stop();
this.action_manager = new openerp.base.ActionManager(this);
this.action_manager.appendTo($("#oe_app"));
+290 -1
View File
@@ -1,5 +1,5 @@
/*---------------------------------------------------------
* OpenERP controller framework
* OpenERP Web core
*--------------------------------------------------------*/
openerp.base.core = function(openerp) {
@@ -574,6 +574,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 +611,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:
+176 -69
View File
@@ -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:
+28 -25
View File
@@ -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);
});
}
});
@@ -1885,7 +1890,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
});
@@ -2210,8 +2215,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 +2325,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',
+15 -14
View File
@@ -74,15 +74,16 @@ openerp.base.parse_time = function(str) {
};
/*
* Just a simple function to add some '0' if an integer it too small.
* 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 fts = function(str, size) {
var zpad = function(str, size) {
str = "" + str;
var to_add = "";
_.each(_.range(size - str.length), function() {
to_add = to_add + "0";
});
return to_add + str;
return new Array(size - str.length).join('0') + str;
};
/**
@@ -99,9 +100,9 @@ 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);
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);
};
/**
@@ -115,8 +116,8 @@ openerp.base.format_date = function(obj) {
if (!obj) {
return false;
}
return fts(obj.getFullYear(),4) + "-" + fts(obj.getMonth() + 1,2) + "-"
+ fts(obj.getDate(),2);
return zpad(obj.getFullYear(),4) + "-" + zpad(obj.getMonth() + 1,2) + "-"
+ zpad(obj.getDate(),2);
};
/**
@@ -130,8 +131,8 @@ openerp.base.format_time = function(obj) {
if (!obj) {
return false;
}
return fts(obj.getHours(),2) + ":" + fts(obj.getMinutes(),2) + ":"
+ fts(obj.getSeconds(),2);
return zpad(obj.getHours(),2) + ":" + zpad(obj.getMinutes(),2) + ":"
+ zpad(obj.getSeconds(),2);
};
/**
+20 -20
View File
@@ -61,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}
*/
@@ -69,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;
@@ -94,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);
@@ -399,11 +400,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;
@@ -454,17 +454,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();
}));
});
},
/**
@@ -476,11 +475,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);
});
},
/**
@@ -1034,10 +1033,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: _.filter(_.pluck(_.select(this.columns, function(x) {return x.tag == "field";}), 'name'), _.identity),
offset: page * limit,
limit: limit
}, function (records) {
if (!self.datagroup.openable) {
view.configure_pager(dataset);
} else {
+46 -100
View File
@@ -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;
@@ -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,90 +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
@@ -847,9 +796,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',
+2 -2
View File
@@ -72,7 +72,7 @@ openerp.base.TreeView = openerp.base.View.extend({
'toolbar': has_toolbar
}));
this.dataset.read_slice(this.fields_list(), 0, false, function (records) {
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
@@ -177,7 +177,7 @@ openerp.base.TreeView = openerp.base.View.extend({
if (!actions.length) { return; }
var action = actions[0][2];
action.flags.new_window = true;
self.session.action_manager.do_action(action);
self.do_action(action);
});
},
+27 -97
View File
@@ -9,27 +9,6 @@ openerp.base.views = function(openerp) {
*/
openerp.base.client_actions = new openerp.base.Registry();
/**
* Registry for all the main views
*/
openerp.base.views = new openerp.base.Registry();
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.ActionManager = openerp.base.Widget.extend({
identifier_prefix: "actionmanager",
init: function(parent) {
@@ -68,25 +47,24 @@ openerp.base.ActionManager = openerp.base.Widget.extend({
pager : !popup
}, action.flags || {});
if (!(type in this)) {
console.log("Action manager can't handle action of type " + action.type, action);
this.log("Action manager can't handle action of type " + action.type, action);
return;
}
this[type](action, on_closed);
this[type](action, on_close);
},
ir_actions_act_window: function (action, on_closed) {
ir_actions_act_window: function (action, on_close) {
if (action.flags.popup) {
if (this.dialog == null) {
this.dialog = new openerp.base.ActionDialog(this, { title: action.name, width: '80%' });
this.dialog.close_callback = on_closed;
this.dialog.start(false);
this.dialog_viewmanager = new openerp.base.ViewManagerAction(this, action);
this.dialog_viewmanager.appendTo(this.dialog.$element);
this.dialog.open();
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();
this.dialog_viewmanager = new openerp.base.ViewManagerAction(this, action);
this.dialog_viewmanager.appendTo(this.dialog.$element);
}
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();
@@ -101,7 +79,7 @@ openerp.base.ActionManager = openerp.base.Widget.extend({
*/
},
ir_actions_act_window_close: function (action, on_closed) {
this.close_dialog();
this.dialog_stop();
},
ir_actions_server: function (action, on_closed) {
var self = this;
@@ -253,9 +231,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();
},
@@ -269,49 +246,19 @@ 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: {}};
}
});
// Move parts or everything to ActionManager
openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
init: function(parent, action) {
this.session = parent.session;
var dataset;
if (!action.res_id) {
dataset = new openerp.base.DataSetSearch(this, action.res_model, action.context || null, action.domain || 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, domain, ...)
dataset.context = action.context;
}
dataset = new openerp.base.DataSetStatic(this, action.res_model, action.context, [action.res_id]);
}
this.action = action;
this._super(parent, dataset, action.views);
this.action = action;
this.flags = this.action.flags || {};
@@ -344,28 +291,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
.then(this.searchview.do_search);
}
}
},
/**
* 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];
}
});
@@ -475,11 +400,10 @@ 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;
var handler = function (r) {
var action = r.result;
@@ -497,8 +421,9 @@ openerp.base.View = openerp.base.Widget.extend({
};
var context = new openerp.base.CompoundContext(dataset.get_context(), action_data.context || {});
if (action_data.special) {
// dunno
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") {
@@ -563,16 +488,16 @@ 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() {
},
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() {
},
@@ -580,6 +505,11 @@ openerp.base.View = openerp.base.Widget.extend({
}
});
/**
* Registry for all the main views
*/
openerp.base.views = new openerp.base.Registry();
openerp.base.json_node_to_xml = function(node, single_quote, indent) {
// For debugging purpose, this function will convert a json node back to xml
// Maybe usefull for xml view editor
+11 -32
View File
@@ -78,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>
@@ -103,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>
@@ -138,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>
@@ -170,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>
@@ -195,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>
@@ -213,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>
@@ -547,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">
@@ -968,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">
-74
View File
@@ -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'}}});
});
});
-1
View File
@@ -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>
+28 -18
View File
@@ -48,14 +48,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++) {
@@ -126,7 +131,7 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
},
load_scheduler: function() {
var self = this;
this.dataset.read_slice([], 0, false, function(events) {
this.dataset.read_slice({}, function(events) {
if (self.session.locale_code) {
// TODO: replace $LAB
$LAB.setOptions({AlwaysPreserveOrder: true}).script([
@@ -307,10 +312,9 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
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);
@@ -327,15 +331,21 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
},
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);
$.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
}, self.on_events_loaded);
});
});
},
do_show: function () {
@@ -411,7 +421,7 @@ openerp.base_calendar.CalendarFormDialog = openerp.base.Dialog.extend({
this.view = view;
},
start: function() {
this._super(false);
this._super();
this.form = new openerp.base.FormView(this, this.element_id, this.dataset, this.view_id, {
sidebar: false,
pager: false
@@ -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']],
+2 -2
View File
@@ -81,7 +81,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);
});
@@ -460,7 +460,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);
+3 -5
View File
@@ -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({
},
});
}
}