diff options
Diffstat (limited to 'addons/web/static/src')
| -rw-r--r-- | addons/web/static/src/js/core/abstract_storage_service.js | 13 | ||||
| -rw-r--r-- | addons/web/static/src/js/core/local_storage.js | 10 | ||||
| -rw-r--r-- | addons/web/static/src/js/core/ram_storage.js | 14 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/relational_fields.js | 12 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_model.js | 8 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/form/form_controller.js | 4 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/form/form_view.js | 4 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/graph/graph_view.js | 3 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/kanban/kanban_record.js | 8 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/list/list_controller.js | 2 | ||||
| -rw-r--r-- | addons/web/static/src/js/widgets/auto_complete.js | 12 | ||||
| -rw-r--r-- | addons/web/static/src/js/widgets/date_picker.js | 5 | ||||
| -rw-r--r-- | addons/web/static/src/scss/ui.scss | 8 |
13 files changed, 86 insertions, 17 deletions
diff --git a/addons/web/static/src/js/core/abstract_storage_service.js b/addons/web/static/src/js/core/abstract_storage_service.js index ef828b5dd5c..5d724f87911 100644 --- a/addons/web/static/src/js/core/abstract_storage_service.js +++ b/addons/web/static/src/js/core/abstract_storage_service.js @@ -45,6 +45,19 @@ var AbstractStorageService = AbstractService.extend({ return val ? JSON.parse(val) : defaultValue; }, /** + * @param {integer} index + * @return {string} + */ + key: function (index) { + return this.storage.key(index); + }, + /** + * @return {integer} + */ + length: function () { + return this.storage.length; + }, + /** * Removes the given key from the storage * * @param {string} key diff --git a/addons/web/static/src/js/core/local_storage.js b/addons/web/static/src/js/core/local_storage.js index 0ae98498b31..ecc0cb7b78f 100644 --- a/addons/web/static/src/js/core/local_storage.js +++ b/addons/web/static/src/js/core/local_storage.js @@ -35,12 +35,10 @@ try { var newValue = e.originalEvent.newValue; try { JSON.parse(newValue); - if (localStorage.getItem(key) === newValue) { - storage.trigger('storage', { - key: key, - newValue: newValue, - }); - } + storage.trigger('storage', { + key: key, + newValue: newValue, + }); } catch (error) {} }); return storage; diff --git a/addons/web/static/src/js/core/ram_storage.js b/addons/web/static/src/js/core/ram_storage.js index 9bf0fc29f93..abad86c4538 100644 --- a/addons/web/static/src/js/core/ram_storage.js +++ b/addons/web/static/src/js/core/ram_storage.js @@ -31,6 +31,7 @@ var RamStorage = Class.extend(mixins.EventDispatcherMixin, { */ clear: function () { this.storage = Object.create(null); + this.length = 0; }, /** * Returns the value associated with a given key in the storage @@ -42,11 +43,21 @@ var RamStorage = Class.extend(mixins.EventDispatcherMixin, { return this.storage[key]; }, /** + * @param {integer} index + * @return {string} + */ + key: function (index) { + return _.keys(this.storage)[index]; + }, + /** * Removes the given key from the storage * * @param {string} key */ removeItem: function (key) { + if (key in this.storage) { + this.length--; + } delete this.storage[key]; this.trigger('storage', {key: key, newValue: null}); }, @@ -58,6 +69,9 @@ var RamStorage = Class.extend(mixins.EventDispatcherMixin, { * @param {string} value */ setItem: function (key, value) { + if (!(key in this.storage)) { + this.length++; + } this.storage[key] = value; this.trigger('storage', {key: key, newValue: value}); }, diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index c0dc8ec65e5..be35395aab7 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -2503,7 +2503,7 @@ var FieldSelection = AbstractField.extend({ description: _lt("Selection"), template: 'FieldSelection', specialData: "_fetchSpecialRelation", - supportedFieldTypes: ['selection', 'many2one'], + supportedFieldTypes: ['selection'], events: _.extend({}, AbstractField.prototype.events, { 'change': '_onChange', }), @@ -2556,10 +2556,14 @@ var FieldSelection = AbstractField.extend({ */ _renderEdit: function () { this.$el.empty(); + var required = this.attrs.modifiersValue && this.attrs.modifiersValue.required; for (var i = 0 ; i < this.values.length ; i++) { + var disabled = required && this.values[i][0] === false; + this.$el.append($('<option/>', { value: JSON.stringify(this.values[i][0]), - text: this.values[i][1] + text: this.values[i][1], + style: disabled ? "display: none" : "", })); } var value = this.value; @@ -2598,9 +2602,7 @@ var FieldSelection = AbstractField.extend({ return v[0] === false && v[1] === ''; }); } - if (!this.attrs.modifiersValue || !this.attrs.modifiersValue.required) { - this.values = [[false, this.attrs.placeholder || '']].concat(this.values); - } + this.values = [[false, this.attrs.placeholder || '']].concat(this.values); }, //-------------------------------------------------------------------------- diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 6d1b31ea8ea..8fd365368d6 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -2001,9 +2001,11 @@ var BasicModel = AbstractModel.extend({ if (field.onChange) { hasOnchange = true; } - _.each(fieldInfo.views, function (view) { - generateSpecs(view.fieldsInfo[view.type], view.fields, key + '.'); - }); + if (field.type === 'one2many' || field.type === 'many2many') { + _.each(fieldInfo.views, function (view) { + generateSpecs(view.fieldsInfo[view.type], view.fields, key + '.'); + }); + } }); } return hasOnchange ? specs : false; diff --git a/addons/web/static/src/js/views/form/form_controller.js b/addons/web/static/src/js/views/form/form_controller.js index 5aef3d54bfa..6ffcb81b3f4 100644 --- a/addons/web/static/src/js/views/form/form_controller.js +++ b/addons/web/static/src/js/views/form/form_controller.js @@ -588,7 +588,9 @@ var FormController = BasicController.extend({ * @private */ _onEdit: function () { - this._setMode('edit'); + // wait for potential pending changes to be saved (done with widgets + // allowing to edit in readonly) + this.mutex.getUnlockedDef().then(this._setMode.bind(this, 'edit')); }, /** * This method is called when someone tries to freeze the order, most likely diff --git a/addons/web/static/src/js/views/form/form_view.js b/addons/web/static/src/js/views/form/form_view.js index 0703d9713d5..4889a27f9e5 100644 --- a/addons/web/static/src/js/views/form/form_view.js +++ b/addons/web/static/src/js/views/form/form_view.js @@ -127,6 +127,10 @@ var FormView = BasicView.extend({ var refinedContext = _.pick(self.loadParams.context, function (value, key) { return key.indexOf('_view_ref') === -1; }); + // Specify the main model to prevent access rights defined in the context + // (e.g. create: 0) to apply to subviews. We use here the same logic as + // the one applied by the server for inline views. + refinedContext.base_model_name = self.controllerParams.modelName; defs.push(parent.loadViews( field.relation, new Context(context, self.userContext, refinedContext).eval(), diff --git a/addons/web/static/src/js/views/graph/graph_view.js b/addons/web/static/src/js/views/graph/graph_view.js index 4a91bd67f19..f0ac97538d0 100644 --- a/addons/web/static/src/js/views/graph/graph_view.js +++ b/addons/web/static/src/js/views/graph/graph_view.js @@ -48,6 +48,9 @@ var GraphView = AbstractView.extend({ this.arch.children.forEach(function (field) { var fieldName = field.attrs.name; + if (fieldName === "id") { + return; + } var interval = field.attrs.interval; if (interval) { fieldName = fieldName + ':' + interval; diff --git a/addons/web/static/src/js/views/kanban/kanban_record.js b/addons/web/static/src/js/views/kanban/kanban_record.js index b643b8355b6..753a1d80ea0 100644 --- a/addons/web/static/src/js/views/kanban/kanban_record.js +++ b/addons/web/static/src/js/views/kanban/kanban_record.js @@ -69,12 +69,14 @@ var KanbanRecord = Widget.extend({ * Called each time the record is attached to the DOM. */ on_attach_callback: function () { + this.isInDOM = true; _.invoke(this.subWidgets, 'on_attach_callback'); }, /** * Called each time the record is detached from the DOM. */ on_detach_callback: function () { + this.isInDOM = false; _.invoke(this.subWidgets, 'on_detach_callback'); }, @@ -255,6 +257,9 @@ var KanbanRecord = Widget.extend({ // a widget already exists for that field, so reset it with the new state widget.reset(self.state); $field.replaceWith(widget.$el); + if (self.isInDOM && widget.on_attach_callback) { + widget.on_attach_callback(); + } } } else { self._processField($field, field_name); @@ -341,6 +346,9 @@ var KanbanRecord = Widget.extend({ */ _render: function () { this.defs = []; + // call 'on_detach_callback' on each subwidget as they will be removed + // from the DOM at the next line + _.invoke(this.subWidgets, 'on_detach_callback'); this._replaceElement(this.qweb.render('kanban-box', this.qweb_context)); this.$el.addClass('o_kanban_record').attr("tabindex", 0); this.$el.attr('role', 'article'); diff --git a/addons/web/static/src/js/views/list/list_controller.js b/addons/web/static/src/js/views/list/list_controller.js index ffeef454716..b864063ee92 100644 --- a/addons/web/static/src/js/views/list/list_controller.js +++ b/addons/web/static/src/js/views/list/list_controller.js @@ -598,6 +598,7 @@ var ListController = BasicController.extend({ _onEditGroupClicked: function (ev) { ev.stopPropagation(); this.do_action({ + context: {create: false}, type: 'ir.actions.act_window', views: [[false, 'form']], res_model: ev.data.record.model, @@ -679,6 +680,7 @@ var ListController = BasicController.extend({ * @param {OdooEvent} ev */ _onToggleGroup: function (ev) { + ev.stopPropagation(); var self = this; this.model .toggleGroup(ev.data.group.id) diff --git a/addons/web/static/src/js/widgets/auto_complete.js b/addons/web/static/src/js/widgets/auto_complete.js index 4da54cf8b5c..1bb00be8d38 100644 --- a/addons/web/static/src/js/widgets/auto_complete.js +++ b/addons/web/static/src/js/widgets/auto_complete.js @@ -140,12 +140,22 @@ return Widget.extend({ var $item = self.make_list_item(result).appendTo($list); result.$el = $item; }); + // IE9 doesn't support addEventListener with option { once: true } + this.el.onmousemove = function (ev) { + self.$('li').each(function (index, li) { + li.onmouseenter = self.focus_element.bind(self, $(li)); + }); + var targetFocus = ev.target.tagName === 'LI' ? + ev.target : + ev.target.closest('li'); + self.focus_element($(targetFocus)); + self.el.onmousemove = null; + }; this.show(); }, make_list_item: function (result) { var self = this; var $li = $('<li>') - .hover(function () {self.focus_element($li);}) .mousedown(function (ev) { if (ev.button === 0) { // left button self.select(ev, {item: {facet: result.facet}}); diff --git a/addons/web/static/src/js/widgets/date_picker.js b/addons/web/static/src/js/widgets/date_picker.js index 5b4480838fe..ac8e83c8e30 100644 --- a/addons/web/static/src/js/widgets/date_picker.js +++ b/addons/web/static/src/js/widgets/date_picker.js @@ -92,8 +92,8 @@ var DateWidget = Widget.extend({ * set datetime value */ changeDatetime: function () { + var oldValue = this.getValue(); if (this.isValid()) { - var oldValue = this.getValue(); this._setValueFromUi(); var newValue = this.getValue(); var hasChanged = !oldValue !== !newValue; @@ -110,6 +110,9 @@ var DateWidget = Widget.extend({ } this.trigger("datetime_changed"); } + } else { + var formattedValue = oldValue ? this._formatClient(oldValue) : null; + this.$input.val(formattedValue); } }, /** diff --git a/addons/web/static/src/scss/ui.scss b/addons/web/static/src/scss/ui.scss index 44d639805be..9ab1729a4ac 100644 --- a/addons/web/static/src/scss/ui.scss +++ b/addons/web/static/src/scss/ui.scss @@ -83,3 +83,11 @@ .o_debounce_disabled { pointer-events: none; } + +span.o_force_ltr { + display: inline-block; +} +.o_force_ltr, .o_field_phone { + /*rtl:ignore*/ + direction: ltr; +} |
