diff options
| author | Paramjit Singh Sahota <psa@tinyerp.com> | 2013-05-17 11:01:30 +0530 |
|---|---|---|
| committer | Paramjit Singh Sahota <psa@tinyerp.com> | 2013-05-17 11:01:30 +0530 |
| commit | a031c86d68ad3ebaad2ea8381c8667ae92b14e19 (patch) | |
| tree | f0bfa73ebe69ebc42fcf04ebe58976bc0239b571 /addons/web/static/src | |
| parent | 876c7900775baa7a653983ba1049355497dcd439 (diff) | |
| parent | ee262e156a19bceb961f62ea3912e362a11ddad3 (diff) | |
[MERGE] Merged lp:openerp-web/7.0
bzr revid: bth@tinyerp.com-20130417073823-qh3hzbj2j70kt6c6
bzr revid: psa@tinyerp.com-20130517053130-09k6t1os2x6g8i0j
Diffstat (limited to 'addons/web/static/src')
| -rw-r--r-- | addons/web/static/src/css/base.css | 10 | ||||
| -rw-r--r-- | addons/web/static/src/css/base.sass | 4 | ||||
| -rw-r--r--[-rwxr-xr-x] | addons/web/static/src/font/entypo-webfont.svg | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | addons/web/static/src/font/mnmliconsv21-webfont.svg | 0 | ||||
| -rw-r--r-- | addons/web/static/src/js/chrome.js | 47 | ||||
| -rw-r--r-- | addons/web/static/src/js/coresetup.js | 8 | ||||
| -rw-r--r-- | addons/web/static/src/js/data.js | 48 | ||||
| -rw-r--r-- | addons/web/static/src/js/formats.js | 30 | ||||
| -rw-r--r-- | addons/web/static/src/js/search.js | 34 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_form.js | 20 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list.js | 5 | ||||
| -rw-r--r-- | addons/web/static/src/js/views.js | 9 | ||||
| -rw-r--r-- | addons/web/static/src/xml/base.xml | 4 |
13 files changed, 159 insertions, 60 deletions
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index b4d6e7968b9..66997040bde 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -1269,7 +1269,7 @@ color: white; padding: 2px 4px; margin: 1px 6px 0 0; - border: 1px solid lightGray; + border: 1px solid lightgrey; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-border-radius: 4px; -webkit-border-radius: 4px; @@ -1301,7 +1301,7 @@ transform: scale(1.1); } .openerp .oe_secondary_submenu .oe_active { - border-top: 1px solid lightGray; + border-top: 1px solid lightgrey; border-bottom: 1px solid #dedede; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2), inset 0 -1px 3px rgba(40, 40, 40, 0.2); @@ -2288,7 +2288,7 @@ } .openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span { font-size: 80%; - color: darkGreen; + color: darkgreen; vertical-align: top; position: relative; top: -4px; @@ -2472,10 +2472,10 @@ width: 7em; } .openerp .oe_form_editable .oe_form .oe_form_field_date input { - width: 7.5em; + width: 100px; } .openerp .oe_form_editable .oe_form .oe_form_field_datetime input { - width: 11.5em; + width: 150px; } .openerp .oe_hidden_input_file { position: relative; diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 52893fc77ca..3f4f3e58bbe 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -1959,9 +1959,9 @@ $sheet-padding: 16px .oe_form_field_float input width: 7em .oe_form_field_date input - width: 7.5em + width: 100px .oe_form_field_datetime input - width: 11.5em + width: 150px // }}} // FormView.fields_binary {{{ /* http://www.quirksmode.org/dom/inputfile.html diff --git a/addons/web/static/src/font/entypo-webfont.svg b/addons/web/static/src/font/entypo-webfont.svg index c24d92adb5f..c24d92adb5f 100755..100644 --- a/addons/web/static/src/font/entypo-webfont.svg +++ b/addons/web/static/src/font/entypo-webfont.svg diff --git a/addons/web/static/src/font/mnmliconsv21-webfont.svg b/addons/web/static/src/font/mnmliconsv21-webfont.svg index 34b20ff992f..34b20ff992f 100755..100644 --- a/addons/web/static/src/font/mnmliconsv21-webfont.svg +++ b/addons/web/static/src/font/mnmliconsv21-webfont.svg diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index ef045f07931..3944078a5a7 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -249,7 +249,9 @@ instance.web.CrashManager = instance.web.Class.extend({ } // yes, exception handling is shitty if (error.code === 300 && error.data && error.data.type == "client_exception" && error.data.debug.match("SessionExpiredException")) { - this.show_warning({type: "Session Expired", data: { fault_code: "Your OpenERP session expired. Please refresh the current web page." }}); + this.show_warning({type: "Session Expired", data: { + fault_code: _t("Your OpenERP session expired. Please refresh the current web page.") + }}); return; } if (error.data.fault_code) { @@ -861,9 +863,7 @@ instance.web.Menu = instance.web.Widget.extend({ self.reflow(); // launch the fetch of needaction counters, asynchronous if (!_.isEmpty(menu_data.all_menu_ids)) { - this.rpc("/web/menu/load_needaction", {menu_ids: menu_data.all_menu_ids}).done(function(r) { - self.on_needaction_loaded(r); - }); + this.do_load_needaction(menu_data.all_menu_ids); } }); var lazyreflow = _.debounce(this.reflow.bind(this), 200); @@ -889,7 +889,7 @@ instance.web.Menu = instance.web.Widget.extend({ this.data = {data: data}; this.renderElement(); this.$secondary_menus.html(QWeb.render("Menu.secondary", { widget : this })); - this.$el.on('click', 'a[data-menu]', this.on_menu_click); + this.$el.on('click', 'a[data-menu]', this.on_top_menu_click); // Hide second level submenus this.$secondary_menus.find('.oe_menu_toggler').siblings('.oe_secondary_submenu').hide(); if (self.current_menu) { @@ -898,6 +898,16 @@ instance.web.Menu = instance.web.Widget.extend({ this.trigger('menu_loaded', data); this.has_been_loaded.resolve(); }, + do_load_needaction: function (menu_ids) { + var self = this; + menu_ids = _.compact(menu_ids); + if (_.isEmpty(menu_ids)) { + return $.when(); + } + return this.rpc("/web/menu/load_needaction", {'menu_ids': menu_ids}).done(function(r) { + self.on_needaction_loaded(r); + }); + }, on_needaction_loaded: function(data) { var self = this; this.needaction_data = data; @@ -1029,11 +1039,38 @@ instance.web.Menu = instance.web.Widget.extend({ } this.open_menu(id); }, + do_reload_needaction: function () { + var self = this; + if (self.current_menu) { + self.do_load_needaction([self.current_menu]).then(function () { + self.trigger("need_action_reloaded"); + }); + } + }, /** * Jquery event handler for menu click * * @param {Event} ev the jquery event */ + on_top_menu_click: function(ev) { + var self = this; + var id = $(ev.currentTarget).data('menu'); + var menu_ids = [id]; + var menu = _.filter(this.data.data.children, function (menu) {return menu.id == id;})[0]; + function add_menu_ids (menu) { + if (menu.children) { + _.each(menu.children, function (menu) { + menu_ids.push(menu.id); + add_menu_ids(menu); + }); + } + }; + add_menu_ids(menu); + self.do_load_needaction(menu_ids).then(function () { + self.trigger("need_action_reloaded"); + }); + this.on_menu_click(ev); + }, on_menu_click: function(ev) { ev.preventDefault(); var needaction = $(ev.target).is('div.oe_menu_counter'); diff --git a/addons/web/static/src/js/coresetup.js b/addons/web/static/src/js/coresetup.js index dedb4a49710..6fc837333b6 100644 --- a/addons/web/static/src/js/coresetup.js +++ b/addons/web/static/src/js/coresetup.js @@ -555,19 +555,19 @@ instance.web.qweb.default_dict = { instance.web.qweb.preprocess_node = function() { // Note that 'this' is the Qweb Node switch (this.node.nodeType) { - case 3: - case 4: + case Node.TEXT_NODE: + case Node.CDATA_SECTION_NODE: // Text and CDATAs var translation = this.node.parentNode.attributes['t-translation']; if (translation && translation.value === 'off') { return; } - var match = /^(\s*)(.+?)(\s*)$/.exec(this.node.data); + var match = /^(\s*)([\s\S]+?)(\s*)$/.exec(this.node.data); if (match) { this.node.data = match[1] + instance.web._t(match[2]) + match[3]; } break; - case 1: + case Node.ELEMENT_NODE: // Element var attr, attrs = ['label', 'title', 'alt', 'placeholder']; while (attr = attrs.pop()) { diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index f1b043bacf9..d60f72c6577 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -112,24 +112,27 @@ instance.web.Query = instance.web.Class.extend({ * @returns {jQuery.Deferred<Array<openerp.web.QueryGroup>> | null} */ group_by: function (grouping) { - if (grouping === undefined) { - return null; + var ctx = instance.web.pyeval.eval( + 'context', this._model.context(this._context)); + + // undefined passed in explicitly (!) + if (_.isUndefined(grouping)) { + grouping = []; } if (!(grouping instanceof Array)) { grouping = _.toArray(arguments); } - if (_.isEmpty(grouping)) { return null; } + if (_.isEmpty(grouping) && !ctx['group_by_no_leaf']) { + return null; + } var self = this; - - var ctx = instance.web.pyeval.eval( - 'context', this._model.context(this._context)); return this._model.call('read_group', { groupby: grouping, fields: _.uniq(grouping.concat(this._fields || [])), domain: this._model.domain(this._filter), - context: this._model.context(this._context), + context: ctx, offset: this._offset, limit: this._limit, orderby: instance.web.serialize_sort(this._order_by) || false @@ -325,7 +328,7 @@ instance.web.Model = instance.web.Class.extend({ * Fetches the model's domain, combined with the provided domain if any * * @param {Array} [domain] to combine with the model's internal domain - * @returns The model's internal domain, or the AND-ed union of the model's internal domain and the provided domain + * @returns {instance.web.CompoundDomain} The model's internal domain, or the AND-ed union of the model's internal domain and the provided domain */ domain: function (domain) { if (!domain) { return this._domain; } @@ -337,7 +340,7 @@ instance.web.Model = instance.web.Class.extend({ * combined with the provided context if any * * @param {Object} [context] to combine with the model's internal context - * @returns The union of the user's context and the model's internal context, as well as the provided context if any. In that order. + * @returns {instance.web.CompoundContext} The union of the user's context and the model's internal context, as well as the provided context if any. In that order. */ context: function (context) { return new instance.web.CompoundContext( @@ -604,6 +607,9 @@ instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin, alter_ids: function(n_ids) { this.ids = n_ids; }, + remove_ids: function (ids) { + this.alter_ids(_(this.ids).difference(ids)); + }, /** * Resequence records. * @@ -701,22 +707,28 @@ instance.web.DataSetSearch = instance.web.DataSet.extend({ get_domain: function (other_domain) { this._model.domain(other_domain); }, + alter_ids: function (ids) { + this._super(ids); + if (this.index !== null && this.index >= this.ids.length) { + this.index = this.ids.length > 0 ? this.ids.length - 1 : 0; + } + }, + remove_ids: function (ids) { + var before = this.ids.length; + this._super(ids); + if (this._length) { + this._length -= (before - this.ids.length); + } + }, unlink: function(ids, callback, error_callback) { var self = this; return this._super(ids).done(function(result) { - self.ids = _(self.ids).difference(ids); - if (self._length) { - self._length -= 1; - } - if (self.index !== null) { - self.index = self.index <= self.ids.length - 1 ? - self.index : (self.ids.length > 0 ? self.ids.length -1 : 0); - } + self.remove_ids( ids); self.trigger("dataset_changed", ids, callback, error_callback); }); }, size: function () { - if (this._length !== undefined) { + if (this._length != null) { return this._length; } return this._super(); diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index 851b60af229..854c5f76218 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -314,4 +314,34 @@ instance.web.auto_date_to_str = function(value, type) { } }; +/** + * performs a half up rounding with arbitrary precision, correcting for float loss of precision + * See the corresponding float_round() in server/tools/float_utils.py for more info + * @param {Number} the value to be rounded + * @param {Number} a non zero precision parameter. eg: 0.01 rounds to two digits. + */ +instance.web.round_precision = function(value, precision){ + if(!value){ + return 0; + }else if(!precision){ + throw new Error('round_precision(...): Cannot round value: '+value+' with a precision of zero (or undefined)'); + } + var normalized_value = value / precision; + var epsilon_magnitude = Math.log(Math.abs(normalized_value))/Math.log(2); + var epsilon = Math.pow(2, epsilon_magnitude - 53); + normalized_value += normalized_value >= 0 ? epsilon : -epsilon; + var rounded_value = Math.round(normalized_value); + return rounded_value * precision; +}; + +/** + * performs a half up rounding with a fixed amount of decimals, correcting for float loss of precision + * See the corresponding float_round() in server/tools/float_utils.py for more info + * @param {Number} the value to be rounded + * @param {Number} the number of decimals. eg: round_decimals(3.141592,2) -> 3.14 + */ +instance.web.round_decimals = function(value, decimals){ + return instance.web.round_precision(value, Math.pow(10,-decimals)); +}; + }; diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index c284dcb513b..e84a9472ff3 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -326,7 +326,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea } }, 'autocompleteopen': function () { - this.$el.autocomplete('widget').css('z-index', 3); + this.$el.autocomplete('widget').css('z-index', 1004); }, }, /** @@ -1346,20 +1346,22 @@ instance.web.search.CharField = instance.web.search.Field.extend( /** @lends ins } }); instance.web.search.NumberField = instance.web.search.Field.extend(/** @lends instance.web.search.NumberField# */{ - value_from: function () { - if (!this.$el.val()) { - return null; - } - var val = this.parse(this.$el.val()), - check = Number(this.$el.val()); - if (isNaN(val) || val !== check) { - this.$el.addClass('error'); - throw new instance.web.search.Invalid( - this.attrs.name, this.$el.val(), this.error_message); - } - this.$el.removeClass('error'); - return val; - } + complete: function (value) { + var val = this.parse(value); + if (isNaN(val)) { return $.when(); } + var label = _.str.sprintf( + _t("Search %(field)s for: %(value)s"), { + field: '<em>' + this.attrs.string + '</em>', + value: '<strong>' + _.str.escapeHTML(value) + '</strong>'}); + return $.when([{ + label: label, + facet: { + category: this.attrs.string, + field: this, + values: [{label: value, value: val}] + } + }]); + }, }); /** * @class @@ -1897,7 +1899,7 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @ this._super(parent); this.fields = _(fields).chain() .map(function(val, key) { return _.extend({}, val, {'name': key}); }) - .filter(function (field) { return !field.deprecated; }) + .filter(function (field) { return !field.deprecated && (field.store === void 0 || field.store || field.fnct_search); }) .sortBy(function(field) {return field.string;}) .value(); this.attrs = {_: _, fields: this.fields, selected: null}; diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index a2091bb5c40..b9dfa8e284a 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -91,6 +91,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM init: function(parent, dataset, view_id, options) { var self = this; this._super(parent); + this.ViewManager = parent; this.set_default_options(options); this.dataset = dataset; this.model = dataset.model; @@ -720,6 +721,8 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM return this.save().done(function(result) { self.trigger("save", result); self.to_view_mode(); + }).then(function(result) { + self.ViewManager.ActionManager.__parentedParent.menu.do_reload_needaction(); }); }, on_button_cancel: function(event) { @@ -765,7 +768,11 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM this.has_been_loaded.done(function() { if (self.datarecord.id && confirm(_t("Do you really want to delete this record?"))) { self.dataset.unlink([self.datarecord.id]).done(function() { - self.execute_pager_action('next'); + if (self.dataset.size()) { + self.execute_pager_action('next'); + } else { + self.do_action('history_back'); + } def.resolve(); }); } else { @@ -802,6 +809,8 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM if (save_obj.error) return $.Deferred().reject(); return $.when.apply($, save_obj.ret); + }).done(function() { + self.$el.removeClass('oe_form_dirty'); }); }, _process_save: function(save_obj) { @@ -1444,6 +1453,9 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt $(this).children().each(function() { var $td = $(this), $child = $td.children(':first'); + if ($child.attr('cell-class')) { + $td.addClass($child.attr('cell-class')); + } switch ($child[0].tagName.toLowerCase()) { case 'separator': break; @@ -1520,7 +1532,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt if (! page.__ic) return; page.__ic.on("change:effective_invisible", null, function() { - if (!page.__ic.get('effective_invisible')) { + if (!page.__ic.get('effective_invisible') && page.autofocus) { $new_notebook.tabs('select', i); return; } @@ -2126,7 +2138,7 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w value without triggering a re-rendering. */ internal_set_value: function(value_) { - var tmp = this.no_render; + var tmp = this.no_rerender; this.no_rerender = true; this.set({'value': value_}); this.no_rerender = tmp; @@ -3281,7 +3293,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc } if (! no_recurse) { var dataset = new instance.web.DataSetStatic(this, this.field.relation, self.build_context()); - dataset.name_get([self.get("value")]).done(function(data) { + this.alive(dataset.name_get([self.get("value")])).done(function(data) { self.display_value["" + self.get("value")] = data[0][1]; self.render_value(true); }); diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 3c89ef7126e..b96079d2051 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -895,8 +895,9 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web. this.record_callbacks = { 'remove': function (event, record) { - var $row = self.$current.children( - '[data-id=' + record.get('id') + ']'); + var id = record.get('id'); + self.dataset.remove_ids([id]) + var $row = self.$current.children('[data-id=' + id + ']'); var index = $row.data('index'); $row.remove(); }, diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 0a7250397f7..f9050369a83 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -521,6 +521,7 @@ instance.web.ViewManager = instance.web.Widget.extend({ return x; } }); + this.ActionManager = parent; this.views = {}; this.flags = flags || {}; this.registry = instance.web.views; @@ -1259,6 +1260,7 @@ instance.web.View = instance.web.Widget.extend({ view_type: undefined, init: function(parent, dataset, view_id, options) { this._super(parent); + this.ViewManager = parent; this.dataset = dataset; this.view_id = view_id; this.set_default_options(options); @@ -1330,7 +1332,6 @@ instance.web.View = instance.web.Widget.extend({ } }; var context = new instance.web.CompoundContext(dataset.get_context(), action_data.context || {}); - var handler = function (action) { if (action && action.constructor == Object) { var ncontext = new instance.web.CompoundContext(context); @@ -1367,7 +1368,11 @@ instance.web.View = instance.web.Widget.extend({ } } args.push(context); - return dataset.call_button(action_data.name, args).then(handler); + return dataset.call_button(action_data.name, args).then(handler).then(function () { + if (instance.webclient) { + instance.webclient.menu.do_reload_needaction(); + } + }); } else if (action_data.type=="action") { return this.rpc('/web/action/load', { action_id: action_data.name, diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index c9adc91a6ad..9c0e3fa249f 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -650,7 +650,7 @@ <li t-if="section.name == 'files'" class="oe_sidebar_add_attachment"> <t t-call="HiddenInputFile"> <t t-set="fileupload_id" t-value="widget.fileupload_id"/> - <t t-set="fileupload_action">/web/binary/upload_attachment</t> + <t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t> <input type="hidden" name="model" t-att-value="widget.dataset and widget.dataset.model"/> <input type="hidden" name="id" t-att-value="widget.model_id"/> <input type="hidden" name="session_id" t-att-value="widget.session.session_id"/> @@ -739,7 +739,7 @@ <td t-foreach="aggregate_columns" t-as="column" class="oe_list_footer oe_number" t-att-data-field="column.id" t-att-title="column.label"> </td> - <td t-if="options.deletable"/> + <td t-if="options.deletable" class="oe_list_record_delete"/> </tr> </tfoot> </table> |
