Thibault Delavallée (OpenERP) has proposed merging
lp:~openerp-dev/openerp-web/trunk-openchatter-dom-chm into lp:openerp-web.
Requested reviews:
OpenERP R&D Web Team (openerp-dev-web)
For more details, see:
https://code.launchpad.net/~openerp-dev/openerp-web/trunk-openchatter-dom-chm/+merge/131884
OpenChatter 5.Pi "Stylin' in the rain", with a better Chatter widget, CSS and
behavior.
This web-side revision brings a new web widget for attachments, in order to
upload one or more file in same time and display them as a list. Files deletion
is supported. The blockui option allows to block the UI while the file is
uploaded.
--
https://code.launchpad.net/~openerp-dev/openerp-web/trunk-openchatter-dom-chm/+merge/131884
Your team OpenERP R&D Team is subscribed to branch
lp:~openerp-dev/openerp-web/trunk-openchatter-dom-chm.
=== modified file 'addons/web/static/src/css/base.css'
--- addons/web/static/src/css/base.css 2012-10-26 15:28:50 +0000
+++ addons/web/static/src/css/base.css 2012-10-29 12:09:37 +0000
@@ -2932,6 +2932,76 @@
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;
=== modified file 'addons/web/static/src/css/base.sass'
--- addons/web/static/src/css/base.sass 2012-10-26 15:28:50 +0000
+++ addons/web/static/src/css/base.sass 2012-10-29 12:09:37 +0000
@@ -314,7 +314,7 @@
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
@@ -679,7 +679,7 @@
// }}}
// 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%
@@ -1026,7 +1026,7 @@
// 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
@@ -2276,6 +2276,67 @@
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)
=== modified file 'addons/web/static/src/js/view_form.js'
--- addons/web/static/src/js/view_form.js 2012-10-28 08:33:24 +0000
+++ addons/web/static/src/js/view_form.js 2012-10-29 12:09:37 +0000
@@ -4674,7 +4674,7 @@
this.binary_value = false;
this.useFileAPI = !!window.FileReader;
if (!this.useFileAPI) {
- this.fileupload_id = _.uniqueId('oe_fileupload');
+ this.fileupload_id = _.uniqueId('oe_attachmentupload');
$(window).on(this.fileupload_id, function() {
var args = [].slice.call(arguments).slice(1);
self.on_file_uploaded.apply(self, args);
@@ -4874,6 +4874,132 @@
}
});
+/**
+ * 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 @@
'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',
});
=== modified file 'addons/web/static/src/xml/base.xml'
--- addons/web/static/src/xml/base.xml 2012-10-25 08:35:09 +0000
+++ addons/web/static/src/xml/base.xml 2012-10-29 12:09:37 +0000
@@ -1174,6 +1174,48 @@
<iframe t-att-id="fileupload_id" t-att-name="fileupload_id" style="display: none"/>
</div>
</t>
+<t t-name="FieldBinaryFileUploader.files">
+ <div class="oe_attachments">
+ <t t-if="!widget.get('effective_readonly')" t-foreach="widget.get('value')" t-as="file">
+ <div class="oe_attachment">
+ <span t-if="(file.upload or file.percent_loaded<100)" t-attf-title="{(file.name || file.filename) + (file.date?' \n('+file.date+')':'' )}" t-attf-name="{file.name || file.filename}">
+ <span class="oe_fileuploader_in_process">...Upload in progress...</span>
+ <t t-raw="file.name || file.filename"/>
+ </span>
+ <a t-if="(!file.upload or file.percent_loaded>=100)" t-att-href="file.url" t-attf-title="{(file.name || file.filename) + (file.date?' \n('+file.date+')':'' )}">
+ <t t-raw="file.name || file.filename"/>
+ </a>
+ <t t-if="(!file.upload or file.percent_loaded>=100)">
+ <a class="oe_right oe_delete oe_e" title="Delete this file" t-attf-data-id="{file.id}">[</a>
+ </t>
+ </div>
+ </t>
+ <t t-if="widget.get('effective_readonly')" t-foreach="widget.get('value')" t-as="file">
+ <div>
+ <a t-att-href="file.url" t-attf-title="{(file.name || file.filename) + (file.date?' \n('+file.date+')':'' )}">
+ <t t-raw="file.name || file.filename"/>
+ </a>
+ </div>
+ </t>
+ </div>
+</t>
+<t t-name="FieldBinaryFileUploader">
+ <div t-att-style="widget.node.attrs.style" t-attf-class="oe_fileupload #{widget.node.attrs.class ? widget.node.attrs.class :''}">
+ <div class="oe_placeholder_files"/>
+ <div class="oe_add" t-if="!widget.get('effective_readonly')">
+ <!-- uploader of file -->
+ <button class="oe_attach"><span class="oe_e">'</span></button>
+ <span class='oe_attach_label'>File</span>
+ <t t-call="HiddenInputFile">
+ <t t-set="fileupload_id" t-value="widget.fileupload_id"/>
+ <t t-set="fileupload_action">/web/binary/upload_attachment</t>
+ <input type="hidden" name="model" t-att-value="widget.view.model"/>
+ <input type="hidden" name="id" value="0"/>
+ <input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
+ </t>
+ </div>
+ </div>
+</t>
<t t-name="WidgetButton">
<button type="button" class="oe_button oe_form_button"
t-att-style="widget.node.attrs.style"
_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help : https://help.launchpad.net/ListHelp