diff options
| author | niv-openerp <nicolas.vanhoren@openerp.com> | 2012-02-17 11:17:31 +0100 |
|---|---|---|
| committer | niv-openerp <nicolas.vanhoren@openerp.com> | 2012-02-17 11:17:31 +0100 |
| commit | 1e9380b8faf05aa5ccb7fdfaf7309c362b1963bb (patch) | |
| tree | e49a42e01b00a5e95522a93c720762d487b17fd8 /addons/web/static/src/js | |
| parent | affc2d4d04539d452ee207eef2c01238df72d1ef (diff) | |
| parent | 9f65e1565e785fd1c11fef65e7b49e78fba290ed (diff) | |
[merge]
bzr revid: nicolas.vanhoren@openerp.com-20120217101731-3g9hrhs65qb32pkv
Diffstat (limited to 'addons/web/static/src/js')
| -rw-r--r-- | addons/web/static/src/js/chrome.js | 52 | ||||
| -rw-r--r-- | addons/web/static/src/js/core.js | 67 | ||||
| -rw-r--r-- | addons/web/static/src/js/data.js | 29 | ||||
| -rw-r--r-- | addons/web/static/src/js/data_import.js | 13 | ||||
| -rw-r--r-- | addons/web/static/src/js/formats.js | 50 | ||||
| -rw-r--r-- | addons/web/static/src/js/search.js | 51 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_editor.js | 112 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_form.js | 146 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list.js | 8 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list_editable.js | 4 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_page.js | 17 | ||||
| -rw-r--r-- | addons/web/static/src/js/views.js | 71 |
12 files changed, 470 insertions, 150 deletions
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index 9fda4752a36..ba31ec81846 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -20,17 +20,27 @@ openerp.web.Notification = openerp.web.OldWidget.extend(/** @lends openerp.web. expires: 2500 }); }, - notify: function(title, text) { + notify: function(title, text, sticky) { + sticky = !!sticky; + var opts = {}; + if (sticky) { + opts.expires = false; + } this.$element.notify('create', { title: title, text: text - }); + }, opts); }, - warn: function(title, text) { + warn: function(title, text, sticky) { + sticky = !!sticky; + var opts = {}; + if (sticky) { + opts.expires = false; + } this.$element.notify('create', 'oe_notification_alert', { title: title, text: text - }); + }, opts); } }); @@ -606,6 +616,10 @@ openerp.web.Login = openerp.web.OldWidget.extend(/** @lends openerp.web.Login# } var $e = this.$element; var db = $e.find("form [name=db]").val(); + if (!db) { + this.do_warn("Login", "No database selected !"); + return false; + } var login = $e.find("form input[name=login]").val(); var password = $e.find("form input[name=password]").val(); @@ -945,7 +959,8 @@ openerp.web.Menu = openerp.web.OldWidget.extend(/** @lends openerp.web.Menu# */ do_menu_click: function($clicked_menu, manual) { var $sub_menu, $main_menu, active = $clicked_menu.is('.active'), - sub_menu_visible = false; + sub_menu_visible = false, + has_submenu_items = false; if (this.$secondary_menu.has($clicked_menu).length) { $sub_menu = $clicked_menu.parents('.oe_secondary_menu'); @@ -956,15 +971,18 @@ openerp.web.Menu = openerp.web.OldWidget.extend(/** @lends openerp.web.Menu# */ } sub_menu_visible = $sub_menu.is(':visible'); + has_submenu_items = !!$sub_menu.children().length; this.$secondary_menu.find('.oe_secondary_menu').hide(); $('.active', this.$element.add(this.$secondary_menu)).removeClass('active'); $main_menu.add($clicked_menu).add($sub_menu).addClass('active'); - if (!(this.folded && manual)) { - this.do_show_secondary($sub_menu, $main_menu); - } else { - this.do_show_secondary(); + if (has_submenu_items) { + if (!(this.folded && manual)) { + this.do_show_secondary($sub_menu, $main_menu); + } else { + this.do_show_secondary(); + } } if ($main_menu != $clicked_menu) { @@ -980,7 +998,7 @@ openerp.web.Menu = openerp.web.OldWidget.extend(/** @lends openerp.web.Menu# */ return true; } } else if (this.folded) { - if (active && sub_menu_visible) { + if ((active && sub_menu_visible) || !has_submenu_items) { $sub_menu.hide(); return true; } @@ -1147,12 +1165,14 @@ openerp.web.WebClient = openerp.web.OldWidget.extend(/** @lends openerp.web.WebC n.warn.apply(n, arguments); }, on_logout: function() { - this.session.session_logout(); - $(window).unbind('hashchange', this.on_hashchange); - this.do_push_state({}); - //would be cool to be able to do this, but I think it will make addons do strange things - //this.show_login(); - window.location.reload(); + var self = this; + this.session.session_logout().then(function () { + $(window).unbind('hashchange', self.on_hashchange); + self.do_push_state({}); + //would be cool to be able to do this, but I think it will make addons do strange things + //this.show_login(); + window.location.reload(); + }); }, bind_hashchange: function() { $(window).bind('hashchange', this.on_hashchange); diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index 8ab6c897fb0..086f7f3b56a 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -254,6 +254,7 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry * @param {Object} mapping a mapping of keys to object-paths */ init: function (mapping) { + this.parent = null; this.map = mapping || {}; }, /** @@ -269,6 +270,9 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry get_object: function (key, silent_error) { var path_string = this.map[key]; if (path_string === undefined) { + if (this.parent) { + return this.parent.get_object(key, silent_error); + } if (silent_error) { return void 'nooo'; } throw new openerp.web.KeyNotFound(key); } @@ -287,6 +291,21 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry return object_match; }, /** + * Checks if the registry contains an object mapping for this key. + * + * @param {String} key key to look for + */ + contains: function (key) { + if (key === undefined) { return false; } + if (key in this.map) { + return true + } + if (this.parent) { + return this.parent.contains(key); + } + return false; + }, + /** * Tries a number of keys, and returns the first object matching one of * the keys. * @@ -299,7 +318,7 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry get_any: function (keys) { for (var i=0; i<keys.length; ++i) { var key = keys[i]; - if (key === undefined || !(key in this.map)) { + if (!this.contains(key)) { continue; } @@ -324,11 +343,22 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry * Creates and returns a copy of the current mapping, with the provided * mapping argument added in (replacing existing keys if needed) * + * Parent and child remain linked, a new key in the parent (which is not + * overwritten by the child) will appear in the child. + * * @param {Object} [mapping={}] a mapping of keys to object-paths */ + extend: function (mapping) { + var child = new openerp.web.Registry(mapping); + child.parent = this; + return child; + }, + /** + * @deprecated use Registry#extend + */ clone: function (mapping) { - return new openerp.web.Registry( - _.extend({}, this.map, mapping || {})); + console.warn('Registry#clone is deprecated, use Registry#extend'); + return this.extend(mapping); } }); @@ -644,6 +674,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. }, session_logout: function() { this.set_cookie('session_id', ''); + return this.rpc("/web/session/destroy", {}); }, on_session_valid: function() { }, @@ -702,17 +733,21 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp. var params = { mods: all_modules, lang: lang}; var to_load = _.difference(result, self.module_list).join(','); self.module_list = all_modules; - return $.when( - self.rpc('/web/webclient/csslist', {mods: to_load}, self.do_load_css), - self.rpc('/web/webclient/qweblist', {mods: to_load}).pipe(self.do_load_qweb), - self.rpc('/web/webclient/translations', params).pipe(function(trans) { - openerp.web._t.database.set_bundle(trans); - var file_list = ["/web/static/lib/datejs/globalization/" + lang.replace("_", "-") + ".js"]; - return self.rpc('/web/webclient/jslist', {mods: to_load}).pipe(function(files) { - return self.do_load_js(file_list.concat(files)); - }); - }) - ).then(function() { + + var loaded = $.Deferred().resolve().promise(); + if (to_load.length) { + loaded = $.when( + self.rpc('/web/webclient/csslist', {mods: to_load}, self.do_load_css), + self.rpc('/web/webclient/qweblist', {mods: to_load}).pipe(self.do_load_qweb), + self.rpc('/web/webclient/translations', params).pipe(function(trans) { + openerp.web._t.database.set_bundle(trans); + var file_list = ["/web/static/lib/datejs/globalization/" + lang.replace("_", "-") + ".js"]; + return self.rpc('/web/webclient/jslist', {mods: to_load}).pipe(function(files) { + return self.do_load_js(file_list.concat(files)); + }); + })) + } + return loaded.then(function() { self.on_modules_loaded(); if (!no_session_valid_signal) { self.on_session_valid(); @@ -1184,9 +1219,7 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we add_module_translation: function(mod) { var self = this; _.each(mod.messages, function(message) { - if (self.db[message.id] === undefined) { - self.db[message.id] = message.string; - } + self.db[message.id] = message.string; }); }, build_translation_function: function() { diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 01962f829e6..8e200951eaa 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -469,13 +469,13 @@ openerp.web.DataSet = openerp.web.OldWidget.extend( /** @lends openerp.web.Data * @param {String} name name to perform a search for/on * @param {Array} [domain=[]] filters for the objects returned, OpenERP domain * @param {String} [operator='ilike'] matching operator to use with the provided name value - * @param {Number} [limit=100] maximum number of matches to return + * @param {Number} [limit=0] maximum number of matches to return * @param {Function} callback function to call with name_search result * @returns {$.Deferred} */ name_search: function (name, domain, operator, limit, callback) { return this.call_and_eval('name_search', - [name || '', domain || false, operator || 'ilike', this.get_context(), limit || 100], + [name || '', domain || false, operator || 'ilike', this.get_context(), limit || 0], 1, 3, callback); }, /** @@ -522,7 +522,13 @@ openerp.web.DataSet = openerp.web.OldWidget.extend( /** @lends openerp.web.Data this._sort.unshift((reverse ? '-' : '') + field); return undefined; - } + }, + size: function () { + return this.ids.length; + }, + alter_ids: function(n_ids) { + this.ids = n_ids; + }, }); openerp.web.DataSetStatic = openerp.web.DataSet.extend({ init: function(parent, model, context, ids) { @@ -568,6 +574,7 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D this._super(parent, model, context); this.domain = domain || []; this.offset = 0; + this._length; // subset records[offset:offset+limit] // is it necessary ? this.ids = []; @@ -599,6 +606,7 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D }).pipe(function (result) { self.ids = result.ids; self.offset = offset; + self._length = result.length; return result.records; }); }, @@ -619,6 +627,12 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D if (callback) callback(result); }, error_callback); + }, + size: function () { + if (this._length !== undefined) { + return this._length; + } + return this._super(); } }); openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({ @@ -640,7 +654,6 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({ defaults: this.last_default_get}; this.to_create.push(_.extend(_.clone(cached), {values: _.clone(cached.values)})); this.cache.push(cached); - this.on_change(); var prom = $.Deferred().then(callback); prom.resolve({result: cached.id}); return prom.promise(); @@ -751,7 +764,7 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({ self.cache.push({id: id, values: record}); } else { // I assume cache value is prioritary - _.defaults(cached.values, record); + cached.values = _.defaults(_.clone(cached.values), record); } }); return_records(); @@ -774,7 +787,11 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({ } } return this._super(method, args, callback, error_callback); - } + }, + alter_ids: function(n_ids) { + this._super(n_ids); + this.on_change(); + }, }); openerp.web.BufferedDataSet.virtual_id_regex = /^one2many_v_id_.*$/; diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 18870ca2157..83eea2cccbb 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -109,9 +109,20 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ _(fields).each(function (field, field_name) { // Ignore spec for id field // Don't import function fields (function and related) - if (field_name === 'id' || 'function' in field) { + if (field_name === 'id') { return; } + // Skip if there's no state which could disable @readonly, + // if a field is ever always readonly we can't import it + if (field.readonly) { + // no states at all + if (_.isEmpty(field.states)) { return; } + // no state altering @readonly + if (!_.any(field.states, function (modifiers) { + return _(modifiers).chain().pluck(0).contains('readonly').value(); + })) { 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 eb7d6c335ac..4fb576e4a90 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -61,6 +61,28 @@ openerp.web.insert_thousand_seps = function (num) { return (negative ? '-' : '') + openerp.web.intersperse( num, _t.database.parameters.grouping, _t.database.parameters.thousands_sep); }; + +/** + * removes literal (non-format) text from a date or time pattern, as datejs can + * not deal with literal text in format strings (whatever the format), whereas + * strftime allows for literal characters + * + * @param {String} value original format + */ +openerp.web.strip_raw_chars = function (value) { + var isletter = /[a-zA-Z]/, output = []; + for(var index=0; index < value.length; ++index) { + var character = value[index]; + if(isletter.test(character) && (index === 0 || value[index-1] !== '%')) { + continue; + } + output.push(character); + } + return output.join(''); +}; +var normalize_format = function (format) { + return Date.normalizeFormat(openerp.web.strip_raw_chars(format)); +}; /** * Formats a single atomic value based on a field descriptor * @@ -101,7 +123,12 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { formatted[0] = openerp.web.insert_thousand_seps(formatted[0]); return formatted.join(l10n.decimal_point); case 'float_time': - return _.str.sprintf("%02d:%02d", + var pattern = '%02d:%02d'; + if (value < 0) { + value = Math.abs(value); + pattern = '-' + pattern; + } + return _.str.sprintf(pattern, Math.floor(value), Math.round((value % 1) * 60)); case 'many2one': @@ -111,16 +138,16 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { if (typeof(value) == "string") value = openerp.web.auto_str_to_date(value); - return value.format(l10n.date_format - + ' ' + l10n.time_format); + return value.toString(normalize_format(l10n.date_format) + + ' ' + normalize_format(l10n.time_format)); case 'date': if (typeof(value) == "string") value = openerp.web.auto_str_to_date(value); - return value.format(l10n.date_format); + return value.toString(normalize_format(l10n.date_format)); case 'time': if (typeof(value) == "string") value = openerp.web.auto_str_to_date(value); - return value.format(l10n.time_format); + return value.toString(normalize_format(l10n.time_format)); case 'selection': // Each choice is [value, label] if(_.isArray(value)) { @@ -137,8 +164,8 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) { }; openerp.web.parse_value = function (value, descriptor, value_if_empty) { - var date_pattern = Date.normalizeFormat(_t.database.parameters.date_format), - time_pattern = Date.normalizeFormat(_t.database.parameters.time_format); + var date_pattern = normalize_format(_t.database.parameters.date_format), + time_pattern = normalize_format(_t.database.parameters.time_format); switch (value) { case false: case "": @@ -171,12 +198,17 @@ openerp.web.parse_value = function (value, descriptor, value_if_empty) { throw new Error(value + " is not a correct float"); return parsed; case 'float_time': + var factor = 1; + if (value[0] === '-') { + value = value.slice(1); + factor = -1; + } var float_time_pair = value.split(":"); if (float_time_pair.length != 2) - return openerp.web.parse_value(value, {type: "float"}); + return factor * openerp.web.parse_value(value, {type: "float"}); var hours = openerp.web.parse_value(float_time_pair[0], {type: "integer"}); var minutes = openerp.web.parse_value(float_time_pair[1], {type: "integer"}); - return hours + (minutes / 60); + return factor * (hours + (minutes / 60)); case 'progressbar': return openerp.web.parse_value(value, {type: "float"}); case 'datetime': diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 6cd05100de5..74ae65785f9 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -154,7 +154,6 @@ openerp.web.SearchView = openerp.web.OldWidget.extend(/** @lends openerp.web.Sea // for extended search view var ext = new openerp.web.search.ExtendedSearch(this, this.model); lines.push([ext]); - this.inputs.push(ext); this.extended_search = ext; var render = QWeb.render("SearchView", { @@ -187,7 +186,10 @@ openerp.web.SearchView = openerp.web.OldWidget.extend(/** @lends openerp.web.Sea }).then(function(result) { self.managed_filters = result; var filters = self.$element.find(".oe_search-view-filters-management"); - filters.html(QWeb.render("SearchView.managed-filters", {filters: result})); + filters.html(QWeb.render("SearchView.managed-filters", { + filters: result, + disabled_filter_message: _t('Filter disabled due to invalid syntax') + })); filters.change(self.on_filters_management); }); }, @@ -425,13 +427,9 @@ openerp.web.SearchView = openerp.web.OldWidget.extend(/** @lends openerp.web.Sea this.$element.find('table:last').hide(); $('.searchview_extended_groups_list').empty(); - _.each(this.inputs, function (input) { - if(input.datewidget && input.datewidget.value) { - input.datewidget.set_value(false); - } - }); - return $.async_when().pipe( - reload_view !== false ? this.on_clear : null); + return $.async_when.apply( + null, _(this.inputs).invoke('clear')).pipe( + reload_view !== false ? this.on_clear : null); }, /** * Triggered when the search view gets cleared @@ -618,7 +616,11 @@ openerp.web.search.Input = openerp.web.search.Widget.extend( /** @lends openerp. } } this.attrs = attrs; - } + }, + /** + * Specific clearing operations, if any + */ + clear: function () {} }); openerp.web.search.FilterGroup = openerp.web.search.Input.extend(/** @lends openerp.web.search.FilterGroup# */{ template: 'SearchView.filters', @@ -900,6 +902,22 @@ openerp.web.search.SelectionField = openerp.web.search.Field.extend(/** @lends o defaults[this.attrs.name] = false; } return this._super(defaults); + }, + clear: function () { + var self = this, d = $.Deferred(), selection = this.attrs.selection; + for(var index=0; index<selection.length; ++index) { + var item = selection[index]; + if (!item[1]) { + setTimeout(function () { + // won't override mutable, because we immediately bail out + //noinspection JSReferencingMutableVariableFromClosure + self.$element.val(index); + d.resolve(); + }, 0); + return d.promise(); + } + } + return d.resolve().promise(); } }); openerp.web.search.BooleanField = openerp.web.search.SelectionField.extend(/** @lends openerp.web.search.BooleanField# */{ @@ -947,15 +965,20 @@ openerp.web.search.DateField = openerp.web.search.Field.extend(/** @lends opener template: "SearchView.date", start: function () { this._super(); + // FIXME: this insanity puts a div inside a span this.datewidget = new openerp.web.DateWidget(this); this.datewidget.prependTo(this.$element); - this.datewidget.$element.find("input").attr("size", 15); - this.datewidget.$element.find("input").attr("autofocus", - this.attrs.default_focus === '1' ? 'autofocus' : undefined); + this.datewidget.$element.find("input") + .attr("size", 15) + .attr("autofocus", this.attrs.default_focus === '1' ? 'autofocus' : null) + .removeAttr('style'); this.datewidget.set_value(this.defaults[this.attrs.name] || false); }, get_value: function () { return this.datewidget.get_value() || null; + }, + clear: function () { + this.datewidget.set_value(false); } }); /** @@ -1051,7 +1074,7 @@ openerp.web.search.ManyToOneField = openerp.web.search.CharField.extend({ } }); -openerp.web.search.ExtendedSearch = openerp.web.search.Widget.extend({ +openerp.web.search.ExtendedSearch = openerp.web.search.Input.extend({ template: 'SearchView.extended_search', init: function (parent, model) { this._super(parent); diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js index 26376f24da2..0258509f172 100644 --- a/addons/web/static/src/js/view_editor.js +++ b/addons/web/static/src/js/view_editor.js @@ -27,6 +27,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ type: 'ir.actions.act_window', target: "current", limit: this.dataset.limit || 80, + auto_search : true, flags: { sidebar: false, deletable: false, @@ -45,9 +46,10 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ {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(); }} + {text: _t("Close"), click: function() { self.view_edit_dialog.close(); window.location.reload(); }} ] }).open(); + this.view_edit_dialog.on_close.add_last(function(){window.location.reload();}); this.main_view_id = this.parent.fields_view.view_id; this.action_manager = new openerp.web.ActionManager(this); this.action_manager.appendTo(this.view_edit_dialog); @@ -162,11 +164,12 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ } }, do_delete_view: function() { + var self = this; if (confirm(_t("Do you really want to remove this view?"))) { var controller = this.action_manager.inner_viewmanager.views[this.action_manager.inner_viewmanager.active_view].controller; this.dataset.unlink([this.main_view_id]).then(function() { controller.reload_content(); - this.main_view_id = self.parent.fields_view.view_id; + self.main_view_id = self.parent.fields_view.view_id; }); } }, @@ -227,14 +230,14 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ get_arch: function() { var self = this; var view_arch_list = []; - this.dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type']).then(function(arch) { + this.dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type','priority']).then(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 == 'tree'? 'list': arch[0].type; - view_arch_list.push({"view_id": self.main_view_id, "arch": arch[0].arch}); + view_arch_list.push({"view_id": self.main_view_id, "arch": arch[0].arch,"priority":arch[0].priority}); self.dataset.read_slice([], {domain: [['inherit_id','=', parseInt(self.main_view_id)]]}).then(function(result) { _.each(result, function(res) { - view_arch_list.push({"view_id": res.id, "arch": res.arch}); + view_arch_list.push({"view_id": res.id, "arch": res.arch,"priority":res.priority}); self.inherit_view(arch_object, res); }); return self.edit_view({"main_object": arch_object, @@ -303,7 +306,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ case 3: //for field[@name='type'] obj = _.detect(arch_object, function(element){ - if ((_.intersection(_.flatten(element.att_list), _.uniq(check))).length == check.length) { + if ((_.intersection(_.flatten(element.att_list), _.uniq(check))).length == _.uniq(check).length) { return element; } }); @@ -361,6 +364,20 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ title: _.str.sprintf(_t("View Editor %d - %s"), self.main_view_id, self.model), height: '90%', buttons: [ + {text: _t("Inherited View"), click: function(){ + var selected_row = self.edit_xml_dialog.$element.find('.ui-selected'); + if (selected_row.length) { + if(selected_row.find('a').text().search("field") != -1){ + if (confirm(_t("Do you really wants to create an inherited view here?"))) { + self.inherited_view(selected_row); + } + }else{ + alert("Can't Update View"); + } + }else{ + alert("Select an element"); + } + }}, {text: _t("Preview"), click: function() { var action = { context: self.session.user_context, @@ -368,6 +385,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ views: [[self.main_view_id, self.main_view_type]], type: 'ir.actions.act_window', target: "new", + auto_search: true, flags: { sidebar: false, views_switcher: false, @@ -378,6 +396,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ action_manager.do_action(action); }}, {text: _t("Close"), click: function(){ + self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller.reload_content(); self.edit_xml_dialog.close(); }} ] @@ -397,6 +416,53 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ self.on_select_img(this); }); }, + inherited_view: function(selected_row){ + var self = this; + var row_id = parseInt((selected_row.attr('id')).split('-')[1]); + var obj = self.get_object_by_id(row_id,self.one_object['main_object'], [])[0]; + var view_name = this.model + '.inherit_' + Math.round(Math.random() * 1000); + var view_find = selected_row; + var view_id; + var min_level = parseInt(selected_row.attr('level')); + while (1) { + view_find = view_find.prev(); + if (view_find.length == 0 || + self.edit_xml_dialog.$element.find(view_find).find('a').text().search("view_id") != -1 && + parseInt(view_find.attr('level')) < min_level ) { + view_id = parseInt($(view_find).find('a').text().replace(/[^0-9]+/g, '')); + break; + } + if (view_find.attr('level') < min_level) { + min_level = parseInt(view_find.attr('level')); + } + } + var val = _.detect(obj.att_list, function(val) {return val[0] == "name";}); + var priority = _.detect(self.one_object['arch'], function(val) {return val.view_id == view_id;}); + var arch = _.str.sprintf("<?xml version='1.0'?>\n\t <field name='%s' position='after'> </field>", val[1]); + var vals = {'model': self.model, 'name': view_name, 'priority': priority.priority + 1, 'type': "form", 'arch': arch,'inherit_id':self.main_view_id}; + this.dataset.create(vals, function(suc) { + var arch_to_obj = self.parse_xml(arch,suc.result); + obj.child_id.push(arch_to_obj[0]); + self.one_object['parent_child_id'] = self.parent_child_list(self.one_object['main_object'],[]); + self.one_object['arch'].push({'view_id':suc.result,"arch":arch,'priority': priority.priority + 1}); + self.increase_level(arch_to_obj[0],obj.level+1); + self.render_inherited_view(selected_row,arch_to_obj[0]); + }); + }, + render_inherited_view: function(selected_row,obj){ + var self = this,row_id = parseInt((selected_row.attr('id')).split('-')[1]); + var clone = this.create_clone(selected_row.clone(),obj); + if (selected_row.find("img[id^='parentimg-']").length == 0) { + ($(selected_row.find('a').parent()).siblings('td')) + .append($('<img width="16" height="16"></img>').attr('src', '/web/static/src/img/collapse.gif'). + attr('id','parentimg-'+ row_id).click(function(){ + self.do_parent_img_hide_show(this); + })); + } + self.edit_xml_dialog.$element. + find("tr[id='viewedit-"+row_id+"']").after(clone.removeClass('ui-selected')); + _.each(obj.child_id,function(obj){self.render_inherited_view(clone,obj);}); + }, on_select_img: function(element_img) { var self = this; var side = $(element_img).closest("tr[id^='viewedit-']"); @@ -449,7 +515,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ }, do_node_add: function(side){ var self = this; - var tr = $(side).find('a').text(); + var tr = self.get_object_by_id(this.one_object.clicked_tr_id, this.one_object['main_object'], [])[0].att_list[0]; var parent_tr = ($(side).prevAll("tr[level=" + String(this.one_object.clicked_tr_level - 1) + "]"))[0]; var field_dataset = new openerp.web.DataSetSearch(this, this.model, null, null); parent_tr = $(parent_tr).find('a').text(); @@ -562,13 +628,13 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ arch.arch = _.detect(children, function(xml_child) { var temp_obj = self.create_View_Node(xml_child), insert = _.intersection(_.flatten(temp_obj.att_list),_.uniq(check_list)); - if (insert.length == check_list.length ) {return xml_child;} + if (insert.length == _.uniq(check_list).length ) {return xml_child;} }); } arch_to_pass = _.filter($(arch.arch), function (child) { return child.nodeType == 1; }); - return self.do_save_xml(arch_to_pass[0], obj[0].child_id[0],[], move_direct, update_values,arch); + return self.do_save_xml(arch_to_pass[0], obj[0].child_id[0],obj[0].child_id, move_direct, update_values,arch); }, get_object_by_id: function(id, one_object, result) { var self = this; @@ -583,7 +649,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ } return result; }, - create_clone: function(clone, new_node_obj, position){ + create_clone: function(clone, new_node_obj){ var self = this; clone.find('a').text(new_node_obj.name); ($(clone.find('a').parent()).siblings('td')).css( "padding-left", 20 * new_node_obj.level); @@ -599,7 +665,8 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ return clone; }, do_save_xml: function(arch1, obj, child_list, move_direct, update_values, arch){ - var self = this, children_list = $(arch1).children(), list_obj_xml = _.zip(children_list, obj.child_id); + var self = this, children_list = $(arch1).children(),list_obj_xml; + try{list_obj_xml = _.zip(children_list, obj.child_id);}catch(err){return;} if (this.one_object.clicked_tr_id) { if (obj.id == this.one_object.clicked_tr_id) { var parent = false, index = _.indexOf(child_list, obj); @@ -823,6 +890,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ var value = _.detect(arch_val[0]['att_list'],function(res) { return res instanceof Array? _.include(res, widget.name): false; }); + value = value instanceof Array ? value[1] : value; 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(); @@ -845,7 +913,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ res_groups.read_slice([], {}).done(function (res_grp) { _.each(res_grp, function (res) { var key = res.id; - group_names[key] = res.name; + group_names[key]=res.full_name; group_ids.push(res.id); }); model_data.read_slice([], {domain: [ @@ -933,16 +1001,16 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({ var action_manager = new openerp.web.ActionManager(self); $.when(action_manager.do_action(action)).then(function() { var controller = action_manager.dialog_viewmanager.views['form'].controller; - // TODO NIV: use page view - controller.do_set_readonly.add_last(function(){ + controller.on_button_cancel.add_last(function(){ + action_manager.stop() + }); + controller.do_save.add_last(function(){ action_manager.stop(); - new_fields_name = new openerp.web.DataSetSearch(self,'ir.model.fields', null, null); - new_fields_name.read_ids([controller.datarecord.id], ['name']).then(function(result) { - self.add_node_dialog.$element.find('select[id=field_value]').append($("<option selected></option>").attr("value", result[0].name).text(result[0].name)); + var value =controller.fields.name.value; + self.add_node_dialog.$element.find('select[id=field_value]').append($("<option selected></option>").attr("value",value).text(value)); _.detect(self.add_widget,function(widget){ - widget.name == "field_value"? widget.selection.push(result[0].name): false; + widget.name == "field_value"? widget.selection.push(value): false; }); - }); }); }); } @@ -1039,7 +1107,7 @@ openerp.web.ViewEditor.FieldSelect = openerp.web.ViewEditor.Field.extend({ var index = 0; value = value === null? false: value; for (var i = 0, ii = this.selection.length; i < ii; i++) { - if ((this.selection[i] instanceof Array && this.selection[i][1] === value) || this.selection[i] === value) index = i; + if ((this.selection[i] instanceof Array && this.selection[i][0] === value) || this.selection[i] === value) index = i; } this.$element.find("select[id=" + this.name + "]")[0].selectedIndex = index; }, @@ -1092,10 +1160,10 @@ var _CHILDREN = { 'calendar': ['field'], 'notebook': ['page'], 'page': ['notebook', 'group', 'field', 'label', 'button', 'newline', 'separator'], - 'group': ['field', 'label', 'button', 'separator', 'newline'], + 'group': ['field', 'label', 'button', 'separator', 'newline','group'], 'board': ['column'], 'action': [], - 'field': ['form', 'tree', 'graph'], + 'field': ['form', 'tree', 'graph','field'], 'label': [], 'button' : [], 'newline': [], diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index ca1c2c29e6e..3f576089e5b 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -121,6 +121,15 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.sidebar.attachments = new openerp.web.form.SidebarAttachments(this.sidebar, this); this.sidebar.add_toolbar(this.fields_view.toolbar); this.set_common_sidebar_sections(this.sidebar); + + this.sidebar.add_section(_t('Customize'), 'customize'); + this.sidebar.add_items('customize', [{ + label: _t('Set Default'), + form: this, + callback: function (item) { + item.form.open_defaults_dialog(); + } + }]); } this.has_been_loaded.resolve(); }, @@ -140,6 +149,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# do_show: function () { var self = this; this.$element.show().css('visibility', 'hidden'); + this.$element.removeClass('oe_form_dirty'); return this.has_been_loaded.pipe(function() { var result; if (self.dataset.index === null) { @@ -168,7 +178,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# on_record_loaded: function(record) { var self = this, set_values = []; if (!record) { - throw new Error("Form: No record received"); + this.do_warn("Form", "The record could not be found in the database.", true); + return $.Deferred().reject(); } this.datarecord = record; @@ -204,6 +215,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# if (record.id) { self.do_push_state({id:record.id}); } + self.$element.removeClass('oe_form_dirty'); }); }, on_form_changed: function() { @@ -216,6 +228,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# w.update_dom(); } }, + do_notify_change: function() { + this.$element.addClass('oe_form_dirty'); + }, on_pager_action: function(action) { if (this.can_be_discarded()) { switch (action) { @@ -437,7 +452,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# }); }, on_button_cancel: function() { - return this.do_prev_view({'default': 'page'}); + if (this.can_be_discarded()) { + return this.do_prev_view({'default': 'page'}); + } }, on_button_new: function() { var self = this; @@ -459,8 +476,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# return def.promise(); }, can_be_discarded: function() { - return true; // FIXME: Disabled until the page view and button refactoring is done - return !this.is_dirty() || confirm(_t("Warning, the record has been modified, your changes will be discarded.")); + return !this.$element.is('.oe_form_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 @@ -559,10 +575,10 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } else { this.datarecord.id = r.result; if (!prepend_on_create) { - this.dataset.ids.push(this.datarecord.id); + this.dataset.alter_ids(this.dataset.ids.concat([this.datarecord.id])); this.dataset.index = this.dataset.ids.length - 1; } else { - this.dataset.ids.unshift(this.datarecord.id); + this.dataset.alter_ids([this.datarecord.id].concat(this.dataset.ids)); this.dataset.index = 0; } this.do_update_pager(); @@ -631,6 +647,82 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# }, sidebar_context: function () { return this.do_save().pipe(_.bind(function() {return this.get_fields_values();}, this)); + }, + open_defaults_dialog: function () { + var self = this; + var fields = _.chain(this.fields) + .map(function (field, name) { + var value = field.get_value(); + // ignore fields which are empty, invisible, readonly, o2m + // or m2m + if (!value + || field.invisible + || field.readonly + || field.field.type === 'one2many' + || field.field.type === 'many2many') { + return false; + } + var displayed; + switch(field.field.type) { + case 'selection': + displayed = _(field.values).find(function (option) { + return option[0] === value; + })[1]; + break; + case 'many2one': + displayed = field.value[1] || value; + break; + default: + displayed = value; + } + + return { + name: name, + string: field.string, + value: value, + displayed: displayed, + // convert undefined to false + change_default: !!field.field.change_default + } + }) + .compact() + .sortBy(function (field) { return field.string; }) + .value(); + var conditions = _.chain(fields) + .filter(function (field) { return field.change_default; }) + .value(); + + var d = new openerp.web.Dialog(this, { + title: _t("Set Default"), + args: { + fields: fields, + conditions: conditions + }, + buttons: [ + {text: _t("Close"), click: function () { d.close(); }}, + {text: _t("Save default"), click: function () { + var $defaults = d.$element.find('#formview_default_fields'); + var field_to_set = $defaults.val(); + if (!field_to_set) { + $defaults.parent().addClass('invalid'); + return; + } + var condition = d.$element.find('#formview_default_conditions').val(), + all_users = d.$element.find('#formview_default_all').is(':checked'); + new openerp.web.DataSet(self, 'ir.values').call( + 'set_default', [ + self.dataset.model, + field_to_set, + self.fields[field_to_set].get_value(), + all_users, + false, + condition || false + ]).then(function () { d.close(); }); + }} + ] + }); + d.template = 'FormView.set_default'; + d.open(); } }); openerp.web.FormDialog = openerp.web.Dialog.extend({ @@ -831,7 +923,7 @@ openerp.web.form.Widget = openerp.web.OldWidget.extend(/** @lends openerp.web.fo }, stop: function() { this._super.apply(this, arguments); - $('div.tipsy').stop().remove(); + $.fn.tipsy.clear(); }, process_modifiers: function() { var compute_domain = openerp.web.form.compute_domain; @@ -861,7 +953,7 @@ openerp.web.form.Widget = openerp.web.OldWidget.extend(/** @lends openerp.web.fo debug: openerp.connection.debug, widget: widget })}, - gravity: $.fn.tipsy.autoBounds(50, 'n'), + gravity: $.fn.tipsy.autoBounds(50, 'nw'), html: true, opacity: 0.85, trigger: 'hover' @@ -1219,6 +1311,11 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({ this._super(view, node); + if (this.node.tag == 'label' && !this.string && this.node.children.length) { + this.string = this.node.children[0]; + this.align = 'left'; + } + if (this.node.tag == 'label' && (this.align === 'left' || this.node.attrs.colspan || (this.string && this.string.length > 32))) { this.form_template = "WidgetParagraph"; this.colspan = parseInt(this.node.attrs.colspan || 1, 10); @@ -1227,6 +1324,8 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({ if (isNaN(parseFloat(this.node.attrs.align))) { this.align = 'left'; } + + this.multilines = this.string && _.str.lines(this.string).length > 1; } else { this.colspan = 1; this.width = '1%'; @@ -1293,6 +1392,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f this._super.apply(this, arguments); if (this.field.translate) { this.view.translatable_fields.push(this); + this.$element.addClass('oe_form_field_translatable'); this.$element.find('.oe_field_translate').click(this.on_translate); } if (this.nolabel && openerp.connection.debug) { @@ -1344,7 +1444,8 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f if (this.is_valid()) { this.set_value_from_ui(); this.view.do_onchange(this); - this.view.on_form_changed(); + this.view.on_form_changed(true); + this.view.do_notify_change(); } else { this.update_dom(true); } @@ -1389,7 +1490,7 @@ openerp.web.form.FieldChar = openerp.web.form.Field.extend({ }, update_dom: function() { this._super.apply(this, arguments); - this.$element.find('input').prop('disabled', this.readonly); + this.$element.find('input').prop('readonly', this.readonly); }, set_value_from_ui: function() { this.value = openerp.web.parse_value(this.$element.find('input').val(), this); @@ -1412,7 +1513,7 @@ openerp.web.form.FieldChar = openerp.web.form.Field.extend({ openerp.web.form.FieldID = openerp.web.form.FieldChar.extend({ update_dom: function() { this._super.apply(this, arguments); - this.$element.find('input').prop('disabled', true); + this.$element.find('input').prop('readonly', true); } }); @@ -1490,7 +1591,7 @@ openerp.web.DateTimeWidget = openerp.web.OldWidget.extend({ showButtonPanel: true }); this.$element.find('img.oe_datepicker_trigger').click(function() { - if (!self.readonly) { + if (!self.readonly && !self.picker('widget').is(':visible')) { self.picker('setDate', self.value ? openerp.web.auto_str_to_date(self.value) : new Date()); self.$input_picker.show(); self.picker('show'); @@ -1520,7 +1621,7 @@ openerp.web.DateTimeWidget = openerp.web.OldWidget.extend({ }, set_readonly: function(readonly) { this.readonly = readonly; - this.$input.prop('disabled', this.readonly); + this.$input.prop('readonly', this.readonly); this.$element.find('img.oe_datepicker_trigger').toggleClass('oe_input_icon_disabled', readonly); }, is_valid: function(required) { @@ -1609,7 +1710,7 @@ openerp.web.form.FieldText = openerp.web.form.Field.extend({ }, update_dom: function() { this._super.apply(this, arguments); - this.$element.find('textarea').prop('disabled', this.readonly); + this.$element.find('textarea').prop('readonly', this.readonly); }, set_value_from_ui: function() { this.value = openerp.web.parse_value(this.$element.find('textarea').val(), this); @@ -2126,7 +2227,7 @@ openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({ }, update_dom: function() { this._super.apply(this, arguments); - this.$input.prop('disabled', this.readonly); + this.$input.prop('readonly', this.readonly); } }); @@ -2248,7 +2349,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views, {}); this.viewmanager.template = 'One2Many.viewmanager'; - this.viewmanager.registry = openerp.web.views.clone({ + this.viewmanager.registry = openerp.web.views.extend({ list: 'openerp.web.form.One2ManyListView', form: 'openerp.web.form.One2ManyFormView', page: 'openerp.web.PageView' @@ -2326,13 +2427,13 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ obj['id'] = _.uniqueId(self.dataset.virtual_id_prefix); obj.defaults = {}; self.dataset.to_create.push(obj); - self.dataset.cache.push(_.clone(obj)); + self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])})); ids.push(obj.id); return; case commands.UPDATE: obj['id'] = command[1]; self.dataset.to_write.push(obj); - self.dataset.cache.push(_.clone(obj)); + self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])})); ids.push(obj.id); return; case commands.DELETE: @@ -2539,6 +2640,13 @@ openerp.web.form.One2ManyFormView = openerp.web.FormView.extend({ this.$form_header.find('button.oe_form_button_create').click(function() { self.do_save().then(self.on_button_new); }); + }, + do_notify_change: function() { + if (this.dataset.parent_view) { + this.dataset.parent_view.do_notify_change(); + } else { + this._super.apply(this, arguments); + } } }); @@ -3151,7 +3259,7 @@ openerp.web.form.FieldBinaryFile = openerp.web.form.FieldBinary.extend({ update_dom: function() { this._super.apply(this, arguments); this.$element.find('.oe-binary-file-set, .oe-binary-file-clear').toggle(!this.readonly); - this.$element.find('input[type=text]').prop('disabled', this.readonly); + this.$element.find('input[type=text]').prop('readonly', this.readonly); }, set_value: function(value) { this._super.apply(this, arguments); diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 7fd4d20fba5..eb13bbd927b 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -246,7 +246,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# self.page = 0; break; case 'last': self.page = Math.floor( - self.dataset.ids.length / self.limit()); + self.dataset.size() / self.limit()); break; case 'next': self.page += 1; break; @@ -293,7 +293,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# this.dataset.ids = dataset.ids; var limit = this.limit(), - total = dataset.ids.length, + total = dataset.size(), first = (this.page * limit), last; if (!limit || (total - first) < limit) { @@ -1317,11 +1317,11 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L if (!self.datagroup.openable) { view.configure_pager(dataset); } else { - if (dataset.ids.length == records.length) { + if (dataset.size() == records.length) { // only one page self.$row.find('td.oe-group-pagination').empty(); } else { - var pages = Math.ceil(dataset.ids.length / limit); + var pages = Math.ceil(dataset.size() / limit); self.$row .find('.oe-pager-state') .text(_.str.sprintf(_t("%(page)d/%(page_count)d"), { diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index 4f6a1531c7a..c7222455889 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -386,7 +386,7 @@ openerp.web.list_editable = function (openerp) { template: 'ListView.row.frame' }); var form_widgets = openerp.web.form.widgets; - openerp.web.list.form.widgets = form_widgets.clone({ + openerp.web.list.form.widgets = form_widgets.extend({ 'frame': 'openerp.web.list.form.WidgetFrame' }); // All form widgets inherit a problematic behavior from @@ -395,7 +395,7 @@ openerp.web.list_editable = function (openerp) { // former should completely remove the cell. We need to override update_dom // on all widgets since we can't just hit on widget itself (I think) var list_form_widgets = openerp.web.list.form.widgets; - _(list_form_widgets.map).each(function (widget_path, key) { + _(form_widgets.map).each(function (widget_path, key) { if (key === 'frame') { return; } var new_path = 'openerp.web.list.form.' + key; diff --git a/addons/web/static/src/js/view_page.js b/addons/web/static/src/js/view_page.js index be3863e9918..95259a01927 100644 --- a/addons/web/static/src/js/view_page.js +++ b/addons/web/static/src/js/view_page.js @@ -92,11 +92,13 @@ openerp.web.page = function (openerp) { openerp.web.page.FieldURIReadonly = openerp.web.page.FieldCharReadonly.extend({ form_template: 'FieldURI.readonly', scheme: null, + format_value: function (value) { + return value; + }, set_value: function (value) { - var displayed = this._super.apply(this, arguments); this.$element.find('a') - .attr('href', this.scheme + ':' + displayed) - .text(displayed); + .attr('href', this.scheme + ':' + value) + .text(this.format_value(value)); } }); openerp.web.page.FieldEmailReadonly = openerp.web.page.FieldURIReadonly.extend({ @@ -105,9 +107,10 @@ openerp.web.page = function (openerp) { openerp.web.page.FieldUrlReadonly = openerp.web.page.FieldURIReadonly.extend({ set_value: function (value) { var s = /(\w+):(.+)/.exec(value); - if (!s || !(s[1] === 'http' || s[1] === 'https')) { return; } - this.scheme = s[1]; - this._super(s[2]); + if (!s) { + value = "http://" + value; + } + this.$element.find('a').attr('href', value).text(value); } }); openerp.web.page.FieldBooleanReadonly = openerp.web.form.FieldBoolean.extend({ @@ -242,7 +245,7 @@ openerp.web.page = function (openerp) { } } }); - openerp.web.page.readonly = openerp.web.form.widgets.clone({ + openerp.web.page.readonly = openerp.web.form.widgets.extend({ 'frame': 'openerp.web.page.WidgetFrameReadonly', 'char': 'openerp.web.page.FieldCharReadonly', 'id': 'openerp.web.page.FieldCharReadonly', diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 7c1f7385927..56997190bc1 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -602,16 +602,6 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner width: '95%'}, $root).open(); }); break; - case 'customize_object': - this.rpc('/web/dataset/search_read', { - model: 'ir.model', - fields: ['id'], - domain: [['model', '=', this.dataset.model]] - }, function (result) { - self.do_edit_resource('ir.model', result.ids[0], { - name : _t("Customize Object") }); - }); - break; case 'manage_views': if (current_view.fields_view && current_view.fields_view.arch) { var view_editor = new session.web.ViewEditor(current_view, current_view.$element, this.dataset, current_view.fields_view.arch); @@ -765,16 +755,21 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner var $logs_list = $logs.find('ul').empty(); $logs.toggleClass('oe-has-more', log_records.length > cutoff); _(log_records.reverse()).each(function (record) { + var context = {}; + if (record.context) { + try { context = py.eval(record.context).toJSON(); } + catch (e) { /* TODO: what do I do now? */ } + } $(_.str.sprintf('<li><a href="#">%s</a></li>', record.name)) .appendTo($logs_list) - .delegate('a', 'click', function (e) { + .delegate('a', 'click', function () { self.do_action({ type: 'ir.actions.act_window', res_model: record.res_model, res_id: record.res_id, // TODO: need to have an evaluated context here somehow - //context: record.context, - views: [[false, 'form']] + context: context, + views: [[context.view_id || false, 'form']] }); return false; }); @@ -821,10 +816,6 @@ session.web.Sidebar = session.web.OldWidget.extend({ }, { label: _t("Export"), callback: view.on_sidebar_export - }, { - label: _t("View Log"), - callback: view.on_sidebar_view_log, - classname: 'oe_hide oe_sidebar_view_log' } ]); }, @@ -863,18 +854,32 @@ session.web.Sidebar = session.web.OldWidget.extend({ } return $section; }, - + /** + * For each item added to the section: + * + * ``label`` + * will be used as the item's name in the sidebar + * + * ``action`` + * descriptor for the action which will be executed, ``action`` and + * ``callback`` should be exclusive + * + * ``callback`` + * function to call when the item is clicked in the sidebar, called + * with the item descriptor as its first argument (so information + * can be stored as additional keys on the object passed to + * ``add_items``) + * + * ``classname`` (optional) + * ``@class`` set on the sidebar serialization of the item + * + * ``title`` (optional) + * will be set as the item's ``@title`` (tooltip) + * + * @param {String} section_code + * @param {Array<{label, action | callback[, classname][, title]}>} items + */ add_items: function(section_code, items) { - // An item is a dictonary : { - // label: label to be displayed for the link, - // action: action to be launch when the link is clicked, - // callback: a function to be executed when the link is clicked, - // classname: optional dom class name for the line, - // title: optional title for the link - // } - // Note: The item should have one action or/and a callback - // - var self = this, $section = this.add_section(_.str.titleize(section_code.replace('_', ' ')), section_code), section_id = $section.attr('id'); @@ -1038,7 +1043,8 @@ session.web.TranslateDialog = session.web.Dialog.extend({ }, on_button_Save: function() { var trads = {}, - self = this; + self = this, + trads_mutex = new $.Mutex(); self.$fields_form.find('.oe_trad_field.touched').each(function() { var field = $(this).attr('name').split('-'); if (!trads[field[0]]) { @@ -1051,9 +1057,10 @@ session.web.TranslateDialog = session.web.Dialog.extend({ _.each(data, function(value, field) { self.view.fields[field].set_value(value); }); - } else { - self.view.dataset.write(self.view.datarecord.id, data, { 'lang': code }); } + trads_mutex.exec(function() { + return self.view.dataset.write(self.view.datarecord.id, data, { context : { 'lang': code } }); + }); }); this.close(); }, @@ -1222,8 +1229,6 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{ view_mode : "list" }); }, - on_sidebar_view_log: function() { - }, sidebar_context: function () { return $.when(); }, |
