diff --git a/addons/web/static/lib/cleditor/jquery.cleditor.js b/addons/web/static/lib/cleditor/jquery.cleditor.js index c0763136c99..0fff0152776 100644 --- a/addons/web/static/lib/cleditor/jquery.cleditor.js +++ b/addons/web/static/lib/cleditor/jquery.cleditor.js @@ -295,7 +295,12 @@ // Bind the window resize event when the width or height is auto or % if (/auto|%/.test("" + options.width + options.height)) - $(window).resize(function() {refresh(editor);}); + $(window).resize(function() { + // CHM Note MonkeyPatch: if the DOM is not remove, refresh the cleditor + if(editor.$main.parent().parent().size()) { + refresh(editor); + } + }); // Create the iframe and resize the controls refresh(editor); @@ -562,7 +567,7 @@ //================== // Private Functions //================== - + // checksum - returns a checksum using the Adler-32 method function checksum(text) { diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 17b65ae91be..2ab5b9dc2d3 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -2931,6 +2931,76 @@ div.ui-widget-overlay { border-radius: 3px; } +.openerp .oe_fileupload { + display: inline-block; + clear: both; + width: 100%; +} +.openerp .oe_fileupload .oe_add { + float: left; + position: relative; + width: 100%; + left: +2px; + top: +7px; +} +.openerp .oe_fileupload .oe_add button{ + display: inline; + height: 24px; + font-size: 12px; + line-height: 12px; + vertical-align: middle; +} +.openerp .oe_fileupload .oe_add button.oe_attach { + width: 24px; + overflow: hidden; + background: transparent; + color: #7C7BAD; + box-shadow: none; + border: none; + text-shadow: none; +} +.openerp .oe_fileupload .oe_add .oe_attach_label{ + color: #7C7BAD; + margin-left: -3px; +} +.openerp .oe_fileupload .oe_add button.oe_attach .oe_e{ + position: relative; + top: -1px; + left: -9px; +} +.openerp .oe_fileupload .oe_add input.oe_form_binary_file{ + display: inline-block; + margin-left: -5px; + height: 28px; + width: 52px; + margin-top: -26px; +} +.openerp .oe_fileupload .oe_attachments { + margin-bottom: 4px; + margin-right: 0px; + font-size: 12px; + border-radius: 2px; + border: solid 1px rgba(124,123,173,0.14); +} +.openerp .oe_fileupload .oe_attachments .oe_attachment{ + padding: 2px; + padding-left: 4px; + padding-right: 4px; +} +.openerp .oe_fileupload .oe_attachments .oe_attachment .oe_e{ + font-size: 23px; + margin-top: -5px; +} +.openerp .oe_fileupload .oe_attachments .oe_attachment .oe_e:hover{ + text-decoration: none; +} +.openerp .oe_fileupload .oe_attachments .oe_attachment:nth-child(odd){ + background:white; +} +.openerp .oe_fileupload .oe_attachments .oe_attachment:nth-child(even){ + background: #F4F5FA; +} + @media print { .openerp { text-shadow: none; diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 15e1898883d..76951a09ba5 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -316,7 +316,7 @@ $sheet-padding: 16px text-decoration: none .oe_about background-color: white - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=) + background-image: url(data:image/pngbase64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=) @include radius(0 0 2px 2px) a color: $link-color @@ -681,7 +681,7 @@ $sheet-padding: 16px // }}} // Login {{{ .oe_login - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=) + background-image: url(data:image/pngbase64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=) text-align: center font-size: 14px height: 100% @@ -1028,7 +1028,7 @@ $sheet-padding: 16px // About openerp {{{ .oe_about background-color: white - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=) + background-image: url(data:image/pngbase64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=) @include radius(0 0 2px 2px) a color: $link-color @@ -2278,6 +2278,67 @@ $sheet-padding: 16px float: right color: #333 // }}} + +.openerp + .oe_fileupload + display: inline-block + clear: both + width: 100% + .oe_add + float: left + position: relative + width: 100% + left: +2px + top: +7px + button + display: inline + height: 24px + font-size: 12px + line-height: 12px + vertical-align: middle + button.oe_attach + width: 24px + overflow: hidden + width: 24px + overflow: hidden + background: transparent + color: #7C7BAD + box-shadow: none + border: none + text-shadow: none + .oe_e + position: relative + top: -1px + left: -9px + input.oe_form_binary_file + display: inline-block + margin-left: -5px + height: 28px + width: 52px + margin-top: -26px + .oe_attach_label + color: #7C7BAD + margin-left: -3px + .oe_attachments + margin-bottom: 4px + margin-right: 0px + font-size: 12px + border-radius: 2px + border: solid 1px rgba(124,123,173,0.14) + .oe_attachment + padding: 2px + padding-left: 4px + padding-right: 4px + .oe_e + font-size: 23px + margin-top: -5px + .oe_e:hover + text-decoration: none + .oe_attachment:nth-child(odd) + background:white + .oe_attachment:nth-child(even) + background: #F4F5FA + // Kitten Mode {{{ .kitten-mode-activated background-image: url(http://placekitten.com/g/1365/769) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 92e636b2216..5ecad26e5df 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -4874,6 +4874,132 @@ instance.web.form.FieldBinaryImage = instance.web.form.FieldBinary.extend({ } }); +/** + * Widget for (one2many 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 + */ +instance.web.form.FieldOne2ManyBinaryMultiFiles = instance.web.form.AbstractField.extend({ + template: "FieldBinaryFileUploader", + init: function(field_manager, node) { + this._super(field_manager, node); + this.field_manager = field_manager; + this.node = node; + if(this.field.type != "one2many" || this.field.relation != 'ir.attachment') { + throw "The type of the field '"+this.field.string+"' must be a one2many field with a relation to 'ir.attachment' model."; + } + this.ds_file = new instance.web.DataSetSearch(this, 'ir.attachment'); + this.fileupload_id = _.uniqueId('oe_fileupload_temp'); + $(window).on(this.fileupload_id, _.bind(this.on_file_loaded, this)); + }, + start: function() { + this._super(this); + this.$el.on('change', 'input.oe_form_binary_file', this.on_file_change ); + }, + get_value: function() { + return _.map(this.get('value'), function (value) { return commands.link_to( value.id ); }); + }, + get_file_url: function (attachment) { + return instance.origin + '/web/binary/saveas?session_id=' + this.session.session_id + '&model=ir.attachment&field=datas&filename_field=datas_fname&id=' + attachment['id']; + }, + render_value: function () { + var render = $(instance.web.qweb.render('FieldBinaryFileUploader.files', {'widget': this})); + render.on('click', '.oe_delete', _.bind(this.on_file_delete, this)); + this.$('.oe_placeholder_files, .oe_attachments').replaceWith( render ); + + // reinit input type file + var $input = this.$('input.oe_form_binary_file'); + $input.after($input.clone(true)).remove(); + this.$(".oe_fileupload").show(); + }, + on_file_change: function (event) { + event.stopPropagation(); + var self = this; + var $target = $(event.target); + if ($target.val() !== '') { + + var filename = $target.val().replace(/.*[\\\/]/,''); + + // if the files is currently uploded, don't send again + if( !isNaN(_.find(this.get('value'), function (file) { return (file.filename || file.name) == filename && file.upload; } )) ) { + return false; + } + + // block UI or not + if(this.node.attrs.blockui) { + instance.web.blockUI(); + } + + // if the files exits for this answer, delete the file before upload + var files = _.filter(this.get('value'), function (file) { + if((file.filename || file.name) == filename) { + self.ds_file.unlink([file.id]); + return false; + } else { + return true; + } + }); + + // TODO : unactivate send on wizard and form + + // submit file + this.$('form.oe_form_binary_form').submit(); + this.$(".oe_fileupload").hide(); + + // add file on result + files.push({ + 'id': 0, + 'name': filename, + 'filename': filename, + 'url': '', + 'upload': true + }); + + this.set({'value': files}); + } + }, + on_file_loaded: function (event, result) { + // unblock UI + if(this.node.attrs.blockui) { + instance.web.unblockUI(); + } + + // TODO : activate send on wizard and form + + var files = this.get('value'); + for(var i in files){ + if(files[i].filename == result.filename && files[i].upload) { + files[i] = { + 'id': result.id, + 'name': result.name, + 'filename': result.filename, + 'url': this.get_file_url(result) + }; + } + } + + this.set({'value': files}); + this.render_value() + }, + on_file_delete: function (event) { + event.stopPropagation(); + var file_id=$(event.target).data("id"); + if (file_id) { + var files=[]; + for(var i in this.get('value')){ + if(file_id != this.get('value')[i].id){ + files.push(this.get('value')[i]); + } + else { + this.ds_file.unlink([file_id]); + } + } + this.set({'value': files}); + } + }, +}); + instance.web.form.FieldStatus = instance.web.form.AbstractField.extend({ template: "FieldStatus", init: function(field_manager, node) { @@ -5026,6 +5152,7 @@ instance.web.form.widgets = new instance.web.Registry({ 'progressbar': 'instance.web.form.FieldProgressBar', 'image': 'instance.web.form.FieldBinaryImage', 'binary': 'instance.web.form.FieldBinaryFile', + 'one2many_binary': 'instance.web.form.FieldOne2ManyBinaryMultiFiles', 'statusbar': 'instance.web.form.FieldStatus', 'monetary': 'instance.web.form.FieldMonetary', }); diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 9880abd20f7..3eb8ff1acc7 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1174,6 +1174,48 @@