From f18695615ca124254106270c5d00bd790ca79ad6 Mon Sep 17 00:00:00 2001 From: msh-openerp Date: Wed, 4 Apr 2012 14:22:43 +0530 Subject: [FIX]Fixed the issue of translation in data_import. bzr revid: msh@tinyerp.com-20120404085243-69cx9zr4915eb6kz --- addons/web/static/src/js/data_import.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web/static/src/js/data_import.js') diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 83eea2cccbb..2fa43511034 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -353,7 +353,7 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ var missing_fields = _.difference(this.required_fields, selected_fields); if (missing_fields.length) { - this.$element.find("#result").before('
*Required Fields are not selected : ' + missing_fields + '.
'); + this.$element.find("#result").before('
' + _t("*Required Fields are not selected :") + missing_fields + '.
'); return false; } return true; -- cgit v1.2.3 From 9d95952436ce9a79c39b78997554f8720f30eb6b Mon Sep 17 00:00:00 2001 From: msh-openerp Date: Wed, 16 May 2012 17:39:46 +0530 Subject: [FIX]Refixed the translation issue in import. bzr revid: msh@tinyerp.com-20120516120946-bxroqa9tiwhqxbpo --- addons/web/static/src/js/data_import.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web/static/src/js/data_import.js') diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 2fa43511034..838652bfb54 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -330,7 +330,7 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ if (_.isEmpty(duplicates)) { this.toggle_import_button(required_valid); } else { - var $err = $('
Destination fields should only be selected once, some fields are selected more than once:
').insertBefore(this.$element.find('#result')); + var $err = $('
'+_t("Destination fields should only be selected once, some fields are selected more than once:")+'
').insertBefore(this.$element.find('#result')); var $dupes = $('
').appendTo($err); _(duplicates).each(function(elements, value) { $('
').text(value).appendTo($dupes); -- cgit v1.2.3 From 6379e7899c785aa8ad3ce289891a1417431fb18a Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 25 May 2012 09:08:59 +0200 Subject: [FIX] data_import: allow importing m2o via name_search() on top of their XML ID We do default to exporting the XML ID, but there are many cases where completely new data needs to be imported and there is no XML ID available to do so. In that case allowing name_search() to be used as in 6.0 is a life-saver. This patch simply makes the m2o field itself visible during import, so users can use it in their CSV file or manually select it. Some trivial examples: - you need to import 2000 new leads with their countries, obviously you can't guess that base.be should be used for country Belgium - you need to update 2000 unassigned leads in the system and assign them to some of the salemen... but you don't have their XML IDs and even if you had, the match is quite hard to do. bzr revid: odo@openerp.com-20120525070859-y4q3bnamvag2pzcq --- addons/web/static/src/js/data_import.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'addons/web/static/src/js/data_import.js') diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 838652bfb54..1d191d03f1f 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -133,6 +133,10 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ switch (field.type) { case 'many2many': case 'many2one': + // push a copy for the bare many2one field, to allow importing + // using name_search too - even if we default to exporting the XML ID + var many2one_field = _.extend({}, f) + parent.fields.push(many2one_field); f.name += '/id'; break; case 'one2many': -- cgit v1.2.3 From 6700a95d7971422418c0991aa3cb3465d73f595e Mon Sep 17 00:00:00 2001 From: Xavier ALT Date: Wed, 30 May 2012 12:16:08 +0200 Subject: [FIX] web: data import: fields matching have to be done first on exactfieldname, then only on string bzr revid: xal@openerp.com-20120530101608-8al6jw332oz0v2c0 --- addons/web/static/src/js/data_import.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'addons/web/static/src/js/data_import.js') diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 1d191d03f1f..6901c16037e 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -267,8 +267,13 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ f = _(fields).detect(function (field) { // TODO: levenshtein between header and field.string return field.name === name - || field.string.toLowerCase() === name.toLowerCase(); }); + if (!f) { + f = _(fields).detect(function (field) { + // TODO: levenshtein between header and field.string + return field.string.toLowerCase() === name.toLowerCase(); + }); + } if (f) { return f.name; } // if ``name`` is a path (o2m), we need to recurse through its .fields @@ -279,8 +284,13 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ f = _(fields).detect(function (field) { // field.name for o2m is $foo/id, so we want to match on id return field.id === column_name - || field.string.toLowerCase() === column_name.toLowerCase() }); + if (!f) { + f = _(fields).detect(function (field) { + // field.name for o2m is $foo/id, so we want to match on id + return field.string.toLowerCase() === column_name.toLowerCase() + }); + } if (!f) { return undefined; } // if we found a matching field for the first path section, recurse in -- cgit v1.2.3 From 3fa52c12b793d566b703b6e0dd1ed09caf35fd28 Mon Sep 17 00:00:00 2001 From: Xavier ALT Date: Wed, 30 May 2012 12:17:15 +0200 Subject: [FIX] web: data import: correctly handle 'required' many2one - user can provided any of base fieldname or with the '/id' bzr revid: xal@openerp.com-20120530101715-oe86b3vk6qynp29e --- addons/web/static/src/js/data_import.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'addons/web/static/src/js/data_import.js') diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 6901c16037e..06386321c50 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -55,7 +55,8 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ .filter(function (field) { return field.required && !_.include(self.fields_with_defaults, field.id); }) - .pluck('name') + .pluck('id') + .uniq() .value(); convert_fields(self); self.all_fields.sort(); @@ -360,9 +361,24 @@ openerp.web.DataImport = openerp.web.Dialog.extend({ check_required: function() { if (!this.required_fields.length) { return true; } + // get real field name (stripping the trailing "/id" for many2one field). + // For many2one fields, user can use any of the two fields: + // - base field name for name_search() import + // - with the "/id" for direct referencing + // In both case we must check if field is required only based on his + // real name. + var get_field_real_id = _.bind(function(field_name) { + var f = _.detect(this.fields, function(field) { + return field.name === field_name + }); + if (!f) { return field_name }; + return f.id; + }, this); + var selected_fields = _(this.$element.find('.sel_fields').get()).chain() .pluck('value') .compact() + .map(get_field_real_id) .value(); var missing_fields = _.difference(this.required_fields, selected_fields); -- cgit v1.2.3 From ce7fb5bb37b969528d8cc24d5493163b492361a3 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 27 Jun 2012 16:12:49 +0200 Subject: [CHG] Ashes to ashes, dashes to underscores. bzr revid: fme@openerp.com-20120627141249-o10e2htxqtio72l7 --- addons/web/static/src/js/data_import.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'addons/web/static/src/js/data_import.js') diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index bc98d8a1c10..6059f292df9 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -68,7 +68,7 @@ instance.web.DataImport = instance.web.Dialog.extend({ this.open({ buttons: [ {text: _t("Close"), click: function() { self.destroy(); }}, - {text: _t("Import File"), click: function() { self.do_import(); }, 'class': 'oe-dialog-import-button'} + {text: _t("Import File"), click: function() { self.do_import(); }, 'class': 'oe_import_dialog_button'} ], close: function(event, ui) { self.destroy(); @@ -78,7 +78,7 @@ instance.web.DataImport = instance.web.Dialog.extend({ this.$element.find('#csvfile').change(this.on_autodetect_data); this.$element.find('fieldset').change(this.on_autodetect_data); this.$element.delegate('fieldset legend', 'click', function() { - $(this).parent().toggleClass('oe-closed'); + $(this).parent().toggleClass('oe_closed'); }); this.ready.push(new instance.web.DataSet(this, this.model).call( 'fields_get', [], function (fields) { @@ -157,7 +157,7 @@ instance.web.DataImport = instance.web.Dialog.extend({ }, toggle_import_button: function (newstate) { instance.web.dialog(this.$element, 'widget') - .find('.oe-dialog-import-button') + .find('.oe_import_dialog_button') .button('option', 'disabled', !newstate); }, do_import: function() { @@ -202,7 +202,7 @@ instance.web.DataImport = instance.web.Dialog.extend({ if (results['error']) { result_node.append(QWeb.render('ImportView.error', { 'error': results['error']})); - this.$element.find('fieldset').removeClass('oe-closed'); + this.$element.find('fieldset').removeClass('oe_closed'); return; } if (results['success']) { @@ -224,11 +224,11 @@ instance.web.DataImport = instance.web.Dialog.extend({ : with_headers ? results.records.slice(1) : results.records })); - this.$element.find('fieldset').addClass('oe-closed'); + this.$element.find('fieldset').addClass('oe_closed'); } - this.$element.find('form').removeClass('oe-import-no-result'); + this.$element.find('form').removeClass('oe_import_no_result'); - this.$element.delegate('.oe-m2o-drop-down-button', 'click', function () { + this.$element.delegate('.oe_m2o_drop_down_button', 'click', function () { $(this).prev('input').focus(); }); -- cgit v1.2.3 From 2c57c15491395e9edd0ad0cebcf3b12f6e02ee03 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 2 Aug 2012 16:46:23 +0200 Subject: [IMP] Mass rename \t to 4 spaces bzr revid: nicolas.vanhoren@openerp.com-20120802144623-ykl5te005ytnv584 --- addons/web/static/src/js/data_import.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web/static/src/js/data_import.js') diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 6059f292df9..620878569ce 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -156,7 +156,7 @@ instance.web.DataImport = instance.web.Dialog.extend({ }); }, toggle_import_button: function (newstate) { - instance.web.dialog(this.$element, 'widget') + instance.web.dialog(this.$element, 'widget') .find('.oe_import_dialog_button') .button('option', 'disabled', !newstate); }, -- cgit v1.2.3 From 5e338c591ac76f57453563792fe20e9a20f31edc Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Fri, 24 Aug 2012 20:27:07 +0200 Subject: [IMP] made a whole-application replace of $element by $el bzr revid: nicolas.vanhoren@openerp.com-20120824182707-vt91ef40ieeudwyw --- addons/web/static/src/js/data_import.js | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'addons/web/static/src/js/data_import.js') diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js index 620878569ce..3c677b0ec26 100644 --- a/addons/web/static/src/js/data_import.js +++ b/addons/web/static/src/js/data_import.js @@ -75,9 +75,9 @@ instance.web.DataImport = instance.web.Dialog.extend({ } }); this.toggle_import_button(false); - this.$element.find('#csvfile').change(this.on_autodetect_data); - this.$element.find('fieldset').change(this.on_autodetect_data); - this.$element.delegate('fieldset legend', 'click', function() { + this.$el.find('#csvfile').change(this.on_autodetect_data); + this.$el.find('fieldset').change(this.on_autodetect_data); + this.$el.delegate('fieldset legend', 'click', function() { $(this).parent().toggleClass('oe_closed'); }); this.ready.push(new instance.web.DataSet(this, this.model).call( @@ -156,19 +156,19 @@ instance.web.DataImport = instance.web.Dialog.extend({ }); }, toggle_import_button: function (newstate) { - instance.web.dialog(this.$element, 'widget') + instance.web.dialog(this.$el, 'widget') .find('.oe_import_dialog_button') .button('option', 'disabled', !newstate); }, do_import: function() { - if(!this.$element.find('#csvfile').val()) { return; } - var lines_to_skip = parseInt(this.$element.find('#csv_skip').val(), 10); - var with_headers = this.$element.find('#file_has_headers').prop('checked'); + if(!this.$el.find('#csvfile').val()) { return; } + var lines_to_skip = parseInt(this.$el.find('#csv_skip').val(), 10); + var with_headers = this.$el.find('#file_has_headers').prop('checked'); if (!lines_to_skip && with_headers) { lines_to_skip = 1; } var indices = [], fields = []; - this.$element.find(".sel_fields").each(function(index, element) { + this.$el.find(".sel_fields").each(function(index, element) { var val = element.value; if (!val) { return; @@ -177,7 +177,7 @@ instance.web.DataImport = instance.web.Dialog.extend({ fields.push(val); }); - jsonp(this.$element.find('#import_data'), { + jsonp(this.$el.find('#import_data'), { url: '/web/import/import_data', data: { model: this.model, @@ -190,19 +190,19 @@ instance.web.DataImport = instance.web.Dialog.extend({ }, this.on_import_results); }, on_autodetect_data: function() { - if(!this.$element.find('#csvfile').val()) { return; } - jsonp(this.$element.find('#import_data'), { + if(!this.$el.find('#csvfile').val()) { return; } + jsonp(this.$el.find('#import_data'), { url: '/web/import/detect_data' }, this.on_import_results); }, on_import_results: function(results) { - this.$element.find('#result').empty(); - var headers, result_node = this.$element.find("#result"); + this.$el.find('#result').empty(); + var headers, result_node = this.$el.find("#result"); if (results['error']) { result_node.append(QWeb.render('ImportView.error', { 'error': results['error']})); - this.$element.find('fieldset').removeClass('oe_closed'); + this.$el.find('fieldset').removeClass('oe_closed'); return; } if (results['success']) { @@ -214,8 +214,8 @@ instance.web.DataImport = instance.web.Dialog.extend({ } if (results['records']) { - var lines_to_skip = parseInt(this.$element.find('#csv_skip').val(), 10), - with_headers = this.$element.find('#file_has_headers').prop('checked'); + var lines_to_skip = parseInt(this.$el.find('#csv_skip').val(), 10), + with_headers = this.$el.find('#file_has_headers').prop('checked'); headers = with_headers ? results.records[0] : null; result_node.append(QWeb.render('ImportView.result', { @@ -224,17 +224,17 @@ instance.web.DataImport = instance.web.Dialog.extend({ : with_headers ? results.records.slice(1) : results.records })); - this.$element.find('fieldset').addClass('oe_closed'); + this.$el.find('fieldset').addClass('oe_closed'); } - this.$element.find('form').removeClass('oe_import_no_result'); + this.$el.find('form').removeClass('oe_import_no_result'); - this.$element.delegate('.oe_m2o_drop_down_button', 'click', function () { + this.$el.delegate('.oe_m2o_drop_down_button', 'click', function () { $(this).prev('input').focus(); }); var self = this; this.ready.then(function () { - var $fields = self.$element.find('.sel_fields').bind('blur', function () { + var $fields = self.$el.find('.sel_fields').bind('blur', function () { if (this.value && !_(self.all_fields).contains(this.value)) { this.value = ''; } @@ -315,9 +315,9 @@ instance.web.DataImport = instance.web.Dialog.extend({ find_duplicate_fields: function() { // Maps values to DOM nodes, in order to discover duplicates var values = {}, duplicates = {}; - this.$element.find(".sel_fields").each(function(index, element) { + this.$el.find(".sel_fields").each(function(index, element) { var value = element.value; - var $element = $(element).removeClass('duplicate_fld'); + var $el = $(element).removeClass('duplicate_fld'); if (!value) { return; } if (!(value in values)) { @@ -329,13 +329,13 @@ instance.web.DataImport = instance.web.Dialog.extend({ } else { duplicates[value] = [same_valued_field, element]; } - $element.add(same_valued_field).addClass('duplicate_fld'); + $el.add(same_valued_field).addClass('duplicate_fld'); } }); return duplicates; }, on_check_field_values: function () { - this.$element.find("#message, #msg").remove(); + this.$el.find("#message, #msg").remove(); var required_valid = this.check_required(); @@ -343,7 +343,7 @@ instance.web.DataImport = instance.web.Dialog.extend({ if (_.isEmpty(duplicates)) { this.toggle_import_button(required_valid); } else { - var $err = $('
'+_t("Destination fields should only be selected once, some fields are selected more than once:")+'
').insertBefore(this.$element.find('#result')); + var $err = $('
'+_t("Destination fields should only be selected once, some fields are selected more than once:")+'
').insertBefore(this.$el.find('#result')); var $dupes = $('
').appendTo($err); _(duplicates).each(function(elements, value) { $('
').text(value).appendTo($dupes); @@ -372,7 +372,7 @@ instance.web.DataImport = instance.web.Dialog.extend({ return f.id; }; - var selected_fields = _(this.$element.find('.sel_fields').get()).chain() + var selected_fields = _(this.$el.find('.sel_fields').get()).chain() .pluck('value') .compact() .map(resolve_field_id) @@ -380,13 +380,13 @@ instance.web.DataImport = instance.web.Dialog.extend({ var missing_fields = _.difference(this.required_fields, selected_fields); if (missing_fields.length) { - this.$element.find("#result").before('
' + _t("*Required Fields are not selected :") + missing_fields + '.
'); + this.$el.find("#result").before('
' + _t("*Required Fields are not selected :") + missing_fields + '.
'); return false; } return true; }, destroy: function() { - this.$element.remove(); + this.$el.remove(); this._super(); } }); -- cgit v1.2.3 From 5848e72d421d0c63a0a9bd3b254b6e4aa35d5cb6 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 11 Sep 2012 08:36:07 +0200 Subject: [REM] import from core, moving to module bzr revid: xmo@openerp.com-20120911063607-xvhyjqohptynro30 --- addons/web/static/src/js/data_import.js | 393 -------------------------------- 1 file changed, 393 deletions(-) delete mode 100644 addons/web/static/src/js/data_import.js (limited to 'addons/web/static/src/js/data_import.js') diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js deleted file mode 100644 index 3c677b0ec26..00000000000 --- a/addons/web/static/src/js/data_import.js +++ /dev/null @@ -1,393 +0,0 @@ -openerp.web.data_import = function(instance) { -var QWeb = instance.web.qweb, - _t = instance.web._t; -/** - * Safari does not deal well at all with raw JSON data being returned. As a - * result, we're going to cheat by using a pseudo-jsonp: instead of getting - * JSON data in the iframe, we're getting a ``script`` tag which consists of a - * function call and the returned data (the json dump). - * - * The function is an auto-generated name bound to ``window``, which calls - * back into the callback provided here. - * - * @param {Object} form the form element (DOM or jQuery) to use in the call - * @param {Object} attributes jquery.form attributes object - * @param {Function} callback function to call with the returned data - */ -function jsonp(form, attributes, callback) { - attributes = attributes || {}; - var options = {jsonp: _.uniqueId('import_callback_')}; - window[options.jsonp] = function () { - delete window[options.jsonp]; - callback.apply(null, arguments); - }; - if ('data' in attributes) { - _.extend(attributes.data, options); - } else { - _.extend(attributes, {data: options}); - } - $(form).ajaxSubmit(attributes); -} - -instance.web.DataImport = instance.web.Dialog.extend({ - template: 'ImportDataView', - dialog_title: {toString: function () { return _t("Import Data"); }}, - init: function(parent, dataset){ - var self = this; - this._super(parent, {}); - this.model = parent.model; - this.fields = []; - this.all_fields = []; - this.fields_with_defaults = []; - this.required_fields = null; - - var convert_fields = function (root, prefix) { - prefix = prefix || ''; - _(root.fields).each(function (f) { - self.all_fields.push(prefix + f.name); - if (f.fields) { - convert_fields(f, prefix + f.id + '/'); - } - }); - }; - this.ready = $.Deferred.queue().then(function () { - self.required_fields = _(self.fields).chain() - .filter(function (field) { - return field.required && - !_.include(self.fields_with_defaults, field.id); }) - .pluck('id') - .uniq() - .value(); - convert_fields(self); - self.all_fields.sort(); - }); - }, - start: function() { - var self = this; - this._super(); - this.open({ - buttons: [ - {text: _t("Close"), click: function() { self.destroy(); }}, - {text: _t("Import File"), click: function() { self.do_import(); }, 'class': 'oe_import_dialog_button'} - ], - close: function(event, ui) { - self.destroy(); - } - }); - this.toggle_import_button(false); - this.$el.find('#csvfile').change(this.on_autodetect_data); - this.$el.find('fieldset').change(this.on_autodetect_data); - this.$el.delegate('fieldset legend', 'click', function() { - $(this).parent().toggleClass('oe_closed'); - }); - this.ready.push(new instance.web.DataSet(this, this.model).call( - 'fields_get', [], function (fields) { - self.graft_fields(fields); - self.ready.push(new instance.web.DataSet(self, self.model) - .default_get(_.pluck(self.fields, 'id')).then(function (fields) { - _.each(fields, function(val, key) { - if (val) { - self.fields_with_defaults.push(key); - } - }); - }) - ) - })); - }, - graft_fields: function (fields, parent, level) { - parent = parent || this; - level = level || 0; - - var self = this; - if (level === 0) { - parent.fields.push({ - id: 'id', - name: 'id', - string: _t('External ID'), - required: false - }); - } - _(fields).each(function (field, field_name) { - // Ignore spec for id field - // Don't import function fields (function and related) - 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, - string: field.string, - required: field.required - }; - - switch (field.type) { - case 'many2many': - case 'many2one': - // push a copy for the bare many2one field, to allow importing - // using name_search too - even if we default to exporting the XML ID - var many2one_field = _.extend({}, f) - parent.fields.push(many2one_field); - f.name += '/id'; - break; - case 'one2many': - f.name += '/id'; - f.fields = []; - // only fetch sub-fields to a depth of 2 levels - if (level < 2) { - self.ready.push(new instance.web.DataSet(self, field.relation).call( - 'fields_get', [], function (fields) { - self.graft_fields(fields, f, level+1); - })); - } - break; - } - parent.fields.push(f); - }); - }, - toggle_import_button: function (newstate) { - instance.web.dialog(this.$el, 'widget') - .find('.oe_import_dialog_button') - .button('option', 'disabled', !newstate); - }, - do_import: function() { - if(!this.$el.find('#csvfile').val()) { return; } - var lines_to_skip = parseInt(this.$el.find('#csv_skip').val(), 10); - var with_headers = this.$el.find('#file_has_headers').prop('checked'); - if (!lines_to_skip && with_headers) { - lines_to_skip = 1; - } - var indices = [], fields = []; - this.$el.find(".sel_fields").each(function(index, element) { - var val = element.value; - if (!val) { - return; - } - indices.push(index); - fields.push(val); - }); - - jsonp(this.$el.find('#import_data'), { - url: '/web/import/import_data', - data: { - model: this.model, - meta: JSON.stringify({ - skip: lines_to_skip, - indices: indices, - fields: fields - }) - } - }, this.on_import_results); - }, - on_autodetect_data: function() { - if(!this.$el.find('#csvfile').val()) { return; } - jsonp(this.$el.find('#import_data'), { - url: '/web/import/detect_data' - }, this.on_import_results); - }, - on_import_results: function(results) { - this.$el.find('#result').empty(); - var headers, result_node = this.$el.find("#result"); - - if (results['error']) { - result_node.append(QWeb.render('ImportView.error', { - 'error': results['error']})); - this.$el.find('fieldset').removeClass('oe_closed'); - return; - } - if (results['success']) { - if (this.getParent().getParent().active_view == "list") { - this.getParent().reload_content(); - } - this.destroy(); - return; - } - - if (results['records']) { - var lines_to_skip = parseInt(this.$el.find('#csv_skip').val(), 10), - with_headers = this.$el.find('#file_has_headers').prop('checked'); - headers = with_headers ? results.records[0] : null; - - result_node.append(QWeb.render('ImportView.result', { - 'headers': headers, - 'records': lines_to_skip ? results.records.slice(lines_to_skip) - : with_headers ? results.records.slice(1) - : results.records - })); - this.$el.find('fieldset').addClass('oe_closed'); - } - this.$el.find('form').removeClass('oe_import_no_result'); - - this.$el.delegate('.oe_m2o_drop_down_button', 'click', function () { - $(this).prev('input').focus(); - }); - - var self = this; - this.ready.then(function () { - var $fields = self.$el.find('.sel_fields').bind('blur', function () { - if (this.value && !_(self.all_fields).contains(this.value)) { - this.value = ''; - } - }).autocomplete({ - minLength: 0, - source: self.all_fields, - change: self.on_check_field_values - }).focus(function () { - $(this).autocomplete('search'); - }); - // Column auto-detection - _(headers).each(function (header, index) { - var field_name = self.match_column_to_field(header); - if (field_name) { - $fields.eq(index).val(field_name); - } - }); - self.on_check_field_values(); - }); - }, - /** - * Returns the name of the field (nested) matching the provided column name - * - * @param {String} name column name to look for - * @param {Array} [fields] fields to look into for the provided name - * @returns {String|undefined} - */ - match_column_to_field: function (name, fields) { - fields = fields || this.fields; - var f; - f = _(fields).detect(function (field) { - return field.name === name - }); - if (!f) { - f = _(fields).detect(function (field) { - // TODO: levenshtein between header and field.string - return field.string.toLowerCase() === name.toLowerCase(); - }); - } - if (f) { return f.name; } - - // if ``name`` is a path (o2m), we need to recurse through its .fields - var index = name.indexOf('/'); - if (index === -1) { return undefined; } - // Get the first path section, try to find the matching field - var column_name = name.substring(0, index); - f = _(fields).detect(function (field) { - // field.name for o2m is $foo/id, so we want to match on id - return field.id === column_name; - }); - if (!f) { - f = _(fields).detect(function (field) { - return field.string.toLowerCase() === column_name.toLowerCase(); - }); - } - if (!f) { return undefined; } - - // if we found a matching field for the first path section, recurse in - // its own .fields to try and get the rest of the path matched - var rest = this.match_column_to_field( - name.substring(index+1), f.fields); - if (!rest) { return undefined; } - return f.id + '/' + rest; - }, - /** - * Looks through all the field selections, and tries to find if two - * (or more) columns were matched to the same model field. - * - * Returns a map of the multiply-mapped fields to an array of offending - * columns (not actually columns, but the inputs containing the same field - * names). - * - * Also has the side-effect of marking the discovered inputs with the class - * ``duplicate_fld``. - * - * @returns {Object>} map of duplicate field matches to same-valued inputs - */ - find_duplicate_fields: function() { - // Maps values to DOM nodes, in order to discover duplicates - var values = {}, duplicates = {}; - this.$el.find(".sel_fields").each(function(index, element) { - var value = element.value; - var $el = $(element).removeClass('duplicate_fld'); - if (!value) { return; } - - if (!(value in values)) { - values[value] = element; - } else { - var same_valued_field = values[value]; - if (value in duplicates) { - duplicates[value].push(element); - } else { - duplicates[value] = [same_valued_field, element]; - } - $el.add(same_valued_field).addClass('duplicate_fld'); - } - }); - return duplicates; - }, - on_check_field_values: function () { - this.$el.find("#message, #msg").remove(); - - var required_valid = this.check_required(); - - var duplicates = this.find_duplicate_fields(); - if (_.isEmpty(duplicates)) { - this.toggle_import_button(required_valid); - } else { - var $err = $('
'+_t("Destination fields should only be selected once, some fields are selected more than once:")+'
').insertBefore(this.$el.find('#result')); - var $dupes = $('
').appendTo($err); - _(duplicates).each(function(elements, value) { - $('
').text(value).appendTo($dupes); - _(elements).each(function(element) { - var cell = $(element).closest('td'); - $('
').text(cell.parent().children().index(cell)).appendTo($dupes); - }); - }); - this.toggle_import_button(false); - } - - }, - check_required: function() { - var self = this; - if (!self.required_fields.length) { return true; } - - // Resolve field id based on column name, as there may be - // several ways to provide the value for a given field and - // thus satisfy the requirement. - // (e.g. m2o_id or m2o_id/id columns may be provided) - var resolve_field_id = function(column_name) { - var f = _.detect(self.fields, function(field) { - return field.name === column_name; - }); - if (!f) { return column_name; }; - return f.id; - }; - - var selected_fields = _(this.$el.find('.sel_fields').get()).chain() - .pluck('value') - .compact() - .map(resolve_field_id) - .value(); - - var missing_fields = _.difference(this.required_fields, selected_fields); - if (missing_fields.length) { - this.$el.find("#result").before('
' + _t("*Required Fields are not selected :") + missing_fields + '.
'); - return false; - } - return true; - }, - destroy: function() { - this.$el.remove(); - this._super(); - } -}); -}; -- cgit v1.2.3