diff options
| author | Antoine Huvelle <ahu@openerp.com> | 2011-12-16 14:07:41 +0100 |
|---|---|---|
| committer | Antoine Huvelle <ahu@openerp.com> | 2011-12-16 14:07:41 +0100 |
| commit | 4bbb1c06833d83df5c8f3dc1469030462a83c5bd (patch) | |
| tree | 85f3a5184ea8a18f2cd5c21423c0e452ad694a2e /addons/web/static/src/js | |
| parent | 5026c6b43ec6b9490a708c2fc7370d96664a84dc (diff) | |
| parent | 2989c829f760df5bc182510146d67fdf9a877908 (diff) | |
[IMP] changes in 'group by' padding
bzr revid: ahu@openerp.com-20111216083515-tvmyyn1zzh34qzfp
bzr revid: ahu@openerp.com-20111216130741-a6f0bv7ixq16osg6
Diffstat (limited to 'addons/web/static/src/js')
| -rw-r--r-- | addons/web/static/src/js/chrome.js | 209 | ||||
| -rw-r--r-- | addons/web/static/src/js/core.js | 317 | ||||
| -rw-r--r-- | addons/web/static/src/js/data.js | 9 | ||||
| -rw-r--r-- | addons/web/static/src/js/data_export.js | 17 | ||||
| -rw-r--r-- | addons/web/static/src/js/data_import.js | 8 | ||||
| -rw-r--r-- | addons/web/static/src/js/formats.js | 2 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_editor.js | 155 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_form.js | 70 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list.js | 56 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list_editable.js | 7 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_page.js | 25 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_tree.js | 7 | ||||
| -rw-r--r-- | addons/web/static/src/js/views.js | 144 |
13 files changed, 599 insertions, 427 deletions
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index 83f7f971434..50fb8018918 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -2,7 +2,8 @@ * OpenERP Web chrome *---------------------------------------------------------*/ openerp.web.chrome = function(openerp) { -var QWeb = openerp.web.qweb; +var QWeb = openerp.web.qweb, + _t = openerp.web._t; openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Notification# */{ template: 'Notification', @@ -157,11 +158,9 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({ on_managed_error: function(error) { $('<div>' + QWeb.render('DialogWarning', {error: error}) + '</div>').dialog({ title: "OpenERP " + _.str.capitalize(error.type), - buttons: { - Ok: function() { - $(this).dialog("close"); - } - } + buttons: [ + {text: _t("Ok"), click: function() { $(this).dialog("close"); }} + ] }); }, on_traceback: function(error) { @@ -172,11 +171,9 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({ height: '90%', min_width: '800px', min_height: '600px', - buttons: { - Ok: function() { - $(this).dialog("close"); - } - } + buttons: [ + {text: _t("Ok"), click: function() { $(this).dialog("close"); }} + ] }).start(); dialog.$element.html(QWeb.render('DialogTraceback', {error: error})); } @@ -368,11 +365,9 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database return $('<div>').dialog({ modal: true, title: error.title, - buttons: { - Ok: function() { - $(this).dialog("close"); - } - } + buttons: [ + {text: _t("Ok"), click: function() { $(this).dialog("close"); }} + ] }).html(error.error); }, do_create: function() { @@ -634,9 +629,6 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{ callback: continuation || function() {} }); }, - on_logout: function() { - this.session.logout(); - } }); openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# */{ @@ -663,7 +655,7 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# * self.$content.remove(); if (!self.session.uid) return; - var func = new openerp.web.Model(self.session, "res.users").get_func("read"); + var func = new openerp.web.Model("res.users").get_func("read"); return func(self.session.uid, ["name", "company_id"]).pipe(function(res) { self.$content = $(QWeb.render("Header-content", {widget: self, user: res})); self.$content.appendTo(self.$element); @@ -680,7 +672,7 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# * self.rpc("/web/webclient/version_info", {}).then(function(res) { var $help = $(QWeb.render("About-Page", {version_info: res})); $help.dialog({autoOpen: true, - modal: true, width: 960, title: "About"}); + modal: true, width: 960, title: _t("About")}); }); }, shortcut_load :function(){ @@ -760,25 +752,22 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# * }); this.dialog = new openerp.web.Dialog(this,{ modal: true, - title: 'Preferences', + title: _t("Preferences"), width: 600, height: 500, - buttons: { - "Change password": function(){ - self.change_password(); - }, - Cancel: function(){ - $(this).dialog('destroy'); - }, - Save: function(){ - var inner_viewmanager = action_manager.inner_viewmanager; - inner_viewmanager.views[inner_viewmanager.active_view].controller.do_save() - .then(function() { - self.dialog.stop(); - window.location.reload(); - }); + buttons: [ + {text: _t("Change password"), click: function(){ self.change_password(); }}, + {text: _t("Cancel"), click: function(){ $(this).dialog('destroy'); }}, + {text: _t("Save"), click: function(){ + var inner_viewmanager = action_manager.inner_viewmanager; + inner_viewmanager.views[inner_viewmanager.active_view].controller.do_save() + .then(function() { + self.dialog.stop(); + window.location.reload(); + }); + } } - } + ] }); this.dialog.start().open(); action_manager.appendTo(this.dialog); @@ -789,7 +778,7 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# * var self = this; this.dialog = new openerp.web.Dialog(this,{ modal : true, - title : 'Change Password', + title: _t("Change Password"), width : 'auto', height : 'auto' }); @@ -814,11 +803,9 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# * return $('<div>').dialog({ modal: true, title: error.title, - buttons: { - Ok: function() { - $(this).dialog("close"); - } - } + buttons: [ + {text: _("Ok"), click: function() { $(this).dialog("close"); }} + ] }).html(error.error); }, on_logout: function() { @@ -966,13 +953,16 @@ openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{ $sub_menu.css(css); $sub_menu.mouseenter(function() { clearTimeout($sub_menu.data('timeoutId')); + $sub_menu.data('timeoutId', null); + return false; }).mouseleave(function(evt) { var timeoutId = setTimeout(function() { - if (self.folded) { - $sub_menu.hide(); + if (self.folded && $sub_menu.data('timeoutId')) { + $sub_menu.hide().unbind('mouseenter').unbind('mouseleave'); } }, self.float_timeout); $sub_menu.data('timeoutId', timeoutId); + return false; }); } $sub_menu.show(); @@ -998,47 +988,56 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie * @param element_id */ init: function(element_id) { + var self = this; this._super(null, element_id); openerp.webclient = this; - var params = {}; - if(jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) { - this.$element.addClass("kitten-mode-activated"); - } - this.$element.html(QWeb.render("Interface", params)); - this.notification = new openerp.web.Notification(this); this.loading = new openerp.web.Loading(this); this.crashmanager = new openerp.web.CrashManager(); this.header = new openerp.web.Header(this); this.login = new openerp.web.Login(this); - this.header.on_logout.add(this.login.on_logout); + this.header.on_logout.add(this.on_logout); this.header.on_action.add(this.on_menu_action); - this.session.on_session_invalid.add(this.login.do_ask_login); - this.session.on_session_valid.add_last(this.header.do_update); - this.session.on_session_invalid.add_last(this.header.do_update); - this.session.on_session_valid.add_last(this.on_logged); - this.session.on_session_invalid.add_last(this.on_logged_out); - - this.menu = new openerp.web.Menu(this, "oe_menu", "oe_secondary_menu"); - this.menu.on_action.add(this.on_menu_action); - this._current_state = null; - }, start: function() { this._super.apply(this, arguments); - this.notification.prependTo(this.$element); - this.loading.appendTo($('#oe_loading')); - this.header.appendTo($("#oe_header")); - this.session.start(); - this.login.appendTo($('#oe_login')); - this.menu.start(); + var self = this; + this.session.bind().then(function() { + var params = {}; + if (jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) { + this.$element.addClass("kitten-mode-activated"); + this.$element.delegate('img.oe-record-edit-link-img', 'hover', function(e) { + self.$element.toggleClass('clark-gable'); + }); + } + self.$element.html(QWeb.render("Interface", params)); + self.menu = new openerp.web.Menu(self, "oe_menu", "oe_secondary_menu"); + self.menu.on_action.add(self.on_menu_action); + + self.notification.prependTo(self.$element); + self.loading.appendTo($('#oe_loading')); + self.header.appendTo($("#oe_header")); + self.login.appendTo($('#oe_login')); + self.menu.start(); + self.login.on_login_invalid(); + }); + this.session.ready.then(function() { + self.login.on_login_valid(); + self.header.do_update(); + self.menu.do_reload(); + if(self.action_manager) + self.action_manager.stop(); + self.action_manager = new openerp.web.ActionManager(this); + self.action_manager.appendTo($("#oe_app")); + self.bind_hashchange(); + }); }, do_reload: function() { - return $.when(this.session.session_restore(),this.menu.do_reload()); + return $.when(this.session.session_init(),this.menu.do_reload()); }, do_notify: function() { var n = this.notification; @@ -1048,27 +1047,12 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie var n = this.notification; n.warn.apply(n, arguments); }, - on_logged: function() { - this.menu.do_reload(); - if(this.action_manager) - this.action_manager.stop(); - this.action_manager = new openerp.web.ActionManager(this); - this.action_manager.do_push_state.add(this.do_push_state); - this.action_manager.appendTo($("#oe_app")); - - if (openerp._modules_loaded) { // TODO: find better option than this - this.bind_hashchange(); - } else { - this.session.on_modules_loaded.add({ // XXX what about a $.Deferred ? - callback: $.proxy(this, 'bind_hashchange'), - unique: true, - position: 'last' - }) - } - }, - on_logged_out: function() { + on_logout: function() { + this.session.session_logout(); + this.login.on_login_invalid(); + this.header.do_update(); $(window).unbind('hashchange', this.on_hashchange); - this.do_push_state({},true); + this.do_push_state({}); if(this.action_manager) this.action_manager.stop(); this.action_manager = null; @@ -1090,11 +1074,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie } this._current_state = state; }, - do_push_state: function(state, overwrite) { - if (!overwrite) { - var hash = $.deparam.fragment(true); - state = _.extend({}, hash, state); - } + do_push_state: function(state) { var url = '#' + $.param(state); this._current_state = _.clone(state); $.bbq.pushState(url); @@ -1113,6 +1093,47 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie }, }); +openerp.currentScript = function() { + var currentScript = document.currentScript; + if (!currentScript) { + var sc = document.getElementsByTagName('script'); + currentScript = sc[sc.length-1]; + } + return currentScript; +}; + +openerp.web.EmbeddedClient = openerp.web.Widget.extend({ + template: 'EmptyComponent', + init: function(action_id, options) { + this._super(); + // TODO take the xmlid of a action instead of its id + this.action_id = action_id; + this.options = options || {}; + this.am = new openerp.web.ActionManager(this); + }, + + start: function() { + var self = this; + + this.am.appendTo(this.$element.addClass('openerp')); + + return this.rpc("/web/action/load", { action_id: this.action_id }, function(result) { + var action = result.result; + action.flags = _.extend({ + //views_switcher : false, + search_view : false, + action_buttons : false, + sidebar : false + //pager : false + }, self.options, action.flags || {}); + + self.am.do_action(action); + }); + }, + +}); + + }; // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index d3734d29278..12422fb5434 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -254,14 +254,16 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry * Retrieves the object matching the provided key string. * * @param {String} key the key to fetch the object for + * @param {Boolean} [silent_error=false] returns undefined if the key or object is not found, rather than throwing an exception * @returns {Class} the stored class, to initialize * * @throws {openerp.web.KeyNotFound} if the object was not in the mapping * @throws {openerp.web.ObjectNotFound} if the object path was invalid */ - get_object: function (key) { + get_object: function (key, silent_error) { var path_string = this.map[key]; if (path_string === undefined) { + if (silent_error) { return void 'nooo'; } throw new openerp.web.KeyNotFound(key); } @@ -272,6 +274,7 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry object_match = object_match[path[i]]; if (object_match === undefined) { + if (silent_error) { return void 'noooooo'; } throw new openerp.web.ObjectNotFound(path_string); } } @@ -350,11 +353,19 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. * @param {String} [server] JSON-RPC endpoint hostname * @param {String} [port] JSON-RPC endpoint port */ - init: function(server, port) { + init: function() { this._super(); - this.server = (server == undefined) ? location.hostname : server; - this.port = (port == undefined) ? location.port : port; - this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp"; + // TODO: session store in cookie should be optional + this.name = openerp._session_id; + }, + bind: function(host, protocol) { + var self = this; + this.host = (host == undefined) ? location.host : host; + this.protocol = (protocol == undefined) ? location.protocol : protocol; + this.prefix = this.protocol + '//' + this.host; + openerp.web.qweb.default_dict['_s'] = this.prefix + this.rpc_mode = (this.host == location.host) ? "json" : "jsonp"; + this.rpc_function = (this.host == location.host) ? this.rpc_json : this.rpc_jsonp; this.debug = (window.location.search.indexOf('?debug') !== -1); this.session_id = false; this.uid = false; @@ -366,14 +377,8 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. this.context = {}; this.shortcuts = []; this.active_id = null; - // TODO: session should have an optional name indicating that they'll - // be saved to (and revived from) cookies - this.name = 'session'; - this.do_load_qweb(['/web/webclient/qweb']); - }, - - start: function() { - this.session_restore(); + this.ready = $.Deferred(); + return this.session_init(); }, /** * Executes an RPC call, registering the provided callbacks. @@ -390,82 +395,133 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. */ rpc: function(url, params, success_callback, error_callback) { var self = this; + // url can be an $.ajax option object + if (_.isString(url)) { + url = { url: url }; + } // Construct a JSON-RPC2 request, method is currently unused params.session_id = this.session_id; if (this.debug) params.debug = 1; - - // Call using the rpc_mode - var deferred = $.Deferred(); - this.rpc_ajax(url, { - jsonrpc: "2.0", - method: "call", + var payload = { + jsonrpc: '2.0', + method: 'call', params: params, - id: _.uniqueId('browser-client-') - }).then(function () {deferred.resolve.apply(deferred, arguments);}, - function(error) {deferred.reject(error, $.Event());}); - return deferred.fail(function() { + id: _.uniqueId('r') + }; + var deferred = $.Deferred(); + this.on_rpc_request(); + this.rpc_function(url, payload).then( + function (response, textStatus, jqXHR) { + self.on_rpc_response(); + if (!response.error) { + deferred.resolve(response["result"], textStatus, jqXHR); + } else if (response.error.data.type === "session_invalid") { + self.uid = false; + // TODO deprecate or use a deferred on login.do_ask_login() + self.on_session_invalid(function() { + self.rpc(url, payload.params, + function() { deferred.resolve.apply(deferred, arguments); }, + function() { deferred.reject.apply(deferred, arguments); }); + }); + } else { + deferred.reject(response.error, $.Event()); + } + }, + 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, $.Event()); + }); + // Allow deferred user to disable on_rpc_error in fail + deferred.fail(function() { deferred.fail(function(error, event) { if (!event.isDefaultPrevented()) { self.on_rpc_error(error, event); } }); }).then(success_callback, error_callback).promise(); + return deferred; }, /** * Raw JSON-RPC call * * @returns {jQuery.Deferred} ajax-webd deferred object */ - rpc_ajax: function(url, payload) { + rpc_json: 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 + 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] } + return $.ajax(ajax); + }, + rpc_jsonp: function(url, payload) { + var self = this; + // extracted from payload to set on the url + var data = { + session_id: this.session_id, + id: payload.id, + }; + url.url = this.get_url(url.url); + var ajax = _.extend({ + type: "GET", + dataType: 'jsonp', + jsonp: 'jsonp', + cache: false, + data: data + }, url); + var payload_str = JSON.stringify(payload); + var payload_url = $.param({r:payload_str}); + if(playload_url.length < 2000) { + // Direct jsonp request + ajax.data.r = payload_str; + return $.ajax(ajax); + } else { + // Indirect jsonp request + var ifid = _.uniqueId('oe_rpc_iframe'); + var display = options.openerp.debug ? 'block' : 'none'; + var $iframe = $(_.str.sprintf("<iframe src='javascript:false;' name='%s' id='%s' style='display:%s'></iframe>", ifid, ifid, display)); + var $form = $('<form>') + .attr('method', 'POST') + .attr('target', ifid) + .attr('enctype', "multipart/form-data") + .attr('action', ajax.url + '?' + $.param(data)) + .append($('<input type="hidden" name="r" />').attr('value', payload_str)) + .hide() + .appendTo($('body')); + var cleanUp = function() { + if ($iframe) { + $iframe.unbind("load").attr("src", "javascript:false;").remove(); + } + $form.remove(); }; - deferred.reject(error); - }); - return deferred.promise(); + var deferred = $.Deferred(); + // the first bind is fired up when the iframe is added to the DOM + $iframe.bind('load', function() { + // the second bind is fired up when the result of the form submission is received + $iframe.unbind('load').bind('load', function() { + $.ajax(ajax).always(function() { + cleanUp(); + }).then( + function() { deferred.resolve.apply(deferred, arguments); }, + function() { deferred.reject.apply(deferred, arguments); } + ); + }); + // now that the iframe can receive data, we fill and submit the form + $form.submit(); + }); + // append the iframe to the DOM (will trigger the first load) + $form.after($iframe); + return deferred; + } }, on_rpc_request: function() { }, @@ -474,75 +530,51 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. 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_authenticate: function(db, login, password, success_callback) { - var self = this; - var base_location = document.location.protocol + '//' + document.location.host; - var params = { db: db, login: login, password: password, base_location: base_location }; - return this.rpc("/web/session/authenticate", params, function(result) { - _.extend(self, { - session_id: result.session_id, - uid: result.uid, - user_context: result.context, - db: result.db, - username: result.login - }); - self.session_save(); - self.on_session_valid(); - return true; - }).then(success_callback); - }, - login: function() { this.session_authenticate.apply(this, arguments); }, - /** - * Reloads uid and session_id from local storage, if they exist + * Init a session, reloads from cookie, if it exists */ - session_restore: function () { + session_init: function () { var self = this; + // TODO: session store in cookie should be optional this.session_id = this.get_cookie('session_id'); - return this.rpc("/web/session/get_session_info", {}).then(function(result) { + return this.rpc("/web/session/get_session_info", {}).pipe(function(result) { // If immediately follows a login (triggered by trying to restore // an invalid session or no session at all), refresh session data - // (should not change, but just in case...) but should not call - // on_session_valid again as it triggers reloading the menu - var already_logged = self.uid; + // (should not change, but just in case...) _.extend(self, { - uid: result.uid, - user_context: result.context, db: result.db, - username: result.login + username: result.login, + uid: result.uid, + user_context: result.context }); - if (!already_logged) { - if (self.uid) { - self.on_session_valid(); - } else { - self.on_session_invalid(); - } + var deferred = self.do_load_qweb(['/web/webclient/qweb']); + if(self.uid) { + return deferred.then(self.load_modules()); } - }, function() { - self.on_session_invalid(); + return deferred; }); }, /** - * Saves the session id and uid locally + * The session is validated either by login or by restoration of a previous session */ - session_save: function () { - this.set_cookie('session_id', this.session_id); + session_authenticate: function(db, login, password) { + var self = this; + var base_location = document.location.protocol + '//' + document.location.host; + var params = { db: db, login: login, password: password, base_location: base_location }; + return this.rpc("/web/session/authenticate", params).pipe(function(result) { + _.extend(self, { + session_id: result.session_id, + db: result.db, + username: result.login, + uid: result.uid, + user_context: result.context + }); + // TODO: session store in cookie should be optional + self.set_cookie('session_id', self.session_id); + return self.load_modules(); + }); }, - logout: function() { + session_logout: function() { this.set_cookie('session_id', ''); - this.reload_client(); - }, - reload_client: function() { window.location.reload(); }, /** @@ -586,23 +618,28 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. */ load_modules: function() { var self = this; + if(openerp._modules_loaded) { + return $.when(); + } this.rpc('/web/session/modules', {}, function(result) { self.module_list = result; var lang = self.user_context.lang; var params = { mods: ["web"].concat(result), lang: lang}; - self.rpc('/web/webclient/translations',params).then(function(transs) { + self.rpc('/web/webclient/translations',params).pipe(function(transs) { openerp.web._t.database.set_bundle(transs); var modules = self.module_list.join(','); var file_list = ["/web/static/lib/datejs/globalization/" + self.user_context.lang.replace("_", "-") + ".js" ]; - - self.rpc('/web/webclient/csslist', {"mods": modules}, self.do_load_css); - self.rpc('/web/webclient/jslist', {"mods": modules}, function(files) { - self.do_load_js(file_list.concat(files)); + return $.when( + self.rpc('/web/webclient/csslist', {mods: modules}, self.do_load_css), + self.rpc('/web/webclient/qweblist', {mods: modules}).pipe(self.do_load_qweb), + self.rpc('/web/webclient/jslist', {mods: modules}).pipe(function(files) { + return self.do_load_js(file_list.concat(files)); + }) + ).then(function() { + self.ready.resolve(); }); - self.rpc('/web/webclient/qweblist', {"mods": modules}, self.do_load_qweb); - openerp._modules_loaded = true; }); }); }, @@ -610,7 +647,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. var self = this; _.each(files, function (file) { $('head').append($('<link>', { - 'href': file, + 'href': self.get_url(file), 'rel': 'stylesheet', 'type': 'text/css' })); @@ -618,28 +655,39 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. }, do_load_js: function(files) { var self = this; + var d = $.Deferred(); if(files.length != 0) { var file = files.shift(); var tag = document.createElement('script'); tag.type = 'text/javascript'; - tag.src = file; + tag.src = self.get_url(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); + self.do_load_js(files).then(function () { + d.resolve(); + }); }; var head = document.head || document.getElementsByTagName('head')[0]; head.appendChild(tag); } else { - this.on_modules_loaded(); + self.on_modules_loaded(); + d.resolve(); } + return d; }, do_load_qweb: function(files) { var self = this; - _.each(files, function(file) { - openerp.web.qweb.add_template(file); - }); + if (files.length != 0) { + var file = files.shift(); + return self.rpc('/web/proxy/load', {path: file}).pipe(function(xml) { + openerp.web.qweb.add_template(_.str.trim(xml)); + return self.do_load_qweb(files); + }); + } else { + return $.when(); + } }, on_modules_loaded: function() { for(var j=0; j<this.module_list.length; j++) { @@ -654,6 +702,9 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. } } }, + get_url: function (file) { + return this.prefix + file; + }, /** * Cooperative file download implementation, for ajaxy APIs. * @@ -1069,6 +1120,7 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we } }); +/** Configure blockui */ if ($.blockUI) { $.blockUI.defaults.baseZ = 1100; $.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">'; @@ -1100,6 +1152,7 @@ openerp.web.qweb.format_text_node = function(s) { openerp.connection = new openerp.web.Connection(); openerp.web.qweb.default_dict['__debug__'] = openerp.connection.debug; +/** Jquery extentions */ $.Mutex = (function() { function Mutex() { this.def = $.Deferred().resolve(); diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 26147b4d4e0..46393aaf205 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -510,9 +510,10 @@ openerp.web.DataSetStatic = openerp.web.DataSet.extend({ }, set_ids: function (ids) { this.ids = ids; - if (this.index !== null) { - this.index = this.index <= this.ids.length - 1 ? - this.index : (this.ids.length > 0 ? this.length - 1 : 0); + if (ids.length === 0) { + this.index = null; + } else if (this.index >= ids.length - 1) { + this.index = ids.length - 1; } }, unlink: function(ids) { @@ -811,7 +812,7 @@ openerp.web.ProxyDataSet = openerp.web.DataSetSearch.extend({ }); openerp.web.Model = openerp.web.CallbackEnabled.extend({ - init: function(_, model_name) { + init: function(model_name) { this._super(); this.model_name = model_name; }, diff --git a/addons/web/static/src/js/data_export.js b/addons/web/static/src/js/data_export.js index ea142606b5b..8a2d2c8594b 100644 --- a/addons/web/static/src/js/data_export.js +++ b/addons/web/static/src/js/data_export.js @@ -1,8 +1,9 @@ openerp.web.data_export = function(openerp) { -var QWeb = openerp.web.qweb; +var QWeb = openerp.web.qweb, + _t = openerp.web._t; openerp.web.DataExport = openerp.web.Dialog.extend({ template: 'ExportTreeView', - dialog_title: 'Export Data', + dialog_title: {toString: function () { return _t("Export Data"); }}, init: function(parent, dataset) { this._super(parent); this.records = {}; @@ -18,14 +19,10 @@ openerp.web.DataExport = openerp.web.Dialog.extend({ width: '55%', height: 'auto', position: 'top', - buttons : { - "Close" : function() { - self.close(); - }, - "Export To File" : function() { - self.on_click_export_data(); - } - }, + buttons : [ + {text: _t("Close"), click: function() { self.close(); }}, + {text: _t("Export To File"), click: function() { self.on_click_export_data(); }} + ], close: function(event, ui){ self.close();} }); self.$element.removeClass('ui-dialog-content ui-widget-content'); diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index cd699c0481d..3d626db125d 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -31,7 +31,7 @@ function jsonp(form, attributes, callback) { openerp.web.DataImport = openerp.web.Dialog.extend({ template: 'ImportDataView', - dialog_title: "Import Data", + dialog_title: {toString: function () { return _t("Import Data"); }}, init: function(parent, dataset){ var self = this; this._super(parent, {}); @@ -111,7 +111,11 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ }); } _(fields).each(function (field, field_name) { - if (field_name === 'id') { return; } + // Ignore spec for id field + // Don't import function fields (function and related) + if (field_name === 'id' || 'function' in field) { + return; + } var f = { id: field_name, name: field_name, diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index 2df651158eb..264cc836e2d 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -254,7 +254,7 @@ openerp.web.format_cell = function (row_data, column, value_if_empty, process_mo if (column.tag === 'button') { return [ '<button type="button" title="', column.string || '', '">', - '<img src="/web/static/src/img/icons/', column.icon, '.png"', + '<img src="', openerp.connection.prefix, '/web/static/src/img/icons/', column.icon, '.png"', ' alt="', column.string || '', '"/>', '</button>' ].join('') diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js index 352856c2b6c..f925a6416eb 100644 --- a/addons/web/static/src/js/view_editor.js +++ b/addons/web/static/src/js/view_editor.js @@ -35,28 +35,19 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ pager: false, radio: true, select_view_id: self.parent.fields_view.view_id - }, + } }; this.view_edit_dialog = new openerp.web.Dialog(this, { modal: true, - title: 'ViewEditor', + title: _t("ViewEditor"), width: 750, height: 500, - buttons: { - "Create": function(){ - self.on_create_view(); - }, - "Edit": function(){ - self.xml_element_id = 0; - self.get_arch(); - }, - "Remove": function(){ - self.do_delete_view(); - }, - "Close": function(){ - self.view_edit_dialog.close(); - } - }, + buttons: [ + {text: _t("Create"), click: function() { self.on_create_view(); }}, + {text: _t("Edit"), click: function() { self.xml_element_id = 0; self.get_arch(); }}, + {text: _t("Remove"), click: function() { self.do_delete_view(); }}, + {text: _t("Close"), click: function() { self.view_edit_dialog.close(); }} + ] }).start().open(); this.main_view_id = this.parent.fields_view.view_id; this.action_manager = new openerp.web.ActionManager(this); @@ -77,36 +68,34 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ var self = this; this.create_view_dialog = new openerp.web.Dialog(this, { modal: true, - title: _.str.sprintf("Create a view (%s)", self.model), + title: _.str.sprintf(_t("Create a view (%s)"), self.model), width: 500, height: 400, - buttons: { - "Save": function(){ - var view_values = {}; - var warn = false; - _.each(self.create_view_widget, function(widget) { - if (widget.is_invalid) { - warn = true; - return false; - }; - if (widget.dirty && !widget.is_invalid) { - view_values[widget.name] = widget.get_value(); - } - }); - if (warn) { - self.on_valid_create_view(self.create_view_widget); - } else { - $.when(self.do_save_view(view_values)).then(function() { - self.create_view_dialog.close(); - var controller = self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller; - controller.reload_content(); - }); + buttons: [ + {text: _t("Save"), click: function () { + var view_values = {}; + var warn = false; + _.each(self.create_view_widget, function(widget) { + if (widget.is_invalid) { + warn = true; + return false; } - }, - "Cancel": function(){ - self.create_view_dialog.close(); + if (widget.dirty && !widget.is_invalid) { + view_values[widget.name] = widget.get_value(); + } + }); + if (warn) { + self.on_valid_create_view(self.create_view_widget); + } else { + $.when(self.do_save_view(view_values)).then(function() { + self.create_view_dialog.close(); + var controller = self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller; + controller.reload_content(); + }); } - } + }}, + {text: _t("Cancel"), click: function () { self.create_view_dialog.close(); }} + ] }); this.create_view_dialog.start().open(); var view_widget = [{'name': 'view_name', 'string':'View Name', 'type': 'char', 'required': true, 'value' : this.model + '.custom_' + Math.round(Math.random() * 1000)}, @@ -375,11 +364,11 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ this.one_object = one_object; this.edit_xml_dialog = new openerp.web.Dialog(this, { modal: true, - title: _.str.sprintf("View Editor %d - %s", self.main_view_id, self.model), + title: _.str.sprintf(_t("View Editor %d - %s"), self.main_view_id, self.model), width: 750, height: 500, - buttons: { - "Preview": function() { + buttons: [ + {text: _t("Preview"), click: function() { var action = { context: self.session.user_context, res_model: self.model, @@ -389,16 +378,16 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ flags: { sidebar: false, views_switcher: false, - action_buttons: false, - }, + action_buttons: false + } }; var action_manager = new openerp.web.ActionManager(self); action_manager.do_action(action); - }, - "Close": function(){ + }}, + {text: _t("Close"), click: function(){ self.edit_xml_dialog.close(); - } - } + }} + ] }).start().open(); var no_property_att = []; _.each(_PROPERTIES, function(val, key) { @@ -764,17 +753,17 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ var self = this; this.edit_node_dialog = new openerp.web.Dialog(this,{ modal: true, - title: 'Properties', + title: _t("Properties"), width: 500, height: 400, - buttons: { - "Update": function(){ + buttons: [ + {text: _t("Update"), click: function () { var warn = false, update_values = []; _.each(self.edit_widget, function(widget) { if (widget.is_invalid) { warn = true; return false; - }; + } if (widget.dirty && !widget.is_invalid) { update_values.push([widget.name, widget.get_value()]); } @@ -785,11 +774,9 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ self.do_save_update_arch("update_node", update_values); self.edit_node_dialog.close(); } - }, - "Cancel": function(){ - self.edit_node_dialog.close(); - } - } + }}, + {text: _t("Cancel"), click: function () { self.edit_node_dialog.close(); }} + ] }); this.edit_node_dialog.start().open(); var _PROPERTIES_ATTRIBUTES = { @@ -893,32 +880,32 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ this.add_widget = []; this.add_node_dialog = new openerp.web.Dialog(this,{ modal: true, - title: 'Properties', + title: _t("Properties"), width: 450, height: 190, - buttons: { - "Update": function(){ - var check_add_node = true, values = {}; - _.each(self.add_widget, function(widget) { - values[widget.name] = widget.get_value() || false; - }); - (values.position == "Inside")? - check_add_node =(_.include(_CHILDREN[properties[0]],values.node_type))?true:false: - check_add_node =(_.include(_CHILDREN[properties[1]],values.node_type))?true:false; - if(values.node_type == "field" && check_add_node ) - {check_add_node = (values.field_value != " ")?true:false; - } - if(check_add_node){ - var tag = (values.node_type == "field")? - _.str.sprintf("<%s name='%s'> </%s>",values.node_type,values.field_value,values.node_type): - _.str.sprintf("<%s> </%s>",values.node_type,values.node_type); - self.do_save_update_arch("add_node", [tag, values.position]); - }else{alert("Can't Update View");} - }, - "Cancel": function(){ - self.add_node_dialog.close(); + buttons: [ + {text: _t("Update"), click: function() { + var check_add_node = true, values = {}; + _.each(self.add_widget, function(widget) { + values[widget.name] = widget.get_value() || false; + }); + (values.position == "Inside")? + check_add_node =(_.include(_CHILDREN[properties[0]],values.node_type))?true:false: + check_add_node =(_.include(_CHILDREN[properties[1]],values.node_type))?true:false; + if(values.node_type == "field" && check_add_node ) + {check_add_node = (values.field_value != " ")?true:false; } - } + if(check_add_node){ + var tag = (values.node_type == "field")? + _.str.sprintf("<%s name='%s'> </%s>",values.node_type,values.field_value,values.node_type): + _.str.sprintf("<%s> </%s>",values.node_type,values.node_type); + self.do_save_update_arch("add_node", [tag, values.position]); + } else { + alert("Can't Update View"); + } + }}, + {text: _t("Cancel"), click: function() { self.add_node_dialog.close(); }} + ] }).start().open(); this.add_node_dialog.$element.append('<table id="rec_table" style="width:420px" class="oe_forms"><tbody><tr></tbody></table>'); var table_selector = self.add_node_dialog.$element.find('table[id=rec_table] tbody'); diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 5908dc67dc6..0d962353b78 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -13,6 +13,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# readonly : false, form_template: "FormView", identifier_prefix: 'formview-', + display_name: {toString: function () { return _t('Form'); }}, /** * @constructs openerp.web.FormView * @extends openerp.web.View @@ -117,6 +118,18 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } this.has_been_loaded.resolve(); }, + + do_load_state: function(state) { + if (state.id && this.datarecord.id != state.id) { + var idx = this.dataset.get_id_index(state.id); + if (idx === null) { + this.dataset.ids.push(state.id) + this.dataset.index = this.dataset.ids.length - 1; + } + this.do_show(); + } + }, + do_show: function () { var promise; if (this.dataset.index === null) { @@ -132,7 +145,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# return promise; }, do_hide: function () { - this.$element.hide(); + this._super(); if (this.sidebar) { this.sidebar.$element.hide(); } @@ -140,7 +153,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# on_record_loaded: function(record) { var self = this, set_values = []; if (!record) { - throw("Form: No record received"); + throw new Error("Form: No record received"); } this.datarecord = record; @@ -175,6 +188,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# if (self.default_focus_field && !self.embedded_view) { self.default_focus_field.focus(); } + if (record.id) { + self.do_push_state({id:record.id}); + } }); }, on_form_changed: function() { @@ -334,11 +350,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# if (!_.isEmpty(result.warning)) { $(QWeb.render("DialogWarning", result.warning)).dialog({ modal: true, - buttons: { - Ok: function() { - $(this).dialog("close"); - } - } + buttons: [ + {text: _t("Ok"), click: function() { $(this).dialog("close"); }} + ] }); } if (result.domain) { @@ -626,7 +640,7 @@ openerp.web.form.SidebarAttachments = openerp.web.Widget.extend({ on_attachment_delete: function(e) { var self = this, $e = $(e.currentTarget); var name = _.str.trim($e.parent().find('a.oe-sidebar-attachments-link').text()); - if (confirm("Do you really want to delete the attachment " + name + " ?")) { + if (confirm(_.sprintf(_t("Do you really want to delete the attachment %s?"), name))) { this.rpc('/web/dataset/unlink', { model: 'ir.attachment', ids: [parseInt($e.attr('data-id'))] @@ -1048,20 +1062,22 @@ openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({ if (self.node.attrs.confirm) { var def = $.Deferred(); var dialog = $('<div>' + self.node.attrs.confirm + '</div>').dialog({ - title: 'Confirm', + title: _t('Confirm'), modal: true, - buttons: { - Ok: function() { - self.on_confirmed().then(function() { - def.resolve(); - }); - $(this).dialog("close"); + buttons: [ + {text: _t("Ok"), click: function() { + self.on_confirmed().then(function() { + def.resolve(); + }); + $(this).dialog("close"); + } }, - Cancel: function() { - def.resolve(); - $(this).dialog("close"); + {text: _t("Cancel"), click: function() { + def.resolve(); + $(this).dialog("close"); + } } - } + ] }); return def.promise(); } else { @@ -2055,7 +2071,9 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ }); this.views = views; - this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views); + this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views, { + action_buttons : false + }); this.viewmanager.template = 'One2Many.viewmanager'; this.viewmanager.registry = openerp.web.views.clone({ list: 'openerp.web.form.One2ManyListView', @@ -2083,7 +2101,6 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ controller.on_pager_action.add_first(function() { self.save_any_view(); }); - controller.$element.find(".oe_form_button_save").hide(); } else if (view_type == "graph") { self.reload_current_view() } @@ -2370,7 +2387,7 @@ openerp.web.form.FieldMany2Many = openerp.web.form.Field.extend({ load_view: function() { var self = this; this.list_view = new openerp.web.form.Many2ManyListView(this, this.dataset, false, { - 'addable': self.is_readonly() ? null : 'Add', + 'addable': self.is_readonly() ? null : _t("Add"), 'deletable': self.is_readonly() ? false : true, 'selectable': self.multi_selection }); @@ -2905,13 +2922,18 @@ openerp.web.form.FieldBinaryFile = openerp.web.form.FieldBinary.extend({ }, set_value: function(value) { this._super.apply(this, arguments); - var show_value = (value != null && value !== false) ? value : ''; + var show_value; + if (this.node.attrs.filename) { + show_value = this.view.datarecord[this.node.attrs.filename] || ''; + } else { + show_value = (value != null && value !== false) ? value : ''; + } this.$element.find('input').eq(0).val(show_value); }, on_file_uploaded_and_valid: function(size, name, content_type, file_base64) { this.value = file_base64; this.binary_value = true; - var show_value = this.human_filesize(size); + var show_value = name + " (" + this.human_filesize(size) + ")"; this.$element.find('input').eq(0).val(show_value); this.set_filename(name); }, diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index bf423434ecc..8ed475c75f6 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -4,6 +4,7 @@ var QWeb = openerp.web.qweb; openerp.web.views.add('list', 'openerp.web.ListView'); openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# */ { _template: 'ListView', + display_name: {toString: function () { return _t('List'); }}, defaults: { // records can be selected one by one 'selectable': true, @@ -12,12 +13,14 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# // whether the column headers should be displayed 'header': true, // display addition button, with that label - 'addable': _t("Create"), + 'addable': {toString: function () { return _t("Create"); }}, // whether the list view can be sorted, note that once a view has been // sorted it can not be reordered anymore 'sortable': true, // whether the view rows can be reordered (via vertical drag & drop) - 'reorderable': true + 'reorderable': true, + // display an edit icon linking to form view + 'isClarkGable': true }, /** * Core class for list-type displays. @@ -120,8 +123,8 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# 'action': function (e, 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); + 'row_link': function (e, id, dataset, view) { + self.do_activate_record(dataset.index, id, dataset, view); } }); }, @@ -402,13 +405,13 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# }, this)); }, do_show: function () { - this.$element.show(); + this._super(); if (this.sidebar) { this.sidebar.$element.show(); } }, do_hide: function () { - this.$element.hide(); + this._super(); if (this.sidebar) { this.sidebar.$element.hide(); } @@ -457,8 +460,32 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# self.compute_aggregates(); reloaded.resolve(); })); + this.do_push_state({ + page: this.page, + limit: this._limit, + }); return reloaded.promise(); }, + + do_load_state: function(state) { + var reload = false; + if (state.page && this.page !== state.page) { + this.page = state.page; + reload = true; + } + if (state.limit) { + if (_.isString(state.limit)) { + state.limit = null; + } + if (state.limit !== this._limit) { + this._limit = state.limit; + reload = true; + } + } + if (reload) { + this.reload_content(); + } + }, /** * Handler for the result of eval_domain_and_context, actually perform the * searching @@ -556,9 +583,9 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# * @param {Object} id identifier of the activated record * @param {openerp.web.DataSet} dataset dataset in which the record is available (may not be the listview's dataset in case of nested groups) */ - do_activate_record: function (index, id, dataset) { + do_activate_record: function (index, id, dataset, view) { this.dataset.ids = dataset.ids; - this.select_record(index); + this.select_record(index, view); }, /** * Handles signal for the addition of a new record (can be a creation, @@ -818,15 +845,19 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis if (!self.dataset.select_id(row_id)) { throw "Could not find id in dataset" } - self.row_clicked(e); + var view; + if ($(e.target).is('.oe-record-edit-link-img')) { + view = 'form'; + } + self.row_clicked(e, view); } }); }, - row_clicked: function () { + row_clicked: function (e, view) { $(this).trigger( 'row_link', [this.dataset.ids[this.dataset.index], - this.dataset]); + this.dataset, view]); }, render_cell: function (record, column) { var value; @@ -887,6 +918,9 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis if (this.options.selectable) { cells.push('<th class="oe-record-selector"></td>'); } + if (this.options.isClarkGable) { + cells.push('<th class="oe-record-edit-link"></td>'); + } _(this.columns).each(function(column) { if (column.invisible === '1') { return; diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index b2edf55b314..453536f7ec6 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -116,7 +116,7 @@ openerp.web.list_editable = function (openerp) { openerp.web.ListView.List.include(/** @lends openerp.web.ListView.List# */{ row_clicked: function (event) { if (!this.options.editable) { - return this._super(event); + return this._super.apply(this, arguments); } this.edit_record($(event.currentTarget).data('id')); }, @@ -248,7 +248,10 @@ openerp.web.list_editable = function (openerp) { .end() .find('td:last').removeClass('oe-field-cell').end(); if (self.options.selectable) { - $new_row.prepend('<td>'); + $new_row.prepend('<th>'); + } + if (self.options.isClarkGable) { + $new_row.prepend('<th>'); } // pad in case of groupby _(self.columns).each(function (column) { diff --git a/addons/web/static/src/js/view_page.js b/addons/web/static/src/js/view_page.js index 40ca1176c79..1b23198da67 100644 --- a/addons/web/static/src/js/view_page.js +++ b/addons/web/static/src/js/view_page.js @@ -5,6 +5,7 @@ openerp.web.page = function (openerp) { openerp.web.views.add('page', 'openerp.web.PageView'); openerp.web.PageView = openerp.web.FormView.extend({ form_template: "PageView", + display_name: {toString: function () { return _t('Page'); }}, init: function () { this._super.apply(this, arguments); this.registry = openerp.web.page.readonly; @@ -200,6 +201,27 @@ openerp.web.page = function (openerp) { openerp.web.page.FieldOne2ManyReadonly = openerp.web.form.FieldOne2Many.extend({ force_readonly: true }); + openerp.web.page.FieldBinaryFileReadonly = openerp.web.form.FieldBinary.extend({ + template: 'FieldURI.readonly', + start: function() { + this._super.apply(this, arguments); + var self = this; + this.$element.find('a').click(function() { + if (self.value) { + self.on_save_as(); + } + return false; + }); + }, + set_value: function(value) { + this._super.apply(this, arguments); + this.$element.find('a').show(!!value); + if (value) { + var show_value = _t("Download") + " " + (this.view.datarecord[this.node.attrs.filename] || ''); + this.$element.find('a').text(show_value); + } + } + }); openerp.web.page.readonly = openerp.web.form.widgets.clone({ 'frame': 'openerp.web.page.WidgetFrameReadonly', 'char': 'openerp.web.page.FieldCharReadonly', @@ -218,6 +240,7 @@ openerp.web.page = function (openerp) { 'boolean': 'openerp.web.page.FieldBooleanReadonly', 'float': 'openerp.web.page.FieldCharReadonly', 'integer': 'openerp.web.page.FieldCharReadonly', - 'float_time': 'openerp.web.page.FieldCharReadonly' + 'float_time': 'openerp.web.page.FieldCharReadonly', + 'binary': 'openerp.web.page.FieldBinaryFileReadonly', }); }; diff --git a/addons/web/static/src/js/view_tree.js b/addons/web/static/src/js/view_tree.js index 34d47b92813..48f7290c8d9 100644 --- a/addons/web/static/src/js/view_tree.js +++ b/addons/web/static/src/js/view_tree.js @@ -3,10 +3,12 @@ *---------------------------------------------------------*/ openerp.web.view_tree = function(openerp) { -var QWeb = openerp.web.qweb; +var QWeb = openerp.web.qweb, + _t = openerp.web._t; openerp.web.views.add('tree', 'openerp.web.TreeView'); openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView# */{ + display_name: {toString: function () { return _t('Tree'); }}, /** * Indicates that this view is not searchable, and thus that no search * view should be displayed (if there is one active). @@ -111,6 +113,9 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView# } }); + // TODO store open nodes in url ?... + this.do_push_state({}); + if (!this.fields_view.arch.attrs.colors) { return; } diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 0ad49f69f7b..5800939ec36 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -20,6 +20,7 @@ session.web.ActionManager = session.web.Widget.extend({ identifier_prefix: "actionmanager", init: function(parent) { this._super(parent); + this.inner_action = null; this.inner_viewmanager = null; this.dialog = null; this.dialog_viewmanager = null; @@ -46,37 +47,47 @@ session.web.ActionManager = session.web.Widget.extend({ this.client_widget = null; } }, - - do_push_state: function(state, overwrite) { + do_push_state: function(state) { + if (this.widget_parent && this.widget_parent.do_push_state) { + if (this.inner_action && this.inner_action.id) { + state['action_id'] = this.inner_action.id; + } + this.widget_parent.do_push_state(state); + } }, - do_load_state: function(state) { + var self = this, + action_loaded; if (state.action_id) { - this.null_action(); - this.do_action(state.action_id); + var run_action = (!this.inner_viewmanager) || this.inner_viewmanager.action.id !== state.action_id; + if (run_action) { + this.null_action(); + action_loaded = this.do_action(state.action_id); + } } else if (state.model && state.id) { // TODO implement it //this.null_action(); - // action = {} + //action = {res_model: state.model, res_id: state.id}; + //action_loaded = this.do_action(action); } else if (state.client_action) { this.null_action(); this.ir_actions_client(state.client_action); } - if (this.inner_viewmanager) { - this.inner_viewmanager.do_load_state(state); - } + $.when(action_loaded || null).then(function() { + if (self.inner_viewmanager) { + self.inner_viewmanager.do_load_state(state); + } + }); }, - do_action: function(action, on_close) { if (_.isNumber(action)) { var self = this; - self.rpc("/web/action/load", { action_id: action }, function(result) { + return self.rpc("/web/action/load", { action_id: action }, function(result) { self.do_action(result.result, on_close); }); - return; } if (!action.type) { console.error("No type for action", action); @@ -128,10 +139,6 @@ session.web.ActionManager = session.web.Widget.extend({ this.content_stop(); this.inner_action = action; this.inner_viewmanager = new session.web.ViewManagerAction(this, action); - this.inner_viewmanager.do_push_state.add(function(state,overwrite) { - state['action_id'] = action.id; - self.do_push_state(state,true); - }); this.inner_viewmanager.appendTo(this.$element); } }, @@ -152,12 +159,9 @@ session.web.ActionManager = session.web.Widget.extend({ }, ir_actions_client: function (action) { this.content_stop(); + this.dialog_stop(); var ClientWidget = session.web.client_actions.get_object(action.tag); (this.client_widget = new ClientWidget(this, action.params)).appendTo(this); - - var client_action = {tag: action.tag}; - if (action.params) _.extend(client_action, {params: action.params}); - this.do_push_state({client_action: client_action}, true); }, ir_actions_report_xml: function(action, on_closed) { var self = this; @@ -200,15 +204,26 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View * @param dataset * @param views */ - init: function(parent, dataset, views) { + init: function(parent, dataset, views, flags) { this._super(parent); this.model = dataset ? dataset.model : undefined; 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) { + if (x instanceof Array) { + var View = session.web.views.get_object(x[1], true); + return { + view_id: x[0], + view_type: x[1], + label: View ? View.prototype.display_name : (void 'nope') + }; + } else { + return x; + } + }); this.views = {}; - this.flags = this.flags || {}; + this.flags = flags || {}; this.registry = session.web.views; this.views_history = []; }, @@ -314,8 +329,6 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View }); return view_promise; }, - - /** * Returns to the view preceding the caller view in this manager's * navigation history (the navigation history is appended to via @@ -391,7 +404,8 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View /** * Called by children view after executing an action */ - on_action_executed: function () {}, + on_action_executed: function () { + }, display_title: function () { var view = this.views[this.active_view]; if (view) { @@ -415,19 +429,10 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner // dataset initialization will take the session from ``this``, so if we // do not have it yet (and we don't, because we've not called our own // ``_super()``) rpc requests will blow up. - this._super(parent, null, action.views); - this.session = parent.session; - this.action = action; - var dataset = new session.web.DataSetSearch(this, action.res_model, action.context, action.domain); - if (action.res_id) { - dataset.ids.push(action.res_id); - dataset.index = 0; - } - this.dataset = dataset; - this.flags = this.action.flags || {}; + var flags = action.flags || {}; if (action.res_model == 'board.board' && action.view_mode === 'form') { // Special case for Dashboards - _.extend(this.flags, { + _.extend(flags, { views_switcher : false, display_title : false, search_view : false, @@ -436,6 +441,15 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner action_buttons : false }); } + this._super(parent, null, action.views, flags); + this.session = parent.session; + this.action = action; + var dataset = new session.web.DataSetSearch(this, action.res_model, action.context, action.domain); + if (action.res_id) { + dataset.ids.push(action.res_id); + dataset.index = 0; + } + this.dataset = dataset; // setup storage for session-wise menu hiding if (this.session.hidden_menutips) { @@ -466,12 +480,6 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner var main_view_loaded = this._super(); - _.each(_.keys(this.views), function(view_type) { - $.when(self.views[view_type].deferred).done(function(view_type) { - self.views[view_type].controller.do_push_state.add(self.do_push_state); - }); - }); - var manager_ready = $.when(searchview_loaded, main_view_loaded); this.$element.find('.oe_debug_view').change(this.on_debug_changed); @@ -584,21 +592,25 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner } else { $search_prefix.remove(); } - - self.do_push_state({view_type: self.active_view}); }); }, - - do_push_state: function(state, overwrite) { + do_push_state: function(state) { + if (this.widget_parent && this.widget_parent.do_push_state) { + state["view_type"] = this.active_view; + this.widget_parent.do_push_state(state); + } }, - do_load_state: function(state) { - var self = this; - $.when(this.on_mode_switch(state.view_type, true)).done(function() { + var self = this, + defs = []; + if (state.view_type && state.view_type !== this.active_view) { + defs.push(this.on_mode_switch(state.view_type, true)); + } + + $.when(defs).then(function() { self.views[self.active_view].controller.do_load_state(state); }); }, - shortcut_check : function(view) { var self = this; var grandparent = this.widget_parent && this.widget_parent.widget_parent; @@ -851,7 +863,7 @@ session.web.Sidebar = session.web.Widget.extend({ }); session.web.TranslateDialog = session.web.Dialog.extend({ - dialog_title: _t("Translations"), + dialog_title: {toString: function () { return _t("Translations"); }}, init: function(view) { // TODO fme: should add the language to fields_view_get because between the fields view get // and the moment the user opens the translation dialog, the user language could have been changed @@ -966,6 +978,8 @@ session.web.TranslateDialog = session.web.Dialog.extend({ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{ template: "EmptyComponent", + // name displayed in view switchers + display_name: '', set_default_options: function(options) { this.options = options || {}; _.defaults(this.options, { @@ -1064,19 +1078,33 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{ this.embedded_view = embedded_view; this.options.sidebar = false; }, + do_show: function () { + this.$element.show(); + }, + do_hide: function () { + this.$element.hide(); + }, + do_push_state: function(state) { + if (this.widget_parent && this.widget_parent.do_push_state) { + this.widget_parent.do_push_state(state); + } + }, + do_load_state: function(state) { + }, /** * Switches to a specific view type * * @param {String} view view type to switch to */ - do_switch_view: function(view) { }, + do_switch_view: function(view) { + }, /** * Cancels the switch to the current view, switches to the previous one */ - do_prev_view: function () { }, + do_prev_view: function () { + }, do_search: function(view) { }, - set_common_sidebar_sections: function(sidebar) { sidebar.add_default_sections(); }, @@ -1144,12 +1172,6 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{ }, sidebar_context: function () { return $.Deferred().resolve({}).promise(); - }, - - do_push_state: function(state, overwrite) { - }, - - do_load_state: function(state) { } }); |
