[IMP] web: allow to upload multiple files in many2many_binary widget
This commit is contained in:
@@ -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 = """<script language="javascript" type="text/javascript">
|
||||
var win = window.top.window;
|
||||
win.jQuery(win).trigger(%s, %s);
|
||||
</script>"""
|
||||
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([
|
||||
|
||||
@@ -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();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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([]);
|
||||
|
||||
@@ -244,6 +244,7 @@
|
||||
<t t-call="HiddenInputFile">
|
||||
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
|
||||
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
|
||||
<t t-set="multi_upload" t-value="true"/>
|
||||
<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" t-if="widget.session.override_session"/>
|
||||
@@ -1003,7 +1004,7 @@
|
||||
<input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
|
||||
<input type="hidden" name="session_id" value="" t-if="widget.session.override_session"/>
|
||||
<input type="hidden" name="callback" t-att-value="fileupload_id"/>
|
||||
<input t-if="widget.widget!='image'" type="file" class="o_form_input_file" name="ufile"/>
|
||||
<input t-if="widget.widget!='image'" type="file" class="o_form_input_file" name="ufile" t-att="{'multiple': multi_upload ? 'multiple' : null}"/>
|
||||
<input t-if="widget.widget=='image'" type="file" class="o_form_input_file" name="ufile" accept="image/*"/>
|
||||
<t t-raw="0"/>
|
||||
</form>
|
||||
@@ -1017,6 +1018,7 @@
|
||||
<t t-call="HiddenInputFile">
|
||||
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
|
||||
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
|
||||
<t t-set="multi_upload" t-value="true"/>
|
||||
<input type="hidden" name="model" t-att-value="widget.view.model"/>
|
||||
<input type="hidden" name="id" value="0"/>
|
||||
<input t-if="widget.session.override_session" type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
|
||||
@@ -1033,23 +1035,24 @@
|
||||
<t t-if="!widget.get('effective_readonly')">
|
||||
<div t-foreach="values" t-as="id" class="oe_attachment">
|
||||
<t t-set="file" t-value="widget.data[id]"/>
|
||||
<span t-if="file.upload or file.percent_loaded<100"
|
||||
t-att-title="(file.name || file.filename) + ((file.date)? (' \n(' + file.date + ')') : '')"
|
||||
t-att-name="file.name || file.filename">
|
||||
<span class="oe_fileuploader_in_process">...Upload in progress...</span>
|
||||
<t t-raw="file.name || file.filename"/>
|
||||
</span>
|
||||
<t t-if="!file.upload or file.percent_loaded>=100">
|
||||
<t t-if="!file.upload">
|
||||
<div>
|
||||
<a href="#" class="fa fa-times pull-right oe_delete" title="Delete this file" t-att-data-id="file.id"/>
|
||||
<t t-raw="file.name || file.filename"/>
|
||||
</div>
|
||||
<a class="o_image" target="_blank" t-att-href="file.url"
|
||||
t-att-title="(file.name || file.filename) + ((file.date)? (' \n(' + file.date + ')') : '')"
|
||||
t-att-title="file.name"
|
||||
t-att-data-mimetype="file.mimetype"
|
||||
t-attf-data-src="/web/image/#{file.id}/100x80"/>
|
||||
</t>
|
||||
</div>
|
||||
<div t-foreach="widget.files_uploading" t-as="file" class="oe_attachment">
|
||||
<div>Uploading...</div>
|
||||
<a t-att-title="file.name" t-att-name="file.name" class="o_image">
|
||||
<i class="fa fa-spinner fa-spin fa-5x fa-fw"></i>
|
||||
</a>
|
||||
<div><t t-esc="file.name"/></div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div t-name="SearchView" class="o_searchview">
|
||||
|
||||
Reference in New Issue
Block a user