Use dropdown for attachments

issue7659
review50551002
This commit is contained in:
Cédric Krier
2018-09-02 10:44:38 +02:00
parent f8271980d9
commit f3796ec776
6 changed files with 217 additions and 91 deletions
+2
View File
@@ -1,3 +1,5 @@
* Remove dialog for input file
* Use dropdown for attachment
* Manage icons in input
* Support RTL language direction
* Apply factor on domain parser
+13
View File
@@ -3412,6 +3412,19 @@
};
Sao.common.get_input_data = function(input, callback, char_) {
var reader = new FileReader(),
file = input[0].files[0];
reader.onload = function() {
var value = new Uint8Array(reader.result);
if (char_) {
value = String.fromCharCode.apply(null, value);
}
callback(value, file.name);
};
reader.readAsArrayBuffer(file);
};
Sao.common.ellipsize = function(string, length) {
if (string.length <= length) {
return string;
+8
View File
@@ -124,6 +124,14 @@ input[type='color'] {
}
}
.input-file {
& input[type='file'] {
position: absolute;
opacity: 0;
cursor: pointer;
}
}
/* Hide empty image displayed as broken image */
[src=''] {
visibility: hidden;
+110 -16
View File
@@ -72,6 +72,7 @@
icon: 'tryton-attach',
label: Sao.i18n.gettext('Attachment'),
tooltip: Sao.i18n.gettext('Add an attachment to the record'),
dropdown: true,
}, {
id: 'note',
icon: 'tryton-note',
@@ -208,16 +209,37 @@
'role': 'group'
}).appendTo(toolbar.find('.btn-toolbar'));
}
this.buttons[item.id] = jQuery('<button/>', {
var attributes = {
'type': 'button',
'class': 'btn btn-default navbar-btn',
'title': item.label,
'id': item.id
})
.append(Sao.common.ICONFACTORY.get_icon_img(item.icon, {
'aria-hidden': 'true',
}))
.appendTo(group);
};
if (item.dropdown) {
attributes['class'] += ' dropdown-toggle';
attributes['data-toggle'] = 'dropdown';
attributes['aria-expanded'] = false;
attributes['aria-haspopup'] = true;
}
var button = jQuery('<button/>', attributes)
.append(Sao.common.ICONFACTORY.get_icon_img(item.icon, {
'aria-hidden': 'true',
}));
this.buttons[item.id] = button;
if (item.dropdown) {
var dropdown = jQuery('<div/>', {
'class': 'btn-group dropdown',
'role': 'group',
}).append(button.append(jQuery('<span/>', {
'class': 'caret',
}))).append(jQuery('<ul/>', {
'class': 'dropdown-menu',
'role': 'menu',
'aria-labelledby': item.id,
})).appendTo(group);
} else {
button.appendTo(group);
}
this.buttons[item.id].click(item, function(event) {
var item = event.data;
var button = this.buttons[item.id];
@@ -234,8 +256,17 @@
}).appendTo(jQuery('<div/>', {
'class': 'navbar-text hidden-xs',
}).insertAfter(this.buttons.previous));
toolbar.find('.btn-toolbar > .btn-group').last().addClass(
'hidden-xs');
toolbar.find('.btn-toolbar > .btn-group').last()
.addClass( 'hidden-xs')
.find('.dropdown')
.on('show.bs.dropdown', function() {
jQuery(this).parents('.btn-group')
.removeClass( 'hidden-xs');
})
.on('hide.bs.dropdown', function() {
jQuery(this).parents('.btn-group')
.addClass('hidden-xs');
});
var tabs = jQuery('#tabs');
toolbar.affix({
'target': tabs.parent(),
@@ -487,7 +518,7 @@
Sao.i18n.gettext('Print report')]
].forEach(function(menu_action) {
var button = jQuery('<div/>', {
'class': 'btn-group',
'class': 'btn-group dropdown',
'role': 'group'
})
.append(jQuery('<button/>', {
@@ -521,7 +552,7 @@
jQuery(this).parents('.btn-group').addClass(
'hidden-xs');
});
var menu = button.find('ul[role*="menu"]');
var menu = button.find('.dropdown-menu');
button.click(function() {
menu.find('.' + menu_action[0] + '_button').remove();
var buttons = screen.get_buttons();
@@ -886,14 +917,77 @@
}.bind(this));
}
},
attach: function() {
var record = this.screen.current_record;
if (!record || (record.id < 0)) {
attach: function(evt) {
var window_ = function() {
return new Sao.Window.Attachment(record, function() {
this.update_attachment_count(true);
}.bind(this));
}.bind(this);
var dropdown = this.buttons.attach.parents('.dropdown');
if (!evt) {
window.setTimeout(function() {
this.buttons.attach.click();
}.bind(this));
return;
}
new Sao.Window.Attachment(record, function() {
this.update_attachment_count(true);
}.bind(this));
var record = this.screen.current_record;
var menu = dropdown.find('.dropdown-menu');
menu.children().remove();
Sao.Window.Attachment.get_attachments(record)
.then(function(attachments) {
attachments.forEach(function(value) {
var name = value[0],
callback = value[1];
var link = jQuery('<a/>', {
'role': 'menuitem',
'href': '#',
'tabindex': -1,
}).append(name).appendTo(jQuery('<li/>', {
'role': 'presentation',
}).appendTo(menu));
if (typeof callback == 'string') {
link.attr('href', callback);
link.attr('target', '_new');
} else {
link.click(function(evt) {
evt.preventDefault();
callback();
});
}
});
}).always(function() {
menu.append(jQuery('<li/>', {
'class': 'divider',
}));
menu.append(jQuery('<li/>', {
'role': 'presentation',
'class': 'input-file',
}).append(jQuery('<input/>', {
'type': 'file',
'role': 'menuitem',
'tabindex': -1,
}).change(function() {
Sao.common.get_input_data(
jQuery(this), function(data, filename) {
window_().add_data(data, filename);
});
})).append(jQuery('<a/>', {
'role': 'menuitem',
'href': '#',
'tabindex': -1,
}).append(Sao.i18n.gettext('Add...'))));
menu.append(jQuery('<li/>', {
'role': 'presentation',
}).append(jQuery('<a/>', {
'role': 'menuitem',
'href': '#',
'tabindex': -1,
}).append(Sao.i18n.gettext('Manage...'))
.click(function(evt) {
evt.preventDefault();
window_();
})));
});
},
update_attachment_count: function(reload) {
var record = this.screen.current_record;
+20 -57
View File
@@ -3512,14 +3512,17 @@ function eval_pyson(value){
).appendTo(group);
this.but_save_as.click(this.save_as.bind(this));
this.but_select = jQuery('<button/>', {
'class': 'btn btn-default',
this.input_select = jQuery('<input/>', {
'type': 'file',
}).change(this.select.bind(this));
this.but_select = jQuery('<div/>', {
'class': 'btn btn-default input-file',
'type': 'button',
'aria-label': Sao.i18n.gettext("Select"),
'title': Sao.i18n.gettext("Select..."),
}).append(Sao.common.ICONFACTORY.get_icon_img('tryton-search')
}).append(this.input_select
).append(Sao.common.ICONFACTORY.get_icon_img('tryton-search')
).appendTo(group);
this.but_select.click(this.select.bind(this));
this.but_clear = jQuery('<button/>', {
'class': 'btn btn-default',
@@ -3533,9 +3536,11 @@ function eval_pyson(value){
return group;
},
filename_field: function() {
var record = this.record();
if (record) {
return record.model.fields[this.filename];
if (this.filename) {
var record = this.record();
if (record) {
return record.model.fields[this.filename];
}
}
},
update_buttons: function(value) {
@@ -3550,58 +3555,16 @@ function eval_pyson(value){
}
},
select: function() {
var record = this.record();
var record = this.record(),
field = this.field(),
filename_field = this.filename_field();
var close = function() {
file_dialog.modal.on('hidden.bs.modal', function(event) {
jQuery(this).remove();
});
file_dialog.modal.modal('hide');
};
var save_file = function() {
var reader = new FileReader();
reader.onload = function(evt) {
var field = this.field();
var uint_array = new Uint8Array(reader.result);
var value;
if (field.get_size) {
value = uint_array;
} else {
value = String.fromCharCode.apply(null, uint_array);
}
field.set_client(record, value);
}.bind(this);
reader.onloadend = function(evt) {
close();
};
var file = file_selector[0].files[0];
reader.readAsArrayBuffer(file);
if (this.filename) {
this.filename_field().set_client(record, file.name);
Sao.common.get_input_data(this.input_select, function(data, filename) {
field.set_client(record, data);
if (filename_field) {
filename_field.set_client(record, filename);
}
}.bind(this);
var file_dialog = new Sao.Dialog(
Sao.i18n.gettext('Select'), 'file-dialog');
file_dialog.footer.append(jQuery('<button/>', {
'class': 'btn btn-link',
'type': 'button'
}).append(Sao.i18n.gettext('Cancel')).click(close))
.append(jQuery('<button/>', {
'class': 'btn btn-primary',
'type': 'submit'
}).append(Sao.i18n.gettext('OK')).click(save_file));
file_dialog.content.submit(function(e) {
save_file();
e.preventDefault();
});
var file_selector = jQuery('<input/>', {
type: 'file'
}).appendTo(file_dialog.body);
file_dialog.modal.modal('show');
}, !field.get_size);
},
open: function() {
var params = {};
+64 -18
View File
@@ -55,23 +55,12 @@
this.info_bar = new Sao.Window.InfoBar();
var view_type = kwargs.view_type || 'form';
var form_prm = jQuery.when();
var screen_views = [];
for (var i = 0, len = this.screen.views.length; i < len; i++) {
screen_views.push(this.screen.views[i].view_type);
}
if (!~screen_views.indexOf(view_type) &&
!~this.screen.view_to_load.indexOf(view_type)) {
form_prm = this.screen.add_view_id(null, view_type);
}
var switch_prm = form_prm.then(function() {
return this.screen.switch_view(view_type).done(function() {
this.switch_prm = this.screen.switch_view(view_type)
.done(function() {
if (kwargs.new_) {
this.screen.new_(undefined, kwargs.rec_name);
}
}.bind(this));
}.bind(this));
var dialog = new Sao.Dialog('', 'window-form', 'lg', false);
this.el = dialog.modal;
this.el.on('keydown', function(e) {
@@ -231,7 +220,7 @@
dialog.body.append(this.info_bar.el);
switch_prm.done(function() {
this.switch_prm.done(function() {
title_prm.done(dialog.add_title.bind(dialog));
content.append(this.screen.screen_container.alternate_viewport);
this.el.modal('show');
@@ -433,14 +422,14 @@
mode: ['tree', 'form'],
context: context,
});
screen.switch_view().done(function() {
screen.search_filter();
});
var title = record.rec_name().then(function(rec_name) {
return Sao.i18n.gettext('Attachments (%1)', rec_name);
});
Sao.Window.Attachment._super.init.call(this, screen, this.callback,
{view_type: 'tree', title: title});
this.switch_prm = this.switch_prm.then(function() {
return screen.search_filter();
});
},
callback: function(result) {
var prm = jQuery.when();
@@ -450,8 +439,65 @@
if (this.attachment_callback) {
prm.always(this.attachment_callback.bind(this));
}
}
},
add_data: function(data, filename) {
var screen = this.screen;
this.switch_prm.then(function() {
screen.set_current_record(null);
screen.switch_view('form').then(function() {
screen.new_().then(function(record) {
var data_field = record.model.fields.data;
record.field_set_client(
data_field.description.filename, filename);
record.field_set_client('data', data);
screen.display();
});
});
});
},
});
Sao.Window.Attachment.get_attachments = function(record) {
var prm;
if (record && (record.id >= 0)) {
var context = record.get_context();
prm = Sao.rpc({
'method': 'model.ir.attachment.search_read',
'params': [
[['resource', '=', record.model.name + ',' + record.id]],
0, 20, null, ['rec_name', 'name', 'type', 'link'],
context],
}, record.model.session);
} else {
prm = jQuery.when([]);
}
var partial = function(callback, attachment, context, session) {
return function() {
return callback(attachment, context, session);
};
};
return prm.then(function(attachments) {
return attachments.map(function(attachment) {
var name = attachment.rec_name;
if (attachment.type == 'link') {
return [name, attachment.link];
} else {
var callback = Sao.Window.Attachment[
'open_' + attachment.type];
return [name, partial(
callback, attachment, context, record.model.session)];
}
});
});
};
Sao.Window.Attachment.open_data = function(attachment, context, session) {
Sao.rpc({
'method': 'model.ir.attachment.read',
'params': [
[attachment.id], ['data'], context],
}, session).then(function(values) {
Sao.common.download_file(values[0].data, attachment.name);
});
};
Sao.Window.Note = Sao.class_(Sao.Window.Form, {
init: function(record, callback) {