odoo.define('web.AttachDocument', function (require) { "use static"; var core = require('web.core'); var framework = require('web.framework'); var widgetRegistry = require('web.widget_registry'); var Widget = require('web.Widget'); var _t = core._t; var AttachDocument = Widget.extend({ template: 'AttachDocument', events: { 'click': '_onClickAttachDocument', 'change input.o_input_file': '_onFileChanged', }, /** * @constructor * @param {Widget} parent * @param {Object} record * @param {Object} nodeInfo */ init: function (parent, record, nodeInfo) { this._super.apply(this, arguments); this.res_id = record.res_id; this.res_model = record.model; this.state = record; this.node = nodeInfo; this.fileuploadID = _.uniqueId('o_fileupload'); }, /** * @override */ start: function () { $(window).on(this.fileuploadID, this._onFileLoaded.bind(this)); return this._super.apply(this, arguments); }, /** * @override */ destroy: function () { $(window).off(this.fileuploadID); this._super.apply(this, arguments); }, //-------------------------------------------------------------------------- // private //-------------------------------------------------------------------------- /** * Helper function to display a warning that some fields have an invalid * value. This is used when a save operation cannot be completed. * * @private * @param {string[]} invalidFields - list of field names */ _notifyInvalidFields: function (invalidFields) { var fields = this.state.fields; var warnings = invalidFields.map(function (fieldName) { var fieldStr = fields[fieldName].string; return _.str.sprintf('
  • %s
  • ', _.escape(fieldStr)); }); warnings.unshift(''); this.do_warn(_t("Invalid fields:"), warnings.join('')); }, //-------------------------------------------------------------------------- // Handlers //-------------------------------------------------------------------------- /** * Opens File Explorer dialog if all fields are valid and record is saved * * @private * @param {Event} ev */ _onClickAttachDocument: function (ev) { if ($(ev.target).is('input.o_input_file')) { return; } var fieldNames = this.getParent().canBeSaved(this.state.id); if (fieldNames.length) { return this._notifyInvalidFields(fieldNames); } // We want to save record on widget click and then open File Selection Explorer // but due to this security restriction give warning to save record first. // https://stackoverflow.com/questions/29728705/trigger-click-on-input-file-on-asynchronous-ajax-done/29873845#29873845 if (!this.res_id) { return this.do_warn(false, _t('Please save before attaching a file')); } this.$('input.o_input_file').trigger('click'); }, /** * Submits file * * @private * @param {Event} ev */ _onFileChanged: function (ev) { ev.stopPropagation(); this.$('form.o_form_binary_form').trigger('submit'); framework.blockUI(); }, /** * Call action given as node attribute after file submission * * @private */ _onFileLoaded: function () { var self = this; // the first argument isn't a file but the jQuery.Event var files = Array.prototype.slice.call(arguments, 1); return new Promise(function (resolve) { if (self.node.attrs.action) { self._rpc({ model: self.res_model, method: self.node.attrs.action, args: [self.res_id], kwargs: { attachment_ids: _.map(files, function (file) { return file.id; }), } }).then(function () { resolve(); }); } else { resolve(); } }).then(function () { self.trigger_up('reload'); framework.unblockUI(); }); }, }); widgetRegistry.add('attach_document', AttachDocument); });