From 43fcbe331812efb17afd28a414e607923ffd59ce Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Mon, 9 Jan 2017 16:34:36 +0100 Subject: [PATCH] [IMP] web: allow to upload multiple files in `many2many_binary` widget --- addons/web/controllers/main.py | 36 ++++---- .../src/js/views/form_relational_widgets.js | 90 ++++++++----------- addons/web/static/src/js/widgets/sidebar.js | 5 +- addons/web/static/src/xml/base.xml | 21 +++-- 4 files changed, 72 insertions(+), 80 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 930a8233eb5..479b74a19d4 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1023,27 +1023,31 @@ class Binary(http.Controller): @http.route('/web/binary/upload_attachment', type='http', auth="user") @serialize_exception def upload_attachment(self, callback, model, id, ufile): + files = request.httprequest.files.getlist('ufile') Model = request.env['ir.attachment'] out = """""" - try: - attachment = Model.create({ - 'name': ufile.filename, - 'datas': base64.encodestring(ufile.read()), - 'datas_fname': ufile.filename, - 'res_model': model, - 'res_id': int(id) - }) - args = { - 'filename': ufile.filename, - 'mimetype': ufile.content_type, - 'id': attachment.id - } - except Exception: - args = {'error': _("Something horrible happened")} - _logger.exception("Fail to upload attachment %s" % ufile.filename) + args = [] + for ufile in files: + try: + attachment = Model.create({ + 'name': ufile.filename, + 'datas': base64.encodestring(ufile.read()), + 'datas_fname': ufile.filename, + 'res_model': model, + 'res_id': int(id) + }) + except Exception: + args = args.append({'error': _("Something horrible happened")}) + _logger.exception("Fail to upload attachment %s" % ufile.filename) + else: + args.append({ + 'filename': ufile.filename, + 'mimetype': ufile.content_type, + 'id': attachment.id + }) return out % (json.dumps(callback), json.dumps(args)) @http.route([ 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 a15b588a297..b95b708aa05 100644 --- a/addons/web/static/src/js/views/form_relational_widgets.js +++ b/addons/web/static/src/js/views/form_relational_widgets.js @@ -1534,43 +1534,27 @@ var FieldMany2ManyBinaryMultiFiles = AbstractManyField.extend(common.Reinitializ 'click .o_attach': function(e) { this.$('.o_form_input_file').click(); }, - 'change .o_form_input_file': function(e) { - e.stopPropagation(); + 'change .o_form_input_file': function(event) { + event.stopPropagation(); + var files = event.target.files, + attachments = this.get('value'); - 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, - }; + if(this.node.attrs.blockui){ + framework.blockUI(); } + _.each(files, function(file){ + var attachment = _.findWhere(_.values(this.data), {filename: file.name}); + if(attachment && !attachment.no_unlink){ + this.ds_file.unlink([attachment.id]); + attachments = _.without(attachments, attachment.id); + this.data = _.omit(this.data, attachment.id); + } + this.files_uploading.push(file); + }.bind(this)); + this.set({value: attachments}); + this.$('form.o_form_binary_form').submit(); + this.$(".oe_fileupload").hide(); + this.render_value(); }, 'click .oe_delete': function(e) { e.preventDefault(); @@ -1581,6 +1565,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractManyField.extend(common.Reinitializ var files = _.without(this.get('value'), file_id); if(!this.data[file_id].no_unlink) { this.ds_file.unlink([file_id]); + this.data = _.omit(this.data, file_id); } this.set({'value': files}); } @@ -1593,6 +1578,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractManyField.extend(common.Reinitializ 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); } this.data = {}; + this.files_uploading = []; this.set_value([]); this.ds_file = new data.DataSetSearch(this, 'ir.attachment'); this.fileupload_id = _.uniqueId('oe_fileupload_temp'); @@ -1628,10 +1614,6 @@ var FieldMany2ManyBinaryMultiFiles = AbstractManyField.extend(common.Reinitializ this.read_name_values().then(function (ids) { self.$('.oe_placeholder_files, .oe_attachments') .replaceWith($(QWeb.render('FieldBinaryFileUploader.files', {'widget': self, 'values': ids}))); - - // reinit input type file - var $input = self.$('.o_form_input_file'); - $input.after($input.clone(true)).remove(); self.$(".oe_fileupload").show(); // display image thumbnail @@ -1644,23 +1626,25 @@ var FieldMany2ManyBinaryMultiFiles = AbstractManyField.extend(common.Reinitializ }); }, on_file_loaded: function(e, result) { - if(this.node.attrs.blockui > 0) { // unblock UI + var attachments = this.get('value'), + files = Array.prototype.slice.call(arguments, 1); + this.files_uploading = []; // files has been uploaded clear uploading + + if(this.node.attrs.blockui) { // unblock UI framework.unblockUI(); } - - 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) { - 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}); + var upload_error = _.filter(files, function(attachment) {return attachment.error;}); + if (upload_error.length) { + this.do_warn(_t('Uploading Error'), upload_error[0].error); } + _.each(files, function(file){ + if(!file.error){ + attachments.push(file.id); + file.url = this.get_file_url(file); + this.data[file.id] = file; + } + }.bind(this)); + this.set({value: _.clone(attachments)}); this.render_value(); }, }); diff --git a/addons/web/static/src/js/widgets/sidebar.js b/addons/web/static/src/js/widgets/sidebar.js index 1e382c3d985..32513048087 100644 --- a/addons/web/static/src/js/widgets/sidebar.js +++ b/addons/web/static/src/js/widgets/sidebar.js @@ -170,8 +170,9 @@ var Sidebar = Widget.extend({ do_attachement_update: function(dataset, model_id, args) { this.dataset = dataset; this.model_id = model_id; - if (args && args[0].error) { - this.do_warn(_t('Uploading Error'), args[0].error); + var upload_error = _.filter(args, function(attachment) {return attachment.error;}); + if (upload_error.length) { + this.do_warn(_t('Uploading Error'), upload_error[0].error); } if (!model_id) { this.on_attachments_loaded([]); diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index dc3119908fe..f6ac60c4d7e 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -244,6 +244,7 @@ /web/binary/upload_attachment + @@ -1003,7 +1004,7 @@ - + @@ -1017,6 +1018,7 @@ /web/binary/upload_attachment + @@ -1033,23 +1035,24 @@
- - ...Upload in progress... - - - +
+