diff options
| author | Aaron Bohy <aab@odoo.com> | 2016-04-08 14:53:34 +0200 |
|---|---|---|
| committer | Géry Debongnie <ged@odoo.com> | 2016-04-21 15:21:39 +0200 |
| commit | 977db823c7c84e9edc7c8cf8384eb9cf47275b3a (patch) | |
| tree | c3312f745baf11d51f976a60d6e285480f557d4c /addons/web/static/src/js/views/form_relational_widgets.js | |
| parent | e1bfd3fbda97ac7a64a585b07be161d5be606cf9 (diff) | |
[REF] web: stop duplicating web
Avoid duplicating web addon in enterprise by extracting a common basis.
Enterprise features stay in enterprise, but use that common basis.
Mainly:
- JS refactoring and linting
- Conversion of .sass into .less split into multiple files
- Templates cleaning and DOM simplification
- Re-generation of web.pot, and update of .po files
Diffstat (limited to 'addons/web/static/src/js/views/form_relational_widgets.js')
| -rw-r--r-- | addons/web/static/src/js/views/form_relational_widgets.js | 426 |
1 files changed, 207 insertions, 219 deletions
diff --git a/addons/web/static/src/js/views/form_relational_widgets.js b/addons/web/static/src/js/views/form_relational_widgets.js index fc852108035..8e64599f470 100644 --- a/addons/web/static/src/js/views/form_relational_widgets.js +++ b/addons/web/static/src/js/views/form_relational_widgets.js @@ -6,7 +6,6 @@ var core = require('web.core'); var data = require('web.data'); var Dialog = require('web.Dialog'); var common = require('web.form_common'); -var FormView = require('web.FormView'); var ListView = require('web.ListView'); var Model = require('web.DataModel'); var session = require('web.session'); @@ -56,16 +55,15 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com events: { 'keydown input': function (e) { switch (e.which) { - case $.ui.keyCode.UP: - case $.ui.keyCode.DOWN: - e.stopPropagation(); + case $.ui.keyCode.UP: + case $.ui.keyCode.DOWN: + e.stopPropagation(); } }, }, init: function(field_manager, node) { this._super(field_manager, node); common.CompletionFieldMixin.init.call(this); - this.set({'value': false}); this.display_value = {}; this.display_value_backup = {}; this.last_search = []; @@ -91,8 +89,9 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com common.ReinitializeFieldMixin.initialize_field.call(this); }, initialize_content: function() { - if (!this.get("effective_readonly")) + if (!this.get("effective_readonly")) { this.render_editable(); + } }, destroy_content: function () { if (this.$dropdown) { @@ -125,16 +124,15 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com }, render_editable: function() { var self = this; - this.$input = this.$el.find("input"); + this.$input = this.$("input"); this.init_error_displayer(); - self.$input.on('focus', function() { self.hide_error_displayer(); }); - this.$dropdown = this.$el.find(".oe_m2o_drop_down_button"); - this.$follow_button = $(".oe_m2o_cm_button", this.$el); + this.$dropdown = this.$(".o_dropdown_button"); + this.$follow_button = this.$(".o_external_button"); this.$follow_button.click(function(ev) { ev.preventDefault(); @@ -177,8 +175,7 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com }; this.$input.keydown(input_changed); this.$input.change(input_changed); - this.$dropdown.click(function() { - self.$input.focus(); + this.$input.on('click', function() { if (self.$input.autocomplete("widget").is(":visible")) { self.$input.autocomplete("close"); } else { @@ -298,7 +295,6 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com }); // set position for list of suggestions box this.$input.autocomplete( "option", "position", { my : "left top", at: "left bottom" } ); - this.$input.autocomplete("widget").openerpClass(); // used to correct a bug when selecting an element by pushing 'enter' in an editable list this.$input.keyup(function(e) { if (e.which === 13) { // ENTER @@ -311,7 +307,7 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com }, render_value: function(no_recurse) { var self = this; - if (! this.get("value")) { + if (!this.get("value")) { this.display_string(""); return; } @@ -320,7 +316,7 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com this.display_string(display); return; } - if (! no_recurse) { + if (!no_recurse) { var dataset = new data.DataSetStatic(this, this.field.relation, self.build_context()); var def = this.alive(dataset.name_get([self.get("value")])).done(function(data) { if (!data[0]) { @@ -341,38 +337,33 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com } }, display_string: function(str) { - var self = this; if (!this.get("effective_readonly")) { this.$input.val(str.split("\n")[0]); this.current_display = this.$input.val(); - if (this.is_false()) { - this.$('.oe_m2o_cm_button').css({'display':'none'}); - } else { - this.$('.oe_m2o_cm_button').css({'display':'inline'}); - } + this.$follow_button.toggle(!this.is_false()); + this.$el.toggleClass('o_with_button', !!this.$follow_button && this.$follow_button.length > 0 && !this.is_false()); } else { - var lines = _.escape(str).split("\n"); - var link = ""; - var follow = ""; - link = lines[0]; - follow = _.rest(lines).join("<br />"); - if (follow) - link += "<br />"; - var $link = this.$el.find('.oe_form_uri') - .unbind('click') - .html(link); - if (! this.options.no_open) - $link.click(function () { - var context = self.build_context().eval(); - var model_obj = new Model(self.field.relation); - model_obj.call('get_formview_action', [self.get("value"), context]).then(function(action){ - self.do_action(action); - }); - return false; - }); - $(".oe_form_m2o_follow", this.$el).html(follow); + this.$el.html(_.escape(str).split("\n").join("<br/>")); + // Define callback to perform when clicking on the field + if (!this.options.no_open) { + // Remove potential previously added event handler + this.$el.off('click'); + // Ensure that the callback is performed only once even with multiple clicks + var execute_formview_action_once = _.once(this.execute_formview_action.bind(this)); + this.$el.click(function (ev) { + ev.preventDefault(); + execute_formview_action_once(); + }); + } } }, + execute_formview_action: function() { + var self = this; + var context = self.build_context().eval(); + (new Model(self.field.relation)).call('get_formview_action', [self.get("value"), context]).then(function(action) { + self.do_action(action); + }); + }, set_value: function(value_) { if (value_ instanceof Array) { this.display_value = {}; @@ -418,11 +409,6 @@ var FieldMany2One = common.AbstractField.extend(common.CompletionFieldMixin, com this.no_ed = false; return res; }, - set_dimensions: function (height, width) { - this._super(height, width); - if (!this.get("effective_readonly") && this.$input) - this.$input.css('height', height); - } }); /** @@ -586,40 +572,39 @@ var AbstractManyField = common.AbstractField.extend({ _.each(command_list, function(command) { self.mutex.exec(function() { var id = command[1]; - if (!id || _.isString(id) || _.isNumber(id)) { - switch (command[0]) { - case COMMANDS.CREATE: - var data = _.clone(command[2]); - delete data.id; - return dataset.create(data, internal_options).then(function (id) { + switch (command[0]) { + case COMMANDS.CREATE: + var data = _.clone(command[2]); + delete data.id; + return dataset.create(data, internal_options).then(function (id) { + dataset.ids.push(id); + res = id; + }); + case COMMANDS.UPDATE: + return dataset.write(id, command[2], internal_options).then(function () { + if (dataset.ids.indexOf(id) === -1) { dataset.ids.push(id); res = id; - }); - case COMMANDS.UPDATE: - return dataset.write(id, command[2], internal_options).then(function () { - if (dataset.ids.indexOf(id) === -1) { - dataset.ids.push(id); - res = id; - } - }); - case COMMANDS.FORGET: - return dataset.unlink([id]); - case COMMANDS.DELETE: - return dataset.unlink([id]); - case COMMANDS.LINK_TO: - if (dataset.ids.indexOf(id) === -1) { - return dataset.add_ids([id], internal_options); } - return; - case COMMANDS.DELETE_ALL: - return dataset.reset_ids([], {keep_read_data: true}); - case COMMANDS.REPLACE_WITH: - dataset.ids = []; - return dataset.alter_ids(command[2], internal_options); - } + }); + case COMMANDS.FORGET: + return dataset.unlink([id]); + case COMMANDS.DELETE: + return dataset.unlink([id]); + case COMMANDS.LINK_TO: + if (dataset.ids.indexOf(id) === -1) { + return dataset.add_ids([id], internal_options); + } + return; + case COMMANDS.DELETE_ALL: + return dataset.reset_ids([], {keep_read_data: true}); + case COMMANDS.REPLACE_WITH: + dataset.ids = []; + return dataset.alter_ids(command[2], internal_options); + default: + throw new Error("send_commands to '"+self.name+"' receive a non command value." + + "\n" + JSON.stringify(command_list)); } - throw new Error("send_commands to '"+self.name+"' receive a non command value." + - "\n" + JSON.stringify(command_list)); }); }); @@ -660,10 +645,6 @@ var AbstractManyField = common.AbstractField.extend({ if (record.to_create) { command_list.push(COMMANDS.create(values)); } else { - if (index === -1) { - // because the UPDATE below does not imply LINK_TO - command_list.push(COMMANDS.link_to(id)); - } command_list.push(COMMANDS.update(record.id, values)); } return; @@ -724,13 +705,12 @@ var FieldX2Many = AbstractManyField.extend({ }, start: function() { this._super.apply(this, arguments); - this.$el.addClass('oe_form_field'); - var self = this; this.load_views(); var destroy = function() { self.is_loaded = self.is_loaded.then(function() { + self.renderElement(); self.viewmanager.destroy(); return $.when(self.load_views()).done(function() { self.reload_current_view(); @@ -828,7 +808,8 @@ var FieldX2Many = AbstractManyField.extend({ }); }); $.async_when().done(function () { - self.alive( self.viewmanager.appendTo(self.$el)); + self.$el.addClass('o_view_manager_content'); + self.alive(self.viewmanager.attachTo(self.$el)); }); return def; }, @@ -881,6 +862,9 @@ var FieldX2Many = AbstractManyField.extend({ } return true; }, + is_false: function() { + return false; + }, }); var X2ManyDataSet = data.BufferedDataSet.extend({ @@ -891,10 +875,15 @@ var X2ManyDataSet = data.BufferedDataSet.extend({ self.context.add(context); }); return this.context; - } + }, }); var X2ManyViewManager = ViewManager.extend({ + custom_events: { + // Catch event scrollTo to prevent scrolling to the top when using the + // pager of List and Kanban views in One2Many fields + 'scrollTo': function() {}, + }, init: function(parent, dataset, views, flags, x2many_views) { // By default, render buttons and pager in X2M fields, but no sidebar flags = _.extend({}, flags, { @@ -984,6 +973,15 @@ var X2ManyListView = ListView.extend({ }); return valid; }, + render_pager: function($node, options) { + options = _.extend(options || {}, { + single_page_hidden: true, + }); + this._super($node, options); + }, + display_nocontent_helper: function () { + return false; + }, }); /** @@ -1008,7 +1006,7 @@ var X2ManyList = ListView.List.extend({ var $cell = $('<td>', { colspan: columns, - 'class': 'oe_form_field_x2many_list_row_add' + 'class': 'o_form_field_x2many_list_row_add' }).append( $('<a>', {href: '#'}).text(_t("Add an item")) .click(function (e) { @@ -1037,7 +1035,6 @@ var X2ManyList = ListView.List.extend({ }); var One2ManyListView = X2ManyListView.extend({ - _template: 'One2Many.listview', init: function () { this._super.apply(this, arguments); this.options = _.extend(this.options, { @@ -1177,7 +1174,7 @@ var One2ManyListView = X2ManyListView.extend({ var click_outside = ($target.closest('.ui-autocomplete,.btn,.modal-backdrop').length === 0); // Check if click inside the current list editable - var $o2m = $target.closest(".oe_list_editable"); + var $o2m = $target.closest(".o_list_editable"); if($o2m.length && $o2m[0] === this.el) { click_outside = false; } @@ -1251,39 +1248,19 @@ var One2ManyGroups = ListView.Groups.extend({ } }); -var One2ManyFormView = FormView.extend({ - form_template: 'One2Many.formview', - load_form: function(data) { - this._super(data); - var self = this; - this.$buttons.find('button.oe_form_button_create').click(function() { - self.save().done(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); - } - } -}); - var FieldOne2Many = FieldX2Many.extend({ init: function() { this._super.apply(this, arguments); this.x2many_views = { - form: One2ManyFormView, kanban: core.view_registry.get('one2many_kanban'), list: One2ManyListView, }; }, start: function() { - this.$el.addClass('oe_form_field_one2many'); + this.$el.addClass('o_form_field_one2many'); return this._super.apply(this, arguments); }, commit_value: function() { - var self = this; var view = this.viewmanager.active_view; if(view.type === "list" && view.controller.editable()) { return this.mutex.def.then(function () { @@ -1357,7 +1334,7 @@ var FieldMany2Many = FieldX2Many.extend({ }; }, start: function() { - this.$el.addClass('oe_form_field_many2many'); + this.$el.addClass('o_form_field_many2many'); return this._super.apply(this, arguments); } }); @@ -1373,7 +1350,7 @@ var FieldMany2ManyKanban = FieldMany2Many.extend({ }); var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, common.ReinitializeFieldMixin, { - className: "oe_form_field o_form_field_many2manytags", + className: "o_form_field_many2manytags", tag_template: "FieldMany2ManyTag", events: { @@ -1435,7 +1412,6 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c } }, get_render_data: function(ids){ - var self = this; this.dataset.cancel_read(); var fields = this.fields.color ? ['display_name', 'name', 'color'] : ['display_name', 'name']; // TODO master: remove useless 'name' return this.dataset.read_ids(ids, fields); @@ -1475,26 +1451,30 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c } return false; }, - set_dimensions: function (height, width) { - this._super(height, width); - var $input = this.$('input'); - if (!this.get("effective_readonly") && $input) { - $input.css('height', height); + set_dimensions: function(height, width) { + if(this.many2one) { + this.many2one.$el.css('height', 'auto'); + } + this.$el.css({ + width: width, + minHeight: height, + }); + if(this.many2one) { + this.many2one.$el.css('height', this.$el.height()); } }, open_color_picker: function(ev){ - this.mutex.exec(function(){ - if (this.fields.color) { - this.$color_picker = $(QWeb.render('FieldMany2ManyTag.colorpicker', { - 'widget': this, - 'tag_id': $(ev.currentTarget).data('id'), - })); - $(ev.currentTarget).append(this.$color_picker); - this.$color_picker.dropdown('toggle'); - this.$color_picker.attr("tabindex", 1).focus(); - } - }.bind(this)); + if (this.fields.color) { + this.$color_picker = $(QWeb.render('FieldMany2ManyTag.colorpicker', { + 'widget': this, + 'tag_id': $(ev.currentTarget).data('id'), + })); + + $(ev.currentTarget).append(this.$color_picker); + this.$color_picker.dropdown('toggle'); + this.$color_picker.attr("tabindex", 1).focus(); + } }, close_color_picker: function(){ this.$color_picker.remove(); @@ -1513,24 +1493,76 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c var old_color = tag.data('color'); tag.removeClass('o_tag_color_' + old_color); tag.data('color', color); - tag.addClass('o_tag_color_' + color); + tag.addClass('o_tag_color_' + color); }); }, - }); /** * Widget for (many2many field) to upload one or more file in same time and display in list. * The user can delete his files. - * Options on attribute ; "blockui" {Boolean} block the UI or not - * during the file is uploading + * Options on attribute ; "blockui" {Boolean} block the UI or not during the file is uploading */ var FieldMany2ManyBinaryMultiFiles = AbstractManyField.extend(common.ReinitializeFieldMixin, { template: "FieldBinaryFileUploader", + events: { + 'click .o_attach': function(e) { + this.$('.o_form_input_file').click(); + }, + 'change .o_form_input_file': function(e) { + e.stopPropagation(); + + var $target = $(e.target); + var value = $target.val(); + + if(value !== '') { + if(this.data[0] && this.data[0].upload) { // don't upload more of one file in same time + return false; + } + + var filename = value.replace(/.*[\\\/]/, ''); + for(var id in this.get('value')) { + // if the files exits, delete the file before upload (if it's a new file) + if(this.data[id] && (this.data[id].filename || this.data[id].name) == filename && !this.data[id].no_unlink) { + this.ds_file.unlink([id]); + } + } + + if(this.node.attrs.blockui > 0) { // block UI or not + framework.blockUI(); + } + + // TODO : unactivate send on wizard and form + + // submit file + this.$('form.o_form_binary_form').submit(); + this.$(".oe_fileupload").hide(); + // add file on data result + this.data[0] = { + id: 0, + name: filename, + filename: filename, + url: '', + upload: true, + }; + } + }, + 'click .oe_delete': function(e) { + e.preventDefault(); + e.stopPropagation(); + + var file_id = $(e.currentTarget).data("id"); + if(file_id) { + var files = _.without(this.get('value'), file_id); + if(!this.data[file_id].no_unlink) { + this.ds_file.unlink([file_id]); + } + this.set({'value': files}); + } + }, + }, init: function(field_manager, node) { - this._super(field_manager, node); - this.field_manager = field_manager; - this.node = node; + this._super.apply(this, arguments); this.session = session; if(this.field.type != "many2many" || this.field.relation != 'ir.attachment') { throw _.str.sprintf(_t("The type of the field '%s' must be a many2many field with a relation to 'ir.attachment' model."), this.field.string); @@ -1541,40 +1573,39 @@ var FieldMany2ManyBinaryMultiFiles = AbstractManyField.extend(common.Reinitializ this.fileupload_id = _.uniqueId('oe_fileupload_temp'); $(window).on(this.fileupload_id, _.bind(this.on_file_loaded, this)); }, - initialize_content: function() { - this.$el.on('change', 'input.o_form_input_file', this.on_file_change ); - }, - get_file_url: function (attachment) { + get_file_url: function(attachment) { return '/web/content/' + attachment.id + '?download=true'; }, - read_name_values : function () { + read_name_values : function() { var self = this; // don't reset know values var ids = this.get('value'); - var _value = _.filter(ids, function (id) { return typeof self.data[id] == 'undefined'; } ); + var _value = _.filter(ids, function(id) { return self.data[id] === undefined; }); // send request for get_name - if (_value.length) { - return this.ds_file.call('read', [_value, ['id', 'name', 'datas_fname', 'mimetype']]).then(function (datas) { - _.each(datas, function (data) { - data.no_unlink = true; - data.url = self.get_file_url(data); - self.data[data.id] = data; - }); - return ids; - }); + if(_value.length) { + return this.ds_file.call('read', [_value, ['id', 'name', 'datas_fname', 'mimetype']]) + .then(process_data); } else { return $.when(ids); } + + function process_data(datas) { + _.each(datas, function(data) { + data.no_unlink = true; + data.url = self.get_file_url(data); + self.data[data.id] = data; + }); + return ids; + } }, - render_value: function () { + render_value: function() { var self = this; this.read_name_values().then(function (ids) { - var render = $(QWeb.render('FieldBinaryFileUploader.files', {'widget': self, 'values': ids})); - render.on('click', '.oe_delete', _.bind(self.on_file_delete, self)); - self.$('.oe_placeholder_files, .oe_attachments').replaceWith( render ); + self.$('.oe_placeholder_files, .oe_attachments') + .replaceWith($(QWeb.render('FieldBinaryFileUploader.files', {'widget': self, 'values': ids}))); // reinit input type file - var $input = self.$('input.o_form_input_file'); + var $input = self.$('.o_form_input_file'); $input.after($input.clone(true)).remove(); self.$(".oe_fileupload").show(); @@ -1587,77 +1618,26 @@ var FieldMany2ManyBinaryMultiFiles = AbstractManyField.extend(common.Reinitializ }); }); }, - on_file_change: function (event) { - event.stopPropagation(); - var self = this; - var $target = $(event.target); - if ($target.val() !== '') { - var filename = $target.val().replace(/.*[\\\/]/,''); - // don't uplode more of one file in same time - if (self.data[0] && self.data[0].upload ) { - return false; - } - for (var id in this.get('value')) { - // if the files exits, delete the file before upload (if it's a new file) - if (self.data[id] && (self.data[id].filename || self.data[id].name) == filename && !self.data[id].no_unlink ) { - self.ds_file.unlink([id]); - } - } - - // block UI or not - if(this.node.attrs.blockui>0) { - framework.blockUI(); - } - - // TODO : unactivate send on wizard and form - - // submit file - this.$('form.o_form_binary_form').submit(); - this.$(".oe_fileupload").hide(); - // add file on data result - this.data[0] = { - 'id': 0, - 'name': filename, - 'filename': filename, - 'url': '', - 'upload': true - }; - } - }, - on_file_loaded: function (event, result) { - var files = this.get('value'); - - // unblock UI - if(this.node.attrs.blockui>0) { + on_file_loaded: function(e, result) { + if(this.node.attrs.blockui > 0) { // unblock UI framework.unblockUI(); } - if (result.error || !result.id ) { - this.do_warn( _t('Uploading Error'), result.error); + if(result.error || !result.id) { + this.do_warn(_t('Uploading Error'), result.error); delete this.data[0]; } else { - if (this.data[0] && this.data[0].filename == result.filename && this.data[0].upload) { + if(this.data[0] && this.data[0].filename === result.filename && this.data[0].upload) { delete this.data[0]; } result.url = this.get_file_url(result); this.data[result.id] = result; var values = _.clone(this.get('value')); values.push(result.id); - this.set({'value': values}); + this.set({value: values}); } this.render_value(); }, - on_file_delete: function (event) { - event.stopPropagation(); - var file_id=$(event.target).closest('.oe_delete').data("id"); - if (file_id) { - var files = _.filter(this.get('value'), function (id) {return id != file_id;}); - if(!this.data[file_id].no_unlink) { - this.ds_file.unlink([file_id]); - } - this.set({'value': files}); - } - }, }); /* @@ -1672,7 +1652,7 @@ var FieldMany2ManyCheckBoxes = AbstractManyField.extend(common.ReinitializeField this.set("records", []); this.field_manager.on("view_content_has_changed", this, function() { var domain = new data.CompoundDomain(this.build_domain()).eval(); - if (! _.isEqual(domain, this.get("domain"))) { + if (!_.isEqual(domain, this.get("domain"))) { this.set("domain", domain); } }); @@ -1694,18 +1674,22 @@ var FieldMany2ManyCheckBoxes = AbstractManyField.extend(common.ReinitializeField }); }, render_value: function() { - this.$().html(QWeb.render("FieldMany2ManyCheckBoxes", {widget: this})); - var inputs = this.$("input"); - inputs.change(_.bind(this.from_dom, this)); - if (this.get("effective_readonly")) - inputs.attr("disabled", "true"); + this.$el.html(QWeb.render("FieldMany2ManyCheckBoxes", {widget: this})); + var $inputs = this.$("input"); + $inputs.change(_.bind(this.from_dom, this)); + if (this.get("effective_readonly")) { + $inputs.attr("disabled", "true"); + } }, from_dom: function() { var new_value = this.$("input:checked").map(function() { return +$(this).data("record-id"); }).get(); - if (! _.isEqual(new_value, this.get("value"))) { + if (!_.isEqual(new_value, this.get("value"))) { this.internal_set_value(new_value); } - } + }, + is_false: function() { + return false; + }, }); core.form_widget_registry @@ -1718,9 +1702,13 @@ core.form_widget_registry .add('many2many_binary', FieldMany2ManyBinaryMultiFiles) .add('many2many_checkboxes', FieldMany2ManyCheckBoxes); +core.one2many_view_registry + .add('list', One2ManyListView); + return { FieldMany2ManyTags: FieldMany2ManyTags, AbstractManyField: AbstractManyField, + FieldMany2One: FieldMany2One, }; }); |
