diff options
| author | Vidhin Mehta (OpenERP) <vme@tinyerp.com> | 2011-11-22 11:47:53 +0530 |
|---|---|---|
| committer | Vidhin Mehta (OpenERP) <vme@tinyerp.com> | 2011-11-22 11:47:53 +0530 |
| commit | 67e7ba0d0037e82196d34c4a0e57244ea40f015e (patch) | |
| tree | af48ad5669afedcb28bd3ab9a862f3ec5a50e332 /addons/web/static/src/js | |
| parent | d206d8dc42f4c364a407637d346e18d01ae4eaad (diff) | |
| parent | 1a2277c1407315546559eb8ed838018febcba9d5 (diff) | |
[MERGE]resove conflict and merge with main branch.
bzr revid: vme@tinyerp.com-20111122061753-5uxqy3mxw0eedthn
Diffstat (limited to 'addons/web/static/src/js')
| -rw-r--r-- | addons/web/static/src/js/chrome.js | 55 | ||||
| -rw-r--r-- | addons/web/static/src/js/core.js | 31 | ||||
| -rw-r--r-- | addons/web/static/src/js/data.js | 11 | ||||
| -rw-r--r-- | addons/web/static/src/js/formats.js | 14 | ||||
| -rw-r--r-- | addons/web/static/src/js/search.js | 10 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_editor.js | 288 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_form.js | 159 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list.js | 18 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_tree.js | 17 | ||||
| -rw-r--r-- | addons/web/static/src/js/views.js | 8 |
10 files changed, 341 insertions, 270 deletions
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index 25b73ee59d5..2b838ee3743 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -158,7 +158,7 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({ }, on_managed_error: function(error) { $('<div>' + QWeb.render('DialogWarning', {error: error}) + '</div>').dialog({ - title: "OpenERP " + _.capitalize(error.type), + title: "OpenERP " + _.str.capitalize(error.type), buttons: { Ok: function() { $(this).dialog("close"); @@ -168,7 +168,7 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({ }, on_traceback: function(error) { var dialog = new openerp.web.Dialog(this, { - title: "OpenERP " + _.capitalize(error.type), + title: "OpenERP " + _.str.capitalize(error.type), autoOpen: true, width: '90%', height: '90%', @@ -184,7 +184,8 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({ } }); -openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# */{ +openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# */{ + template: 'Loading', /** * @constructs openerp.web.Loading * @extends openerp.web.Widget @@ -192,8 +193,8 @@ openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# * @param parent * @param element_id */ - init: function(parent, element_id) { - this._super(parent, element_id); + init: function(parent) { + this._super(parent); this.count = 0; this.blocked_ui = false; this.session.on_rpc_request.add_first(this.on_rpc_event, 1); @@ -210,12 +211,13 @@ openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading# } this.count += increment; - if (this.count) { + if (this.count > 0) { //this.$element.html(QWeb.render("Loading", {})); this.$element.html("Loading ("+this.count+")"); this.$element.show(); this.widget_parent.$element.addClass('loading'); } else { + this.count = 0; clearTimeout(this.long_running_timer); // Don't unblock if blocked by somebody else if (self.blocked_ui) { @@ -242,10 +244,8 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database this.$option_id = $('#' + option_id); }, start: function() { + this._super(); this.$element.html(QWeb.render("Database", this)); - this.$element.closest(".openerp") - .removeClass("login-mode") - .addClass("database_block"); var self = this; var fetch_db = this.rpc("/web/database/get_list", {}, function(result) { @@ -266,23 +266,30 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database this.$element.find('#db-restore').click(this.do_restore); this.$element.find('#db-change-password').click(this.do_change_password); this.$element.find('#back-to-login').click(function() { - self.stop(); + self.hide(); }); }, stop: function () { + this.hide(); this.$option_id.empty(); this.$element .find('#db-create, #db-drop, #db-backup, #db-restore, #db-change-password, #back-to-login') .unbind('click') .end() - .closest(".openerp") - .addClass("login-mode") - .removeClass("database_block") - .end() .empty(); this._super(); }, + show: function () { + this.$element.closest(".openerp") + .removeClass("login-mode") + .addClass("database_block"); + }, + hide: function () { + this.$element.closest(".openerp") + .addClass("login-mode") + .removeClass("database_block") + }, /** * Converts a .serializeArray() result into a dict. Does not bother folding * multiple identical keys into an array, last key wins. @@ -368,6 +375,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database } self.db_list.push(self.to_object(fields)['db_name']); self.db_list.sort(); + self.widget_parent.set_db_list(self.db_list); var form_obj = self.to_object(fields); self.wait_for_newdb(result, { password: form_obj['super_admin_pwd'], @@ -397,6 +405,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database } $db_list.find(':selected').remove(); self.db_list.splice(_.indexOf(self.db_list, db, true), 1); + self.widget_parent.set_db_list(self.db_list); self.do_notify("Dropping database", "The database '" + db + "' has been dropped"); }); } @@ -529,16 +538,16 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{ var self = this; this.database = new openerp.web.Database( this, "oe_database", "oe_db_options"); + this.database.start(); this.$element.find('#oe-db-config').click(function() { - self.database.start(); + self.database.show(); }); this.$element.find("form").submit(this.on_submit); this.rpc("/web/database/get_list", {}, function(result) { - var tpl = openerp.web.qweb.render('Login_dblist', {db_list: result.db_list, selected_db: self.selected_db}); - self.$element.find("input[name=db]").replaceWith(tpl) + self.set_db_list(result.db_list); }, function(error, event) { if (error.data.fault_code === 'AccessDenied') { @@ -547,6 +556,15 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{ }); }, + stop: function () { + this.database.stop(); + this._super(); + }, + set_db_list: function (list) { + this.$element.find("[name=db]").replaceWith( + openerp.web.qweb.render('Login_dblist', { + db_list: list, selected_db: this.selected_db})) + }, on_login_invalid: function() { this.$element.closest(".openerp").addClass("login-mode"); }, @@ -966,7 +984,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie this.$element.html(QWeb.render("Interface", params)); this.notification = new openerp.web.Notification(this); - this.loading = new openerp.web.Loading(this,"oe_loading"); + this.loading = new openerp.web.Loading(this); this.crashmanager = new openerp.web.CrashManager(); this.header = new openerp.web.Header(this); @@ -990,6 +1008,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie 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')); diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index 369e1191665..a9731ef5b16 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -125,7 +125,11 @@ openerp.web.callback = function(obj, method) { callback.callback_chain.splice(i, 1); i -= 1; } - r = c.callback.apply(c.self, c.args.concat(args)); + var result = c.callback.apply(c.self, c.args.concat(args)); + if (c.callback === method) { + // return the result of the original method + r = result; + } // TODO special value to stop the chain // openerp.web.callback_stop } @@ -354,6 +358,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. this.debug = (window.location.search.indexOf('?debug') !== -1); this.session_id = false; this.uid = false; + this.username = false; this.user_context= {}; this.db = false; this.module_list = []; @@ -484,10 +489,13 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. var self = this; var params = { db: db, login: login, password: password }; return this.rpc("/web/session/login", params, function(result) { - self.session_id = result.session_id; - self.uid = result.uid; - self.user_context = result.context; - self.db = result.db; + _.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; @@ -501,9 +509,12 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. var self = this; this.session_id = this.get_cookie('session_id'); return this.rpc("/web/session/get_session_info", {}).then(function(result) { - self.uid = result.uid; - self.user_context = result.context; - self.db = result.db; + _.extend(self, { + uid: result.uid, + user_context: result.context, + db: result.db, + username: result.login + }); if (self.uid) self.on_session_valid(); else @@ -716,7 +727,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. if (parseInt(cookie_val, 10) !== token) { continue; } // clear cookie - document.cookie = _.sprintf("%s=;expires=%s;path=/", + document.cookie = _.str.sprintf("%s=;expires=%s;path=/", cookie_name, new Date().toGMTString()); if (options.success) { options.success(); } complete(); @@ -1055,7 +1066,7 @@ openerp.web.qweb.format_text_node = function(s) { if (translation && translation.value === 'off') { return s; } - var ts = _.trim(s); + var ts = _.str.trim(s); if (ts.length === 0) { return s; } diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index f4509c82a81..69d8fd9ddfd 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -119,17 +119,18 @@ openerp.web.ContainerDataGroup = openerp.web.DataGroup.extend( /** @lends opener aggregates[key] = value || 0; }); + var group_size = fixed_group[field_name + '_count'] || fixed_group.__count || 0; + var leaf_group = fixed_group.__context.group_by.length === 0; return { __context: fixed_group.__context, __domain: fixed_group.__domain, grouped_on: field_name, // if terminal group (or no group) and group_by_no_leaf => use group.__count - length: fixed_group[field_name + '_count'] || fixed_group.__count, + length: group_size, value: fixed_group[field_name], - - openable: !(this.context['group_by_no_leaf'] - && fixed_group.__context.group_by.length === 0), + // A group is openable if it's not a leaf in group_by_no_leaf mode + openable: !(leaf_group && this.context['group_by_no_leaf']), aggregates: aggregates }; @@ -315,7 +316,7 @@ openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet def.reject(); } else { fields = fields || false; - return this.read_ids([this.ids[this.index]], fields).then(function(records) { + this.read_ids([this.ids[this.index]], fields).then(function(records) { def.resolve(records[0]); }, function() { def.reject.apply(def, arguments); diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index c4af2d0cf6b..3151b34636b 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -76,7 +76,13 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { if (typeof value === 'number' && isNaN(value)) { value = false; } + //noinspection FallthroughInSwitchStatementJS switch (value) { + case '': + if (descriptor.type === 'char') { + return ''; + } + console.warn('Field', descriptor, 'had an empty string as value, treating as false...'); case false: case Infinity: case -Infinity: @@ -86,18 +92,18 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { switch (descriptor.widget || descriptor.type) { case 'integer': return openerp.web.insert_thousand_seps( - _.sprintf('%d', value)); + _.str.sprintf('%d', value)); case 'float': var precision = descriptor.digits ? descriptor.digits[1] : 2; - var formatted = _.sprintf('%.' + precision + 'f', value).split('.'); + var formatted = _.str.sprintf('%.' + precision + 'f', value).split('.'); formatted[0] = openerp.web.insert_thousand_seps(formatted[0]); return formatted.join(l10n.decimal_point); case 'float_time': - return _.sprintf("%02d:%02d", + return _.str.sprintf("%02d:%02d", Math.floor(value), Math.round((value % 1) * 60)); case 'progressbar': - return _.sprintf( + return _.str.sprintf( '<progress value="%.2f" max="100.0">%.2f%%</progress>', value, value); case 'many2one': diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 4fb5f02c690..f95801975b5 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -41,7 +41,11 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search if (this.headless) { this.ready.resolve(); } else { - this.rpc("/web/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded); + this.rpc("/web/searchview/load", { + model: this.model, + view_id: this.view_id, + context: this.dataset.get_context() + }, this.on_loaded); } return this.ready.promise(); }, @@ -137,7 +141,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search on_loaded: function(data) { if (data.fields_view.type !== 'search' || data.fields_view.arch.tag !== 'search') { - throw new Error(_.sprintf( + throw new Error(_.str.sprintf( "Got non-search view after asking for a search view: type %s, arch root %s", data.fields_view.type, data.fields_view.arch.tag)); } @@ -425,7 +429,7 @@ openerp.web.search.Invalid = openerp.web.Class.extend( /** @lends openerp.web.se this.message = message; }, toString: function () { - return _.sprintf( + return _.str.sprintf( _t("Incorrect value for field %(fieldname)s: [%(value)s] is %(message)s"), {fieldname: this.field, value: this.value, message: this.message} ); diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js index 033c2a31850..f907612bc1c 100644 --- a/addons/web/static/src/js/view_editor.js +++ b/addons/web/static/src/js/view_editor.js @@ -18,7 +18,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ init_view_editor: function() { var self = this; var action = { - name: _.sprintf("Manage Views (%s)", this.model), + name: _.str.sprintf("Manage Views (%s)", this.model), context: this.session.user_context, domain: [["model", "=", this.model]], res_model: 'ir.ui.view', @@ -78,7 +78,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ var self = this; this.create_view_dialog = new openerp.web.Dialog(this, { modal: true, - title: _.sprintf("Create a view (%s)", self.model), + title: _.str.sprintf("Create a view (%s)", self.model), width: 500, height: 400, buttons: { @@ -86,16 +86,16 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ var view_values = {}; var warn = false; _.each(self.create_view_widget, function(widget) { - if (widget.invalid) { + if (widget.is_invalid) { warn = true; return false; }; - if (widget.dirty && !widget.invalid) { + if (widget.dirty && !widget.is_invalid) { view_values[widget.name] = widget.get_value(); } }); if (warn) { - self.on_valid_create_view(); + self.on_valid_create_view(self.create_view_widget); } else { $.when(self.do_save_view(view_values)).then(function() { self.create_view_dialog.close(); @@ -112,15 +112,11 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ 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)}, {'name': 'view_type', 'string': 'View Type', 'type': 'selection', 'required': true, 'value': 'Form', 'selection': [['',''],['tree', 'Tree'],['form', 'Form'],['graph', 'Graph'],['calendar', 'Calender']]}, - {'name': 'proirity', 'string': 'Priority', 'type': 'char', 'required': true, 'value':'16'}]; + {'name': 'proirity', 'string': 'Priority', 'type': 'float', 'required': true, 'value':'16'}]; this.create_view_dialog.$element.append('<table id="create_view" style="width:400px" class="oe_forms"></table>'); this.create_view_widget = []; _.each(view_widget, function(widget) { - var type_widget = new (self.property.get_any([widget.type])) (self.create_view_dialog, widget.name); - if (widget.selection) { - type_widget.selection = widget.selection; - } - type_widget.required = widget.required; + var type_widget = new (self.property.get_any([widget.type])) (self.create_view_dialog, widget); self.create_view_dialog.$element.find('table[id=create_view]').append('<tr><td width="100px" align="right">' + widget.string + ':</td>' + type_widget.render()+'</tr>'); var value = null; if (widget.value) { @@ -147,7 +143,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ if (field_name) { model_dataset.read_slice(['name','field_id'], {"domain": [['model','=',self.model]]}, function(records) { if (records) {view_string = records[0].name;} - var arch = _.sprintf("<?xml version='1.0'?>\n<%s string='%s'>\n\t<field name='%s'/>\n</%s>", values.view_type, view_string, field_name, values.view_type); + var arch = _.str.sprintf("<?xml version='1.0'?>\n<%s string='%s'>\n\t<field name='%s'/>\n</%s>", values.view_type, view_string, field_name, values.view_type); var vals = {'model': self.model, 'name': values.view_name, 'priority': values.priority, 'type': values.view_type, 'arch': arch}; self.dataset.create(vals, function(suc) { def.resolve(); @@ -157,25 +153,29 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }); return def.promise(); }, - on_valid_create_view: function() { + on_valid_create_view: function(widgets) { var msg = "<ul>"; - _.each(self.create_view_widget, function(widget) { - if (widget.invalid) { + _.each(widgets, function(widget) { + if (widget.is_invalid) { msg += "<li>" + widget.name + "</li>"; } }); msg += "</ul>"; - self.do_warn("The following fields are invalid :", msg); + this.do_warn("The following fields are invalid :", msg); }, add_node_name : function(node) { if(node.tagName.toLowerCase() == "button" || node.tagName.toLowerCase() == "field"){ return (node.getAttribute('name'))? - _.sprintf( "<%s name='%s'>",node.tagName.toLowerCase(), node.getAttribute('name')): - _.sprintf( "<%s>",node.tagName.toLowerCase()); + _.str.sprintf( "<%s name='%s'>",node.tagName.toLowerCase(), node.getAttribute('name')): + _.str.sprintf( "<%s>",node.tagName.toLowerCase()); + }else if(node.tagName.toLowerCase() == "group"){ + return (node.getAttribute('string'))? + _.str.sprintf( "<%s>",node.getAttribute('string')): + _.str.sprintf( "<%s>",node.tagName.toLowerCase()); }else{ return (node.getAttribute('string'))? - _.sprintf( "<%s string='%s'>",node.tagName.toLowerCase(), node.getAttribute('string')): - _.sprintf( "<%s>",node.tagName.toLowerCase()); + _.str.sprintf( "<%s string='%s'>",node.tagName.toLowerCase(), node.getAttribute('string')): + _.str.sprintf( "<%s>",node.tagName.toLowerCase()); } }, do_delete_view: function() { @@ -237,7 +237,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ 'level': 0, 'id': this.xml_element_id +=1, 'att_list': [], - 'name': _.sprintf("<view view_id = %s>", view_id), + 'name': _.str.sprintf("<view view_id = %s>", view_id), 'child_id': [] }; var xml_arch = QWeb.load_xml(arch); @@ -249,7 +249,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ this.dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type'], function(arch) { if (arch.length) { var arch_object = self.parse_xml(arch[0].arch, self.main_view_id); - self.main_view_type = arch[0].type + self.main_view_type = arch[0].type == 'tree'? 'list': arch[0].type; view_arch_list.push({"view_id": self.main_view_id, "arch": arch[0].arch}); self.dataset.read_slice([], {domain: [['inherit_id','=', parseInt(self.main_view_id)]]}, function(result) { _.each(result, function(res) { @@ -295,7 +295,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }); }else{ var temp = _.reject(xpath_arch_object[0].child_id[0].att_list, function(list) { - return _.include(list, "position") + return list instanceof Array? _.include(list, "position"): false }); expr_to_list = [_.flatten(temp)]; } @@ -382,12 +382,12 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ this.one_object = one_object; this.edit_xml_dialog = new openerp.web.Dialog(this, { modal: true, - title: _.sprintf("View Editor %d - %s", self.main_view_id, self.model), + title: _.str.sprintf("View Editor %d - %s", self.main_view_id, self.model), width: 750, height: 500, buttons: { "Inherited View": function() { - //todo + //TODO }, "Preview": function() { var action = { @@ -439,7 +439,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ var view_id,view_xml_id; var view_find = side; - //for view id found + //for view id finding var min_level = this.one_object.clicked_tr_id; if(($(side).find('a').text()).search("view_id") != -1){ view_id = parseInt(($(view_find).find('a').text()).replace(/[^0-9]+/g, '')); @@ -494,7 +494,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ _.each([tr,parent_tr],function(element){ property_to_check.push( _.detect(_.keys(_CHILDREN),function(res){ - return _.includes(element, res); + return _.str.include(element, res); })); }); self.on_add_node(property_to_check, fields); @@ -502,12 +502,17 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }, do_node_edit: function(side){ var self = this; - var tr = $(side).find('a').text(); + var result = self.get_object_by_id(this.one_object.clicked_tr_id,this.one_object['main_object'], []); + if (result.length && result[0] && result[0].att_list) { + var properties = _PROPERTIES[result[0].att_list[0]]; + self.on_edit_node(properties); + } +/* var tr = $(side).find('a').text(); var tag = _.detect(_.keys(_PROPERTIES),function(res){ return _.includes(tr, res); }); var properties = _PROPERTIES[tag]; - self.on_edit_node(properties); + self.on_edit_node(properties);*/ }, do_node_down: function(cur_tr, img){ var self = this; @@ -663,18 +668,15 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ parent = $(arch1).parents(); } else if (move_direct == "update_node") { - _.each(update_values, function(val){ - if(val[0] == "required"){ - $(arch1).attr("required", "true"); - }else{ - $(arch1).attr(val[0],val[1]); - } + if (val[1]) $(arch1)[0].setAttribute(val[0], val[1]); + else $(arch1)[0].removeAttribute(val[0]); }); var new_obj = self.create_View_Node(arch1); new_obj.id = obj.id,new_obj.child_id = obj.child_id; - self.edit_xml_dialog.$element.find("tr[id='viewedit-"+self.one_object.clicked_tr_id+"']") - .find('a').text(new_obj.name); + self.edit_xml_dialog.$element. + find("tr[id='viewedit-"+this.one_object.clicked_tr_id+"']"). + find('a').text(new_obj.name); child_list.splice(index, 1, new_obj); parent = $(arch1).parents(); @@ -802,14 +804,23 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ height: 400, buttons: { "Update": function(){ + var warn = false; var update_values = []; _.each(self.edit_widget, function(widget) { - if (widget.dirty && !widget.invalid) { + if (widget.is_invalid) { + warn = true; + return false; + }; + if (widget.dirty && !widget.is_invalid) { update_values.push([widget.name, widget.get_value()]); } }); - self.do_save_update_arch("update_node", update_values); - self.edit_node_dialog.close(); + if (warn) { + self.on_valid_create_view(self.edit_widget); + } else { + self.do_save_update_arch("update_node", update_values); + self.edit_node_dialog.close(); + } }, "Cancel": function(){ self.edit_node_dialog.close(); @@ -817,24 +828,63 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ } }); this.edit_node_dialog.start().open(); - var widget = _.keys(self.property.map); + var _PROPERTIES_ATTRIBUTES = { + 'name' : {'name':'name', 'string': 'Name', 'type': 'char'}, + 'string' : {'name':'string', 'string': 'String', 'type': 'char'}, + 'required' : {'name':'required', 'string': 'Required', 'type': 'boolean'}, + 'readonly' : {'name':'readonly', 'string': 'Readonly', 'type': 'boolean'}, + 'domain' : {'name':'domain', 'string': 'Domain', 'type': 'char'}, + 'context' : {'name':'context', 'string': 'Context', 'type': 'char'}, + 'limit' : {'name':'limit', 'string': 'Limit', 'type': 'float'}, + 'min_rows' : {'name':'min_rows', 'string': 'Minimum rows', 'type': 'float'}, + 'date_start' : {'name':'date_start', 'string': 'Start date', 'type': 'char'}, + 'date_delay' : {'name':'date_delay', 'string': 'Delay date', 'type': 'char'}, + 'day_length' : {'name':'day_length', 'string': 'Day length', 'type': 'char'}, + 'mode' : {'name':'mode', 'string': 'Mode', 'type': 'char'}, + 'align' : {'name':'align', 'string': 'Alignment ', 'type': 'selection', 'selection': [['', ''], ['0.0', 'Left'], ['0.5', 'Center'], ['1.0', 'Right']]}, + 'icon' : {'name':'icon', 'string': 'Icon', 'type': 'selection', 'selection': _ICONS}, + 'type' : {'name':'type', 'string': 'Type', 'type': 'selection', 'selection': [['', ''], ['action', 'Action'], ['object', 'Object'], ['workflow', 'Workflow'], ['server_action', 'Server Action']]}, + 'special' : {'name':'special', 'string': 'Special', 'type': 'selection', 'selection': [['',''],['save', 'Save Button'], ['cancel', 'Cancel Button'], ['open', 'Open Button']]}, + 'target' : {'name':'target', 'string': 'Target', 'type': 'selection', 'selection': [['', ''], ['new', 'New Window']]}, + 'confirm' : {'name':'confirm', 'string': 'Confirm', 'type': 'char'}, + 'style' : {'name':'style', 'string': 'Style', 'type': 'selection', 'selection':[["",""],["1", "1"],["1-1", "1-1"],["1-2", "1-2"],["2-1", "2-1"],["1-1-1", "1-1-1"]]}, + 'filename' : {'name':'filename', 'string': 'File Name', 'type': 'char'}, + 'width' : {'name':'width', 'string': 'Width', 'type': 'float'}, + 'height' : {'name':'height', 'string': 'Height', 'type': 'float'}, + 'attrs' : {'name':'attrs', 'string': 'Attrs', 'type': 'char'}, + 'col' : {'name':'col', 'string': 'col', 'type': 'float'}, + 'link' : {'name':'link', 'string': 'Link', 'type': 'char'}, + 'position' : {'name':'position', 'string': 'Position', 'type': 'selection', 'selection': [['',''],['after', 'After'],['before', 'Before'],['inside', 'Inside'],['replace', 'Replace']]}, + 'states' : {'name':'states', 'string': 'states', 'type': 'char'}, + 'eval' : {'name':'eval', 'string': 'Eval', 'type': 'char'}, + 'ref' : {'name':'ref', 'string': 'Ref', 'type': 'char'}, + 'on_change' : {'name':'on_change', 'string': 'On change', 'type': 'char'}, + 'nolabel' : {'name':'nolabel', 'string': 'No label', 'type': 'boolean'}, + 'completion' : {'name':'completion', 'string': 'Completion', 'type': 'boolean'}, + 'colspan' : {'name':'colspan', 'string': 'Colspan', 'type': 'float'}, + 'widget' : {'name':'widget', 'string': 'widget', 'type': 'selection'}, + 'colors' : {'name':'colors', 'string': 'Colors', 'type': 'char'}, + 'editable' : {'name':'editable', 'string': 'Editable', 'type': 'selection', 'selection': [["",""],["top","Top"],["bottom", "Bottom"]]}, + 'groups' : {'name':'groups', 'string': 'Groups', 'type': 'seleciton_multi'}, + }; var arch_val = self.get_object_by_id(this.one_object.clicked_tr_id,this.one_object['main_object'], []); this.edit_node_dialog.$element.append('<table id="rec_table" style="width:400px" class="oe_forms"></table>'); this.edit_widget = []; - _.each(properties, function(property) { - type_widget = false; - self.ready = $.when(self.on_groups(property)).then(function () { - if (_.include(widget, property)){ - type_widget = new (self.property.get_any([property])) (self.edit_node_dialog, property); - } else { - type_widget = new openerp.web.ViewEditor.FieldChar (self.edit_node_dialog, property); - } + self.ready = $.when(self.on_groups(properties)).then(function () { + _PROPERTIES_ATTRIBUTES['groups']['selection'] = self.groups; + var values = _.keys( openerp.web.form.widgets.map); + values.push(''); + values.sort(); + _PROPERTIES_ATTRIBUTES['widget']['selection'] = values; + var widgets = _.filter(_PROPERTIES_ATTRIBUTES, function(property){ return _.include(properties, property.name)}) + _.each(widgets, function(widget) { + var type_widget = new (self.property.get_any([widget.type])) (self.edit_node_dialog, widget); var value = _.detect(arch_val[0]['att_list'],function(res) { - return _.include(res, property); + if (res instanceof Array) return _.include(res, widget.name); + else return false; }); value = value instanceof Array ? value[1] : value; - if (property == 'groups') type_widget.selection = self.groups; - self.edit_node_dialog.$element.find('table[id=rec_table]').append('<tr><td align="right">' + property + ':</td>' + type_widget.render() + '</tr>'); + self.edit_node_dialog.$element.find('table[id=rec_table]').append('<tr><td align="right">' + widget.string + ':</td>' + type_widget.render() + '</tr>'); type_widget.start(); type_widget.set_value(value); self.edit_widget.push(type_widget); @@ -842,12 +892,12 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ }); }, //for getting groups - on_groups: function(property){ + on_groups: function(properties){ var self = this, def = $.Deferred(); - if (property != 'groups') { + if (!_.include(properties, 'groups')) { self.groups = false; - return false; + def.resolve(); } var group_ids = [], group_names = {}, @@ -862,7 +912,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ group_names[key]=res.name; group_ids.push(res.id); }); - model_data + model_data .read_slice([],{domain:[['res_id', 'in', group_ids],['model','=','res.groups']]}) .done(function(model_grp) { _.each(model_grp,function(res_group){ @@ -879,9 +929,9 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ var positions = ['After','Before','Inside']; var render_list = []; var render_list =[{'name': 'node_type','selection': _.keys(_CHILDREN).sort(), - 'value': 'field', 'string': 'Node Type'}, - {'name': 'position','selection': positions, 'value': false, 'string': 'Position'}, - {'name': 'field_value','selection': fields, 'value': false, 'string': ''}]; + 'value': 'field', 'string': 'Node Type','type': 'selection'}, + {'name': 'position','selection': positions, 'value': false, 'string': 'Position','type': 'selection'}, + {'name': 'field_value','selection': fields, 'value': false, 'string': '','type': 'selection'}]; this.add_widget = []; this.add_node_dialog = new openerp.web.Dialog(this,{ modal: true, @@ -903,8 +953,8 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ } if(check_add_node){ var tag = (values.node_type == "field")? - _.sprintf("<%s name='%s'> </%s>",values.node_type,values.field_value,values.node_type): - _.sprintf("<%s> </%s>",values.node_type,values.node_type); + _.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");} }, @@ -917,8 +967,7 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ append('<table id="rec_table" style="width:400px" class="oe_forms"></table>'); var table_selector = self.add_node_dialog.$element.find('table[id=rec_table]'); _.each(render_list,function(node){ - type_widget = new openerp.web.ViewEditor.FieldSelect (self.add_node_dialog, node.name); - type_widget.selection = node.selection; + type_widget = new (self.property.get_any([node.type])) (self.add_node_dialog, node); table_selector.append('<tr><td align="right">' + node.string + ':</td>' + type_widget.render() + '</tr>'); type_widget.start(); type_widget.set_value(node.value); @@ -963,33 +1012,39 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({ } }); openerp.web.ViewEditor.Field = openerp.web.Class.extend({ - init: function(view, name) { + init: function(view, widget) { this.$element = view.$element; this.dirty = false; - this.name = name; - this.required = false; - this.invalid = false; + this.name = widget.name; + this.selection = widget.selection || []; + this.required = widget.required || false; + this.string = widget.string || ""; + this.type = widget.type; + this.is_invalid = false; }, start: function () { this.update_dom(); }, update_dom: function() { - this.$element.find("td[id="+ this.name+"]").toggleClass('invalid', this.invalid); + this.$element.find("td[id="+ this.name+"]").toggleClass('invalid', this.is_invalid); this.$element.find("td[id="+ this.name+"]").toggleClass('required', this.required); }, on_ui_change: function() { - var value = this.get_value(); - value = value instanceof Array ? value[1] : value; - if (this.required && !value) { - this.invalid = true; - } else { - this.invalid = false; - } + this.validate(); this.dirty = true; this.update_dom(); }, + validate: function() { + this.is_invalid = false; + try { + var value = openerp.web.parse_value(this.get_value(), this, ''); + this.is_invalid = this.required && value === ''; + } catch(e) { + this.is_invalid = true; + } + }, render: function() { - return _.sprintf("<td id = %s>%s</td>", this.name, QWeb.render(this.template, {widget: this})) + return _.str.sprintf("<td id = %s>%s</td>", this.name, QWeb.render(this.template, {widget: this})) }, }); openerp.web.ViewEditor.FieldBoolean = openerp.web.ViewEditor.Field.extend({ @@ -1000,7 +1055,6 @@ openerp.web.ViewEditor.FieldBoolean = openerp.web.ViewEditor.Field.extend({ this.$element.find("input[id="+ self.name+"]").change(function() { self.on_ui_change(); }); - }, set_value: function(value) { if (value) { @@ -1008,7 +1062,8 @@ openerp.web.ViewEditor.FieldBoolean = openerp.web.ViewEditor.Field.extend({ } }, get_value: function() { - return this.$element.find("input[id=" + this.name + "]").is(':checked') || null; + var value = this.$element.find("input[id=" + this.name + "]").is(':checked') + return value? "1" : null; } }); openerp.web.ViewEditor.FieldChar = openerp.web.ViewEditor.Field.extend({ @@ -1029,10 +1084,6 @@ openerp.web.ViewEditor.FieldChar = openerp.web.ViewEditor.Field.extend({ }); openerp.web.ViewEditor.FieldSelect = openerp.web.ViewEditor.Field.extend({ template : "vieweditor_selection", - init: function(view, name) { - this._super(view, name); - this.selection = false; - }, start: function () { var self = this; this._super(); @@ -1058,53 +1109,7 @@ openerp.web.ViewEditor.FieldSelect = openerp.web.ViewEditor.Field.extend({ return this.$element.find("select[id=" + this.name + "]").val(); } }); -openerp.web.ViewEditor.WidgetProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, name) { - this._super(view, name); - this.registry = openerp.web.form.widgets; - var values = _.keys(this.registry.map); - values.push(''); - values.sort(); - this.selection = values; - }, -}); -openerp.web.ViewEditor.IconProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, name) { - this._super(view, name); - this.selection = _ICONS; - }, -}); -openerp.web.ViewEditor.ButtonTargetProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, name) { - this._super(view, name); - this.selection = [['', ''], ['new', 'New Window']]; - }, -}); -openerp.web.ViewEditor.ButtonTypeProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, name) { - this._super(view, name); - this.selection = [['', ''], ['action', 'Action'], ['object', 'Object'], ['workflow', 'Workflow'], ['server_action', 'Server Action']]; - }, -}); -openerp.web.ViewEditor.AlignProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, name) { - this._super(view, name); - this.selection = [['', ''], ['0.0', 'Left'], ['0.5', 'Center'], ['1.0', 'Right']]; - }, -}); -openerp.web.ViewEditor.ButtonSpecialProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, name) { - this._super(view, name); - this.selection = [['',''],['save', 'Save Button'], ['cancel', 'Cancel Button'], ['open', 'Open Button']]; - }, -}); -openerp.web.ViewEditor.PositionProperty = openerp.web.ViewEditor.FieldSelect.extend({ - init: function(view, name) { - this._super(view, name); - this.selection = [['',''],['after', 'After'],['before', 'Before'],['inside', 'Inside'],['replace', 'Replace']]; - }, -}); -openerp.web.ViewEditor.GroupsProperty = openerp.web.ViewEditor.FieldSelect.extend({ +openerp.web.ViewEditor.FieldSelectMulti = openerp.web.ViewEditor.FieldSelect.extend({ start: function () { this._super(); this.$element.find("select[id=" + this.name + "]").css('height', '100px').attr("multiple",true); @@ -1120,9 +1125,13 @@ openerp.web.ViewEditor.GroupsProperty = openerp.web.ViewEditor.FieldSelect.exten }); } }); +openerp.web.ViewEditor.FieldFloat = openerp.web.ViewEditor.FieldChar.extend({ + +}); + var _PROPERTIES = { 'field' : ['name', 'string', 'required', 'readonly', 'domain', 'context', 'nolabel', 'completion', - 'colspan', 'widget', 'eval', 'ref', 'on_change', 'groups', 'attrs'], + 'colspan', 'widget', 'eval', 'ref', 'on_change', 'attrs', 'groups'], 'form' : ['string', 'col', 'link'], 'notebook' : ['colspan', 'position', 'groups'], 'page' : ['string', 'states', 'attrs', 'groups'], @@ -1130,7 +1139,7 @@ var _PROPERTIES = { 'image' : ['filename', 'width', 'height', 'groups'], 'separator' : ['string', 'colspan', 'groups'], 'label': ['string', 'align', 'colspan', 'groups'], - 'button': ['name', 'string', 'icon', 'type', 'states', 'readonly', 'special', 'target', 'confirm', 'context', 'attrs', 'groups','colspan'], + 'button': ['name', 'string', 'icon', 'type', 'states', 'readonly', 'special', 'target', 'confirm', 'context', 'attrs', 'colspan', 'groups'], 'newline' : [], 'board': ['style'], 'column' : [], @@ -1156,7 +1165,7 @@ var _CHILDREN = { 'newline': [], 'separator': [], }; -var icons = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD', +var _ICONS = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD', 'STOCK_CANCEL', 'STOCK_CDROM', 'STOCK_CLEAR', 'STOCK_CLOSE', 'STOCK_COLOR_PICKER', 'STOCK_CONNECT', 'STOCK_CONVERT', 'STOCK_COPY', 'STOCK_CUT', 'STOCK_DELETE', 'STOCK_DIALOG_AUTHENTICATION', 'STOCK_DIALOG_ERROR', 'STOCK_DIALOG_INFO', @@ -1184,19 +1193,10 @@ var icons = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD', 'terp-project', 'terp-report', 'terp-stock', 'terp-calendar', 'terp-graph' ]; openerp.web.ViewEditor.property_widget = new openerp.web.Registry({ - 'required' : 'openerp.web.ViewEditor.FieldBoolean', - 'readonly' : 'openerp.web.ViewEditor.FieldBoolean', - 'nolabel' : 'openerp.web.ViewEditor.FieldBoolean', - 'completion' : 'openerp.web.ViewEditor.FieldBoolean', - 'widget' : 'openerp.web.ViewEditor.WidgetProperty', - 'groups' : 'openerp.web.ViewEditor.GroupsProperty', - 'position' : 'openerp.web.ViewEditor.PositionProperty', - 'icon' : 'openerp.web.ViewEditor.IconProperty', - 'align' : 'openerp.web.ViewEditor.AlignProperty', - 'special' : 'openerp.web.ViewEditor.ButtonSpecialProperty', - 'type' : 'openerp.web.ViewEditor.ButtonTypeProperty', - 'target' : 'openerp.web.ViewEditor.ButtonTargetProperty', + 'boolean' : 'openerp.web.ViewEditor.FieldBoolean', + 'seleciton_multi' : 'openerp.web.ViewEditor.FieldSelectMulti', 'selection' : 'openerp.web.ViewEditor.FieldSelect', 'char' : 'openerp.web.ViewEditor.FieldChar', + 'float' : 'openerp.web.ViewEditor.FieldFloat', }); }; diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 84041ef8b60..d833b7471c6 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -35,7 +35,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.fields = {}; this.datarecord = {}; this.show_invalid = true; - this.dirty_for_user = false; this.default_focus_field = null; this.default_focus_button = null; this.registry = this.readonly ? openerp.web.form.readonly : openerp.web.form.widgets; @@ -141,7 +140,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# // null index means we should start a new record promise = this.on_button_new(); } else { - promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); + promise = this.dataset.read_index(_.keys(this.fields_view.fields)).pipe(this.on_record_loaded); } this.$element.show(); if (this.sidebar) { @@ -156,6 +155,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } }, on_record_loaded: function(record) { + var self = this, + deferred_stack = $.Deferred.queue(); if (!record) { throw("Form: No record received"); } @@ -172,35 +173,42 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } this.$form_header.find('.oe_form_on_readonly').toggle(this.readonly); this.$form_header.find('.oe_form_on_editable').toggle(!this.readonly); - this.dirty_for_user = false; this.datarecord = record; - for (var f in this.fields) { - var field = this.fields[f]; + + _(this.fields).each(function (field, f) { field.dirty = false; - field.set_value(this.datarecord[f] || false); - field.validate(); - } - if (!record.id) { - // New record: Second pass in order to trigger the onchanges - this.show_invalid = false; - for (var f in record) { - var field = this.fields[f]; - if (field) { - field.dirty = true; - this.do_onchange(field); + var result = field.set_value(self.datarecord[f] || false); + if (result && _.isFunction(result.promise)) { + deferred_stack.push(result); + } + $.when(result).then(function() { + field.validate(); + }); + }); + deferred_stack.push('force resolution if no fields'); + return deferred_stack.then(function() { + if (!record.id) { + // New record: Second pass in order to trigger the onchanges + self.show_invalid = false; + for (var f in record) { + var field = self.fields[f]; + if (field) { + field.dirty = true; + self.do_onchange(field); + } } } - } - this.on_form_changed(); - this.initial_mutating_lock.resolve(); - this.show_invalid = true; - this.do_update_pager(record.id == null); - if (this.sidebar) { - this.sidebar.attachments.do_update(); - } - if (this.default_focus_field && !this.embedded_view) { - this.default_focus_field.focus(); - } + self.on_form_changed(); + self.initial_mutating_lock.resolve(); + self.show_invalid = true; + self.do_update_pager(record.id == null); + if (self.sidebar) { + self.sidebar.attachments.do_update(); + } + if (self.default_focus_field && !self.embedded_view) { + self.default_focus_field.focus(); + } + }); }, on_form_changed: function() { for (var w in this.widgets) { @@ -240,7 +248,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# try { processed = processed || []; if (widget.node.attrs.on_change) { - var onchange = _.trim(widget.node.attrs.on_change); + var onchange = _.str.trim(widget.node.attrs.on_change); var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/); if (call) { var method = call[1], args = []; @@ -257,7 +265,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# }; var parent_fields = null; _.each(call[2].split(','), function(a, i) { - var field = _.trim(a); + var field = _.str.trim(a); if (field in argument_replacement) { args.push(argument_replacement[field](i)); return; @@ -267,11 +275,11 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# return; } else { var splitted = field.split('.'); - if (splitted.length > 1 && _.trim(splitted[0]) === "parent" && self.dataset.parent_view) { + if (splitted.length > 1 && _.str.trim(splitted[0]) === "parent" && self.dataset.parent_view) { if (parent_fields === null) { parent_fields = self.dataset.parent_view.get_fields_values(); } - var p_val = parent_fields[_.trim(splitted[1])]; + var p_val = parent_fields[_.str.trim(splitted[1])]; if (p_val !== undefined) { args.push(p_val == null ? false : p_val); return; @@ -317,7 +325,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# processed.push(field.name); if (field.get_value() != value) { field.set_value(value); - field.dirty = this.dirty_for_user = true; + field.dirty = true; if (_.indexOf(processed, field.name) < 0) { this.do_onchange(field, processed); } @@ -356,12 +364,13 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# var keys = _.keys(self.fields_view.fields); $.when(self.do_set_editable()).then(function() { if (keys.length) { - self.dataset.default_get(keys).then(self.on_record_loaded).then(function() { + self.dataset.default_get(keys).pipe(self.on_record_loaded).then(function() { def.resolve(); }); } else { - self.on_record_loaded({}); - def.resolve(); + self.on_record_loaded({}).then(function() { + def.resolve(); + }); } }); } @@ -402,7 +411,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# return def.promise(); }, can_be_discarded: function() { - return !this.dirty_for_user || confirm(_t("Warning, the record has been modified, your changes will be discarded.")); + return !this.is_dirty() || confirm(_t("Warning, the record has been modified, your changes will be discarded.")); }, /** * Triggers saving the form's record. Chooses between creating a new @@ -418,8 +427,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# try { if (!self.initial_mutating_lock.isResolved() && !self.initial_mutating_lock.isRejected()) return; - var form_dirty = false, - form_invalid = false, + var form_invalid = false, values = {}, first_invalid_field = null; for (var f in self.fields) { @@ -431,7 +439,6 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# first_invalid_field = f; } } else if (f.is_dirty()) { - form_dirty = true; values[f.name] = f.get_value(); } } @@ -480,8 +487,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# // should not happen in the server, but may happen for internal purpose return $.Deferred().reject(); } else { - this.reload(); - return $.when(r).then(success); + return $.when(this.reload()).pipe(function () { + return $.when(r).then(success); }, null); } }, /** @@ -528,7 +535,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# if (self.dataset.index == null || self.dataset.index < 0) { return $.when(self.on_button_new()); } else { - return self.dataset.read_index(_.keys(self.fields_view.fields), self.on_record_loaded); + return self.dataset.read_index(_.keys(self.fields_view.fields)).pipe(self.on_record_loaded); } }; this.reload_lock = this.reload_lock.pipe(act, act); @@ -553,6 +560,11 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# return self.dataset.parent_view.recursive_save(); }); }, + is_dirty: function() { + return _.any(this.fields, function (value) { + return value.is_dirty(); + }); + }, is_interactible_record: function() { var id = this.datarecord.id; if (!id) { @@ -638,7 +650,7 @@ openerp.web.form.SidebarAttachments = openerp.web.Widget.extend({ }, on_attachment_delete: function(e) { var self = this, $e = $(e.currentTarget); - var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text()); + var name = _.str.trim($e.parent().find('a.oe-sidebar-attachments-link').text()); if (confirm("Do you really want to delete the attachment " + name + " ?")) { this.rpc('/web/dataset/unlink', { model: 'ir.attachment', @@ -798,8 +810,13 @@ openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form. _build_view_fields_values: function() { var a_dataset = this.view.dataset; var fields_values = this.view.get_fields_values(); - var parent_values = a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {}; - fields_values.parent = parent_values; + var active_id = a_dataset.ids[a_dataset.index]; + _.extend(fields_values, { + active_id: active_id || false, + active_ids: active_id ? [active_id] : [], + active_model: a_dataset.model, + parent: a_dataset.parent_view ? a_dataset.parent_view.get_fields_values() : {} + }); return fields_values; }, _build_eval_context: function() { @@ -1231,7 +1248,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f } }, on_ui_change: function() { - this.dirty = this.view.dirty_for_user = true; + this.dirty = true; this.validate(); if (this.is_valid()) { this.set_value_from_ui(); @@ -1344,54 +1361,58 @@ openerp.web.DateTimeWidget = openerp.web.Widget.extend({ template: "web.datetimepicker", jqueryui_object: 'datetimepicker', type_of_date: "datetime", + init: function(parent) { + this._super(parent); + this.name = parent.name; + }, start: function() { var self = this; - this.$element.find('input').change(this.on_change); + this.$input = this.$element.find('input.oe_datepicker_master'); + this.$input_picker = this.$element.find('input.oe_datepicker_container'); + this.$input.change(this.on_change); this.picker({ onSelect: this.on_picker_select, changeMonth: true, changeYear: true, showWeek: true, - showButtonPanel: false + showButtonPanel: true }); this.$element.find('img.oe_datepicker_trigger').click(function() { if (!self.readonly) { self.picker('setDate', self.value ? openerp.web.auto_str_to_date(self.value) : new Date()); - self.$element.find('.oe_datepicker').toggle(); + self.$input_picker.show(); + self.picker('show'); + self.$input_picker.hide(); } }); - this.$element.find('.ui-datepicker-inline').removeClass('ui-widget-content ui-corner-all'); - this.$element.find('button.oe_datepicker_close').click(function() { - self.$element.find('.oe_datepicker').hide(); - }); this.set_readonly(false); this.value = false; }, picker: function() { - return $.fn[this.jqueryui_object].apply(this.$element.find('.oe_datepicker_container'), arguments); + return $.fn[this.jqueryui_object].apply(this.$input_picker, arguments); }, on_picker_select: function(text, instance) { var date = this.picker('getDate'); - this.$element.find('input').val(date ? this.format_client(date) : '').change(); + this.$input.val(date ? this.format_client(date) : '').change(); }, set_value: function(value) { this.value = value; - this.$element.find('input').val(value ? this.format_client(value) : ''); + this.$input.val(value ? this.format_client(value) : ''); }, get_value: function() { return this.value; }, set_value_from_ui: function() { - var value = this.$element.find('input').val() || false; + var value = this.$input.val() || false; this.value = this.parse_client(value); }, set_readonly: function(readonly) { this.readonly = readonly; - this.$element.find('input').attr('disabled', this.readonly); + this.$input.attr('disabled', this.readonly); this.$element.find('img.oe_datepicker_trigger').toggleClass('oe_input_icon_disabled', readonly); }, is_valid: function(required) { - var value = this.$element.find('input').val(); + var value = this.$input.val(); if (value === "") { return !required; } else { @@ -1404,7 +1425,7 @@ openerp.web.DateTimeWidget = openerp.web.Widget.extend({ } }, focus: function() { - this.$element.find('input').focus(); + this.$input.focus(); }, parse_client: function(v) { return openerp.web.parse_value(v, {"widget": this.type_of_date}); @@ -1421,11 +1442,7 @@ openerp.web.DateTimeWidget = openerp.web.Widget.extend({ openerp.web.DateWidget = openerp.web.DateTimeWidget.extend({ jqueryui_object: 'datepicker', - type_of_date: "date", - on_picker_select: function(text, instance) { - this._super(text, instance); - this.$element.find('.oe_datepicker').hide(); - } + type_of_date: "date" }); openerp.web.form.FieldDatetime = openerp.web.form.Field.extend({ @@ -1437,7 +1454,7 @@ openerp.web.form.FieldDatetime = openerp.web.form.Field.extend({ var self = this; this._super.apply(this, arguments); this.datewidget = this.build_widget(); - this.datewidget.on_change.add(this.on_ui_change); + this.datewidget.on_change.add_last(this.on_ui_change); this.datewidget.appendTo(this.$element); }, set_value: function(value) { @@ -1825,7 +1842,7 @@ openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({ if (search_val.length > 0 && !_.include(raw_result, search_val) && (!self.value || search_val !== self.value[1])) { - values.push({label: _.sprintf(_t('<em> Create "<strong>%s</strong>"</em>'), + values.push({label: _.str.sprintf(_t('<em> Create "<strong>%s</strong>"</em>'), $('<span />').text(search_val).html()), action: function() { self._quick_create(search_val); }}); @@ -2103,7 +2120,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ }, reload_current_view: function() { var self = this; - self.is_loaded = self.is_loaded.pipe(function() { + return self.is_loaded = self.is_loaded.pipe(function() { var view = self.viewmanager.views[self.viewmanager.active_view].controller; if(self.viewmanager.active_view === "list") { return view.reload_content(); @@ -2176,8 +2193,8 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ if (this.dataset.index === null && this.dataset.ids.length > 0) { this.dataset.index = 0; } - self.reload_current_view(); - this.is_setted.resolve(); + self.is_setted.resolve(); + return self.reload_current_view(); }, get_value: function() { var self = this; @@ -2955,7 +2972,7 @@ openerp.web.form.FieldStatus = openerp.web.form.Field.extend({ render_list: function() { var self = this; var shown = _.map(((this.node.attrs || {}).statusbar_visible || "").split(","), - function(x) { return _.trim(x); }); + function(x) { return _.str.trim(x); }); shown = _.select(shown, function(x) { return x.length > 0; }); if (shown.length == 0) { diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 77f04d4c864..728b090d679 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -295,7 +295,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# } else { last = first + limit; } - this.$element.find('span.oe-pager-state').empty().text(_.sprintf( + this.$element.find('span.oe-pager-state').empty().text(_.str.sprintf( "[%d to %d] of %d", first + 1, last, total)); this.$element @@ -647,7 +647,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# return; } - $footer_cells.filter(_.sprintf('[data-field=%s]', column.id)) + $footer_cells.filter(_.str.sprintf('[data-field=%s]', column.id)) .html(openerp.web.format_cell(aggregation, column, undefined, false)); }); }, @@ -1127,7 +1127,7 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L child.datagroup = group; var $row = child.$row = $('<tr>'); - if (group.openable) { + if (group.openable && group.length) { $row.click(function (e) { if (!$row.data('open')) { $row.data('open', true) @@ -1159,7 +1159,13 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L } catch (e) { $group_column.html(row_data[group_column.id].value); } - if (group.openable) { + if (!group.length) { + // Kinda-ugly hack: jquery-ui has no "empty" icon, so set + // wonky background position to ensure nothing is displayed + // there but the rest of the behavior is ui-icon's + $group_column.prepend( + '<span class="ui-icon" style="float: left; background-position: 150px 150px">'); + } else if (group.openable) { // Make openable if not terminal group & group_by_no_leaf $group_column .prepend('<span class="ui-icon ui-icon-triangle-1-e" style="float: left;">'); @@ -1186,7 +1192,7 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L format = "%.2f"; } $('<td>') - .text(_.sprintf(format, value)) + .text(_.str.sprintf(format, value)) .appendTo($row); } else { $row.append('<td>'); @@ -1245,7 +1251,7 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L var pages = Math.ceil(dataset.ids.length / limit); self.$row .find('.oe-pager-state') - .text(_.sprintf('%d/%d', page + 1, pages)) + .text(_.str.sprintf('%d/%d', page + 1, pages)) .end() .find('button[data-pager-action=previous]') .attr('disabled', page === 0) diff --git a/addons/web/static/src/js/view_tree.js b/addons/web/static/src/js/view_tree.js index 5143adb3838..34d47b92813 100644 --- a/addons/web/static/src/js/view_tree.js +++ b/addons/web/static/src/js/view_tree.js @@ -42,7 +42,8 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView# model: this.model, view_id: this.view_id, view_type: "tree", - toolbar: this.view_manager ? !!this.view_manager.sidebar : false + toolbar: this.view_manager ? !!this.view_manager.sidebar : false, + context: this.dataset.get_context() }, this.on_loaded); }, /** @@ -214,17 +215,23 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView# // Get details in listview activate: function(id) { var self = this; + var local_context = { + active_model: self.dataset.model, + active_id: id, + active_ids: [id]}; this.rpc('/web/treeview/action', { id: id, model: this.dataset.model, context: new openerp.web.CompoundContext( - this.dataset.get_context(), { - active_model: this.dataset.model, - active_id: id, - active_ids: [id]}) + this.dataset.get_context(), local_context) }, function (actions) { if (!actions.length) { return; } var action = actions[0][2]; + var c = new openerp.web.CompoundContext(local_context); + if (action.context) { + c.add(action.context); + } + action.context = c; self.do_action(action); }); }, diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index efa5ac5b2a8..eff94b95ad7 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -210,7 +210,7 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View sidebar_id : self.element_id + '_sidebar_' + view.view_type, action : self.action, action_views_ids : views_ids - }, self.flags, view.options || {}) + }, self.flags, self.flags[view.view_type] || {}, view.options || {}) }); views_ids[view.view_type] = view.view_id; }); @@ -534,7 +534,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner $logs_list = $logs.find('ul').empty(); $logs.toggleClass('oe-has-more', log_records.length > cutoff); _(log_records.reverse()).each(function (record) { - $(_.sprintf('<li><a href="#">%s</a></li>', record.name)) + $(_.str.sprintf('<li><a href="#">%s</a></li>', record.name)) .appendTo($logs_list) .delegate('a', 'click', function (e) { self.do_action({ @@ -628,7 +628,7 @@ session.web.Sidebar = session.web.Widget.extend({ }, add_section: function(name, code) { - if(!code) code = _.underscored(name); + if(!code) code = _.str.underscored(name); var $section = this.sections[code]; if(!$section) { @@ -656,7 +656,7 @@ session.web.Sidebar = session.web.Widget.extend({ // var self = this, - $section = this.add_section(_.titleize(section_code.replace('_', ' ')), section_code), + $section = this.add_section(_.str.titleize(section_code.replace('_', ' ')), section_code), section_id = $section.attr('id'); if (items) { |
