Send client email via server
issue9449 review292001002
This commit is contained in:
1 parent
5b674ad987
commit
d9242e3a6b
10 files changed
+454
-159
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Support e-mail template
|
||||
* Always encode CSV export in UTF-8
|
||||
* Use tempusdominus and Popper for date time picker
|
||||
* Support PYSON comparison of date and datetime
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>
|
||||
|
After Width: | Height: | Size: 175 B |
@@ -132,8 +132,6 @@
|
||||
params.name = action.report_name;
|
||||
params.data = data;
|
||||
params.direct_print = action.direct_print;
|
||||
params.email_print = action.email_print;
|
||||
params.email = action.email;
|
||||
params.context = context;
|
||||
Sao.Action.exec_report(params);
|
||||
return;
|
||||
@@ -183,15 +181,10 @@
|
||||
if (!attributes.context) {
|
||||
attributes.context = {};
|
||||
}
|
||||
if (!attributes.email) {
|
||||
attributes.email = {};
|
||||
}
|
||||
var data = jQuery.extend({}, attributes.data);
|
||||
var context = jQuery.extend({}, Sao.Session.current_session.context);
|
||||
jQuery.extend(context, attributes.context);
|
||||
context.direct_print = attributes.direct_print;
|
||||
context.email_print = attributes.email_print;
|
||||
context.email = attributes.email;
|
||||
|
||||
var prm = Sao.rpc({
|
||||
'method': 'report.' + attributes.name + '.execute',
|
||||
|
||||
+144
-3
@@ -133,7 +133,7 @@
|
||||
|
||||
keys.forEach(function(k, i) {
|
||||
jQuery('<div/>', {
|
||||
'class': 'checkbox'
|
||||
'class': 'radio'
|
||||
}).append(jQuery('<label/>')
|
||||
.text(' ' + k)
|
||||
.prepend(jQuery('<input/>', {
|
||||
@@ -150,7 +150,7 @@
|
||||
'type': 'button'
|
||||
}).text(Sao.i18n.gettext('Cancel')).click(function() {
|
||||
dialog.modal.modal('hide');
|
||||
prm.fail();
|
||||
prm.reject();
|
||||
}).appendTo(dialog.footer);
|
||||
jQuery('<button/>', {
|
||||
'class': 'btn btn-primary',
|
||||
@@ -2723,6 +2723,7 @@
|
||||
'tryton-remove',
|
||||
'tryton-save',
|
||||
'tryton-search',
|
||||
'tryton-send',
|
||||
'tryton-star-border',
|
||||
'tryton-star',
|
||||
'tryton-switch',
|
||||
@@ -3435,7 +3436,9 @@
|
||||
this.input.focus();
|
||||
}.bind(this)).prependTo(this.menu);
|
||||
}, this);
|
||||
if (!this.input.val()) {
|
||||
if (!this.input.val() || (
|
||||
!this.menu.find('li.completion').length &&
|
||||
!this.menu.find('li.action').length)) {
|
||||
if (this.dropdown.hasClass('open')) {
|
||||
this.menu.dropdown('toggle');
|
||||
}
|
||||
@@ -3770,4 +3773,142 @@
|
||||
return colors;
|
||||
};
|
||||
|
||||
Sao.common.richtext_toolbar = function() {
|
||||
var toolbar = jQuery('<div/>', {
|
||||
'class': 'btn-toolbar',
|
||||
'role': 'toolbar',
|
||||
});
|
||||
|
||||
var button_apply_command = function(evt) {
|
||||
document.execCommand(evt.data);
|
||||
};
|
||||
|
||||
var add_buttons = function(buttons) {
|
||||
var group = jQuery('<div/>', {
|
||||
'class': 'btn-group',
|
||||
'role': 'group'
|
||||
}).appendTo(toolbar);
|
||||
for (var i in buttons) {
|
||||
var properties = buttons[i];
|
||||
var button = jQuery('<button/>', {
|
||||
'class': 'btn btn-default',
|
||||
'type': 'button'
|
||||
}).append(Sao.common.ICONFACTORY.get_icon_img(
|
||||
'tryton-format-' + properties.icon)
|
||||
).appendTo(group);
|
||||
button.click(properties.command, button_apply_command);
|
||||
}
|
||||
};
|
||||
|
||||
add_buttons([
|
||||
{
|
||||
'icon': 'bold',
|
||||
'command': 'bold'
|
||||
}, {
|
||||
'icon': 'italic',
|
||||
'command': 'italic'
|
||||
}, {
|
||||
'icon': 'underline',
|
||||
'command': 'underline'
|
||||
}]);
|
||||
|
||||
var selections = [
|
||||
{
|
||||
'heading': Sao.i18n.gettext('Font'),
|
||||
'options': ['Normal', 'Serif', 'Sans', 'Monospace'], // XXX
|
||||
'command': 'fontname'
|
||||
}, {
|
||||
'heading': Sao.i18n.gettext('Size'),
|
||||
'options': [1, 2, 3, 4, 5, 6, 7],
|
||||
'command': 'fontsize'
|
||||
}];
|
||||
var add_option = function(dropdown, properties) {
|
||||
return function(option) {
|
||||
dropdown.append(jQuery('<li/>').append(jQuery('<a/>', {
|
||||
'href': '#'
|
||||
}).text(option).click(function(evt) {
|
||||
evt.preventDefault();
|
||||
document.execCommand(properties.command, false, option);
|
||||
})));
|
||||
};
|
||||
};
|
||||
for (var i in selections) {
|
||||
var properties = selections[i];
|
||||
var group = jQuery('<div/>', {
|
||||
'class': 'btn-group',
|
||||
'role': 'group'
|
||||
}).appendTo(toolbar);
|
||||
var button = jQuery('<button/>', {
|
||||
'class': 'btn btn-default dropdown-toggle',
|
||||
'type': 'button',
|
||||
'data-toggle': 'dropdown',
|
||||
'aria-expanded': false,
|
||||
'aria-haspopup': true
|
||||
}).append(properties.heading)
|
||||
.append(jQuery('<span/>', {
|
||||
'class': 'caret'
|
||||
})).appendTo(group);
|
||||
var dropdown = jQuery('<ul/>', {
|
||||
'class': 'dropdown-menu'
|
||||
}).appendTo(group);
|
||||
properties.options.forEach(add_option(dropdown, properties));
|
||||
}
|
||||
|
||||
add_buttons([
|
||||
{
|
||||
'icon': 'align-left',
|
||||
'command': Sao.i18n.rtl? 'justifyRight' : 'justifyLeft',
|
||||
}, {
|
||||
'icon': 'align-center',
|
||||
'command': 'justifyCenter'
|
||||
}, {
|
||||
'icon': 'align-right',
|
||||
'command': Sao.i18n.rtl? 'justifyLeft': 'justifyRight',
|
||||
}, {
|
||||
'icon': 'align-justify',
|
||||
'command': 'justifyFull'
|
||||
}]);
|
||||
|
||||
// TODO backColor
|
||||
[['foreColor', '#000000']].forEach(
|
||||
function(e) {
|
||||
var command = e[0];
|
||||
var color = e[1];
|
||||
jQuery('<input/>', {
|
||||
'class': 'btn btn-default',
|
||||
'type': 'color'
|
||||
}).appendTo(toolbar)
|
||||
.change(function() {
|
||||
document.execCommand(command, false, jQuery(this).val());
|
||||
}).focusin(function() {
|
||||
document.execCommand(command, false, jQuery(this).val());
|
||||
}).val(color);
|
||||
});
|
||||
return toolbar;
|
||||
};
|
||||
|
||||
Sao.common.richtext_normalize = function(html) {
|
||||
var el = jQuery('<div/>').html(html);
|
||||
// TODO order attributes
|
||||
el.find('div').each(function(i, el) {
|
||||
el = jQuery(el);
|
||||
// Not all browsers respect the styleWithCSS
|
||||
if (el.css('text-align')) {
|
||||
// Remove browser specific prefix
|
||||
var align = el.css('text-align').split('-').pop();
|
||||
el.attr('align', align);
|
||||
el.css('text-align', '');
|
||||
}
|
||||
// Some browsers set start as default align
|
||||
if (el.attr('align') == 'start') {
|
||||
if (Sao.i18n.rtl) {
|
||||
el.attr('align', 'right');
|
||||
} else {
|
||||
el.attr('align', 'left');
|
||||
}
|
||||
}
|
||||
});
|
||||
return el.html();
|
||||
};
|
||||
|
||||
}());
|
||||
+4
-4
@@ -488,8 +488,6 @@ var Sao = {};
|
||||
try {
|
||||
attributes.data = loads(params.data || '{}');
|
||||
attributes.direct_print = loads(params.direct_print || 'false');
|
||||
attributes.email_print = loads(params.email_print || 'false');
|
||||
attributes.email = loads(params.email || 'null');
|
||||
attributes.name = loads(params.name || '""');
|
||||
attributes.window = loads(params.window || 'false');
|
||||
attributes.context = loads(params.context || '{}');
|
||||
@@ -512,8 +510,6 @@ var Sao = {};
|
||||
try {
|
||||
attributes.data = loads(params.data || '{}');
|
||||
attributes.direct_print = loads(params.direct_print || 'false');
|
||||
attributes.email_print = loads(params.email_print || 'false');
|
||||
attributes.email = loads(params.email || 'null');
|
||||
attributes.context = loads(params.context || '{}');
|
||||
} catch (e) {
|
||||
return;
|
||||
@@ -1014,6 +1010,10 @@ var Sao = {};
|
||||
shortcut: 'ctrl+p',
|
||||
label: Sao.i18n.gettext('Print'),
|
||||
id: 'print',
|
||||
}, {
|
||||
shortcut: 'ctrl+shift+e',
|
||||
label: Sao.i18n.gettext('E-Mail'),
|
||||
id: 'email',
|
||||
}, {
|
||||
shortcut: 'alt+shift+tab',
|
||||
label: Sao.i18n.gettext('Previous tab'),
|
||||
|
||||
@@ -681,6 +681,18 @@ input.column-boolean {
|
||||
}
|
||||
}
|
||||
|
||||
.email {
|
||||
.email-richtext {
|
||||
min-height: 10em;
|
||||
}
|
||||
input[type='file'] {
|
||||
display: inline-block;
|
||||
}
|
||||
.close {
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
|
||||
.bootstrap-datetimepicker-widget.dropdown-menu {
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
+38
-3
@@ -91,6 +91,11 @@
|
||||
id: 'print',
|
||||
icon: 'tryton-print',
|
||||
label: Sao.i18n.gettext('Print'),
|
||||
}, {
|
||||
id: 'email',
|
||||
icon: 'tryton-email',
|
||||
label: Sao.i18n.gettext('E-Mail...'),
|
||||
tooltip: Sao.i18n.gettext('Send an e-mail using the record'),
|
||||
}, null, {
|
||||
id: 'export',
|
||||
icon: 'tryton-export',
|
||||
@@ -522,7 +527,7 @@
|
||||
'role': 'menu',
|
||||
'aria-labelledby': menu_action[0]
|
||||
}))
|
||||
.appendTo(toolbar.find('.btn-toolbar > .btn-group').last());
|
||||
.insertBefore(toolbar.find('button#email'));
|
||||
buttons[menu_action[0]] = button;
|
||||
var dropdown = button
|
||||
.on('show.bs.dropdown', function() {
|
||||
@@ -643,8 +648,6 @@
|
||||
.selected_records.map(function(record) {
|
||||
return record.id;
|
||||
});
|
||||
exec_action = Sao.Action.evaluate(exec_action,
|
||||
menu_action[0], screen.current_record);
|
||||
var data = {
|
||||
model: screen.model_name,
|
||||
id: record_id,
|
||||
@@ -1173,6 +1176,38 @@
|
||||
this.refresh_resources(true);
|
||||
}.bind(this));
|
||||
},
|
||||
email: function() {
|
||||
function is_report(action) {
|
||||
return action.type == 'ir.action.report';
|
||||
}
|
||||
if (!this.buttons.email.hasClass('disabled')) {
|
||||
var record = this.screen.current_record;
|
||||
if (!record || (record.id < 0)) {
|
||||
return;
|
||||
}
|
||||
var title = this.title.text();
|
||||
this.screen.model.execute(
|
||||
'view_toolbar_get', [], this.screen.context)
|
||||
.then(function(toolbars) {
|
||||
var prints = toolbars.print.filter(is_report);
|
||||
var emails = {};
|
||||
for (var i = 0; i < toolbars.emails.length; i++) {
|
||||
var email = toolbars.emails[i];
|
||||
emails[email.name] = email.id;
|
||||
}
|
||||
record.rec_name().then(function(rec_name) {
|
||||
function email(template) {
|
||||
new Sao.Window.Email(
|
||||
title + ': ' + rec_name, record,
|
||||
prints, template);
|
||||
}
|
||||
Sao.common.selection(
|
||||
Sao.i18n.gettext("Template"), emails, true)
|
||||
.then(email, email);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
refresh_resources: function(reload) {
|
||||
var record = this.screen.current_record;
|
||||
if (record) {
|
||||
|
||||
@@ -187,6 +187,9 @@ select.form-control {
|
||||
.checkbox-inline {
|
||||
label {
|
||||
padding-left: 25px;
|
||||
input {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="radio"],
|
||||
|
||||
+9
-142
@@ -2100,7 +2100,10 @@ function eval_pyson(value){
|
||||
'class': this.class_ + ' panel panel-default'
|
||||
});
|
||||
if (parseInt(attributes.toolbar || '1', 10)) {
|
||||
this.toolbar = this.get_toolbar().appendTo(this.el);
|
||||
this.toolbar = Sao.common.richtext_toolbar().appendTo(
|
||||
jQuery('<div/>', {
|
||||
'class': 'panel-heading',
|
||||
}).appendTo(this.el));
|
||||
}
|
||||
this.input = this.labelled = jQuery('<div/>', {
|
||||
'class': 'richtext mousetrap',
|
||||
@@ -2122,122 +2125,6 @@ function eval_pyson(value){
|
||||
button.click(this.translate.bind(this));
|
||||
}
|
||||
},
|
||||
get_toolbar: function() {
|
||||
var i, properties, button;
|
||||
var toolbar = jQuery('<div/>', {
|
||||
'class': 'btn-toolbar',
|
||||
'role': 'toolbar'
|
||||
}).appendTo(jQuery('<div/>', {
|
||||
'class': 'panel-heading'
|
||||
}));
|
||||
|
||||
var button_apply_command = function(evt) {
|
||||
document.execCommand(evt.data);
|
||||
};
|
||||
|
||||
var add_buttons = function(buttons) {
|
||||
var group = jQuery('<div/>', {
|
||||
'class': 'btn-group',
|
||||
'role': 'group'
|
||||
}).appendTo(toolbar);
|
||||
for (i in buttons) {
|
||||
properties = buttons[i];
|
||||
button = jQuery('<button/>', {
|
||||
'class': 'btn btn-default',
|
||||
'type': 'button'
|
||||
}).append(Sao.common.ICONFACTORY.get_icon_img(
|
||||
'tryton-format-' + properties.icon)
|
||||
).appendTo(group);
|
||||
button.click(properties.command, button_apply_command);
|
||||
}
|
||||
};
|
||||
|
||||
add_buttons([
|
||||
{
|
||||
'icon': 'bold',
|
||||
'command': 'bold'
|
||||
}, {
|
||||
'icon': 'italic',
|
||||
'command': 'italic'
|
||||
}, {
|
||||
'icon': 'underline',
|
||||
'command': 'underline'
|
||||
}]);
|
||||
|
||||
var selections = [
|
||||
{
|
||||
'heading': Sao.i18n.gettext('Font'),
|
||||
'options': ['Normal', 'Serif', 'Sans', 'Monospace'], // XXX
|
||||
'command': 'fontname'
|
||||
}, {
|
||||
'heading': Sao.i18n.gettext('Size'),
|
||||
'options': [1, 2, 3, 4, 5, 6, 7],
|
||||
'command': 'fontsize'
|
||||
}];
|
||||
var add_option = function(dropdown, properties) {
|
||||
return function(option) {
|
||||
dropdown.append(jQuery('<li/>').append(jQuery('<a/>', {
|
||||
'href': '#'
|
||||
}).text(option).click(function(evt) {
|
||||
evt.preventDefault();
|
||||
document.execCommand(properties.command, false, option);
|
||||
})));
|
||||
};
|
||||
};
|
||||
for (i in selections) {
|
||||
properties = selections[i];
|
||||
var group = jQuery('<div/>', {
|
||||
'class': 'btn-group',
|
||||
'role': 'group'
|
||||
}).appendTo(toolbar);
|
||||
button = jQuery('<button/>', {
|
||||
'class': 'btn btn-default dropdown-toggle',
|
||||
'type': 'button',
|
||||
'data-toggle': 'dropdown',
|
||||
'aria-expanded': false,
|
||||
'aria-haspopup': true
|
||||
}).append(properties.heading)
|
||||
.append(jQuery('<span/>', {
|
||||
'class': 'caret'
|
||||
})).appendTo(group);
|
||||
var dropdown = jQuery('<ul/>', {
|
||||
'class': 'dropdown-menu'
|
||||
}).appendTo(group);
|
||||
properties.options.forEach(add_option(dropdown, properties));
|
||||
}
|
||||
|
||||
add_buttons([
|
||||
{
|
||||
'icon': 'align-left',
|
||||
'command': Sao.i18n.rtl? 'justifyRight' : 'justifyLeft',
|
||||
}, {
|
||||
'icon': 'align-center',
|
||||
'command': 'justifyCenter'
|
||||
}, {
|
||||
'icon': 'align-right',
|
||||
'command': Sao.i18n.rtl? 'justifyLeft': 'justifyRight',
|
||||
}, {
|
||||
'icon': 'align-justify',
|
||||
'command': 'justifyFull'
|
||||
}]);
|
||||
|
||||
// TODO backColor
|
||||
[['foreColor', '#000000']].forEach(
|
||||
function(e) {
|
||||
var command = e[0];
|
||||
var color = e[1];
|
||||
jQuery('<input/>', {
|
||||
'class': 'btn btn-default',
|
||||
'type': 'color'
|
||||
}).appendTo(toolbar)
|
||||
.change(function() {
|
||||
document.execCommand(command, false, jQuery(this).val());
|
||||
}).focusin(function() {
|
||||
document.execCommand(command, false, jQuery(this).val());
|
||||
}).val(color);
|
||||
});
|
||||
return toolbar;
|
||||
},
|
||||
focus_out: function() {
|
||||
// Let browser set the next focus before testing
|
||||
// if it moved out of the widget
|
||||
@@ -2277,31 +2164,8 @@ function eval_pyson(value){
|
||||
this.field.set_client(this.record, value);
|
||||
},
|
||||
_normalize_markup: function(content) {
|
||||
var el = jQuery('<div/>').html(
|
||||
return Sao.common.richtext_normalize(
|
||||
Sao.HtmlSanitizer.sanitize(content || ''));
|
||||
this._normalize(el);
|
||||
return el.html();
|
||||
},
|
||||
_normalize: function(el) {
|
||||
// TODO order attributes
|
||||
el.find('div').each(function(i, el) {
|
||||
el = jQuery(el);
|
||||
// Not all browsers respect the styleWithCSS
|
||||
if (el.css('text-align')) {
|
||||
// Remove browser specific prefix
|
||||
var align = el.css('text-align').split('-').pop();
|
||||
el.attr('align', align);
|
||||
el.css('text-align', '');
|
||||
}
|
||||
// Some browsers set start as default align
|
||||
if (el.attr('align') == 'start') {
|
||||
if (Sao.i18n.rtl) {
|
||||
el.attr('align', 'right');
|
||||
} else {
|
||||
el.attr('align', 'left');
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
get modified() {
|
||||
if (this.record && this.field) {
|
||||
@@ -2323,7 +2187,10 @@ function eval_pyson(value){
|
||||
'class': this.class_ + ' panel panel-default',
|
||||
});
|
||||
if (parseInt(this.attributes.toolbar || '1', 10)) {
|
||||
this.get_toolbar().appendTo(widget);
|
||||
Sao.common.richtext_toolbar().appendTo(
|
||||
jQuery('<div/>', {
|
||||
'class': 'panel-heading',
|
||||
}).appendTo(this.el));
|
||||
}
|
||||
var input = jQuery('<div/>', {
|
||||
'class': 'richtext mousetrap',
|
||||
|
||||
+242
@@ -1972,4 +1972,246 @@
|
||||
return row;
|
||||
};
|
||||
|
||||
Sao.Window.EmailEntry = Sao.class_(Sao.common.InputCompletion, {
|
||||
init: function(el, session) {
|
||||
this.session = session;
|
||||
Sao.Window.EmailEntry._super.init.call(
|
||||
this, el,
|
||||
this._email_source,
|
||||
this._email_match_selected,
|
||||
this._email_format);
|
||||
},
|
||||
_email_match_selected: function(value) {
|
||||
this.input.val(value[2]);
|
||||
},
|
||||
_email_source: function(text) {
|
||||
if (this.input[0].selectionStart < this.input.val().length) {
|
||||
return jQuery.when([]);
|
||||
}
|
||||
return Sao.rpc({
|
||||
'method': 'model.ir.email.complete',
|
||||
'params': [text, Sao.config.limit, {}],
|
||||
}, this.session);
|
||||
},
|
||||
_email_format: function(value) {
|
||||
return value[1];
|
||||
},
|
||||
});
|
||||
|
||||
Sao.Window.Email = Sao.class_(Object, {
|
||||
init: function(name, record, prints, template) {
|
||||
this.record = record;
|
||||
this.dialog = new Sao.Dialog(
|
||||
Sao.i18n.gettext('E-mail %1', name), 'email', 'lg');
|
||||
this.el = this.dialog.modal;
|
||||
this.dialog.content.addClass('form-horizontal');
|
||||
|
||||
var body = this.dialog.body;
|
||||
function add_group(name, label, required) {
|
||||
var group = jQuery('<div/>', {
|
||||
'class': 'form-group',
|
||||
}).appendTo(body);
|
||||
jQuery('<label/>', {
|
||||
'class': 'control-label col-sm-1',
|
||||
'text': label,
|
||||
'for': 'email-' + name,
|
||||
}).appendTo(group);
|
||||
var input = jQuery('<input/>', {
|
||||
'type': 'text',
|
||||
'class':'form-control input-sm',
|
||||
'id': 'email-' + name,
|
||||
}).appendTo(jQuery('<div/>', {
|
||||
'class': 'col-sm-11',
|
||||
}).appendTo(group));
|
||||
if (required) {
|
||||
input.attr('required', true);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
this.to = add_group('to', Sao.i18n.gettext('To:'), true);
|
||||
this.cc = add_group('cc', Sao.i18n.gettext('Cc:'));
|
||||
this.bcc = add_group('bcc', Sao.i18n.gettext('Bcc:'));
|
||||
[this.to, this.cc, this.bcc].forEach(function(input) {
|
||||
new Sao.Window.EmailEntry(input, this.record.model.session);
|
||||
}.bind(this));
|
||||
this.subject = add_group(
|
||||
'subject', Sao.i18n.gettext('Subject:'), true);
|
||||
|
||||
var panel = jQuery('<div/>', {
|
||||
'class': 'panel panel-default',
|
||||
}).appendTo(body
|
||||
).append(jQuery('<div/>', {
|
||||
'class': 'panel-heading',
|
||||
}).append(Sao.common.richtext_toolbar()));
|
||||
this.body = jQuery('<div>', {
|
||||
'class': 'email-richtext form-control input-sm mousetrap',
|
||||
'contenteditable': true,
|
||||
'spellcheck': true,
|
||||
'id': 'email-body',
|
||||
}).appendTo(jQuery('<div/>', {
|
||||
'class': 'panel-body',
|
||||
}).appendTo(panel));
|
||||
|
||||
var print_frame = jQuery('<div/>', {
|
||||
'class': 'col-md-6',
|
||||
}).appendTo(body);
|
||||
jQuery('<label/>', {
|
||||
'text': Sao.i18n.gettext("Reports"),
|
||||
}).appendTo(print_frame);
|
||||
this.print_actions = {};
|
||||
for (var i = 0; i < prints.length; i++) {
|
||||
var print = prints[i];
|
||||
var print_check = jQuery('<input/>', {
|
||||
'type': 'checkbox',
|
||||
});
|
||||
jQuery('<div/>', {
|
||||
'class': 'checkbox',
|
||||
}).append(jQuery('<label/>'
|
||||
).text(Sao.i18n.gettext(print.name)
|
||||
).prepend(print_check)).appendTo(print_frame);
|
||||
this.print_actions[print.id] = print_check;
|
||||
}
|
||||
|
||||
this.files = jQuery('<div/>', {
|
||||
'class': 'col-md-6',
|
||||
}).appendTo(body);
|
||||
jQuery('<label/>', {
|
||||
'text': Sao.i18n.gettext("Attachments"),
|
||||
}).appendTo(this.files);
|
||||
this._add_file_button();
|
||||
|
||||
jQuery('<button/>', {
|
||||
'class': 'btn btn-link',
|
||||
'type': 'button',
|
||||
}).text(' ' + Sao.i18n.gettext('Cancel')).prepend(
|
||||
Sao.common.ICONFACTORY.get_icon_img('tryton-cancel')
|
||||
).click(function() {
|
||||
this.response('RESPONSE_CANCEL');
|
||||
}.bind(this)).appendTo(this.dialog.footer);
|
||||
|
||||
jQuery('<button/>', {
|
||||
'class': 'btn btn-primary',
|
||||
'type': 'submit',
|
||||
}).text(' ' + Sao.i18n.gettext('Send')).prepend(
|
||||
Sao.common.ICONFACTORY.get_icon_img('tryton-send')
|
||||
).appendTo(this.dialog.footer);
|
||||
this.dialog.content.submit(function(e) {
|
||||
e.preventDefault();
|
||||
this.response('RESPONSE_OK');
|
||||
}.bind(this));
|
||||
|
||||
this._fill_with(template);
|
||||
|
||||
this.el.modal('show');
|
||||
this.el.on('hidden.bs.modal', function() {
|
||||
jQuery(this).remove();
|
||||
});
|
||||
},
|
||||
_add_file_button: function() {
|
||||
var row = jQuery('<div/>').appendTo(this.files);
|
||||
var file = jQuery('<input/>', {
|
||||
'type': 'file',
|
||||
}).appendTo(row);
|
||||
var button = jQuery('<a/>', {
|
||||
'class': 'close',
|
||||
'title': Sao.i18n.gettext("Remove attachment"),
|
||||
}).append(jQuery('<span/>', {
|
||||
'aria-hidden': true,
|
||||
'text': 'x',
|
||||
})).append(jQuery('<span/>', {
|
||||
'class': 'sr-only',
|
||||
}).text(Sao.i18n.gettext("Remove")));
|
||||
button.hide();
|
||||
button.appendTo(row);
|
||||
|
||||
file.on('change', function() {
|
||||
button.show();
|
||||
this._add_file_button();
|
||||
}.bind(this));
|
||||
button.click(function() {
|
||||
row.remove();
|
||||
});
|
||||
},
|
||||
get_files: function() {
|
||||
var prms = [];
|
||||
var files = [];
|
||||
this.files.find('input[type=file]').each(function(i, input) {
|
||||
if (input.files.length) {
|
||||
var dfd = jQuery.Deferred();
|
||||
prms.push(dfd);
|
||||
Sao.common.get_file_data(
|
||||
input.files[0], function(data, filename) {
|
||||
files.push([filename, data]);
|
||||
dfd.resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
return jQuery.when.apply(jQuery, prms).then(function() {
|
||||
return files;
|
||||
});
|
||||
},
|
||||
_fill_with: function(template) {
|
||||
var prm;
|
||||
if (template) {
|
||||
prm = Sao.rpc({
|
||||
'method': 'model.ir.email.template.get',
|
||||
'params': [template, this.record.id, {}],
|
||||
}, this.record.model.session);
|
||||
} else {
|
||||
prm = Sao.rpc({
|
||||
'method': 'model.ir.email.template.get_default',
|
||||
'params': [this.record.model.name, this.record.id, {}],
|
||||
}, this.record.model.session);
|
||||
}
|
||||
prm.then(function(values) {
|
||||
this.to.val((values.to || []).join(', '));
|
||||
this.cc.val((values.cc || []).join(', '));
|
||||
this.bcc.val((values.bcc || []).join(', '));
|
||||
this.subject.val(values.subject || '');
|
||||
this.body.html(Sao.HtmlSanitizer.sanitize(values.body || ''));
|
||||
var print_ids = (values.reports || []);
|
||||
for (var print_id in this.print_actions) {
|
||||
var check = this.print_actions[print_id];
|
||||
check.prop(
|
||||
'checked', ~print_ids.indexOf(parseInt(print_id, 10)));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
response: function(response_id) {
|
||||
if (response_id == 'RESPONSE_OK') {
|
||||
var to = this.to.val();
|
||||
var cc = this.cc.val();
|
||||
var bcc = this.bcc.val();
|
||||
var subject = this.subject.val();
|
||||
var body = Sao.common.richtext_normalize(this.body.html());
|
||||
var reports = [];
|
||||
for (var id in this.print_actions) {
|
||||
var check = this.print_actions[id];
|
||||
if (check.prop('checked')) {
|
||||
reports.push(id);
|
||||
}
|
||||
}
|
||||
var record = this.record;
|
||||
this.get_files().then(function(attachments) {
|
||||
return Sao.rpc({
|
||||
'method': 'model.ir.email.send',
|
||||
'params': [
|
||||
to, cc, bcc, subject, body,
|
||||
attachments,
|
||||
[record.model.name, record.id],
|
||||
reports, {}],
|
||||
}, record.model.session);
|
||||
}).then(function() {
|
||||
this.destroy();
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.destroy();
|
||||
}
|
||||
},
|
||||
destroy: function() {
|
||||
this.el.modal('hide');
|
||||
},
|
||||
});
|
||||
|
||||
}());
|
||||
Reference in new issue
Block a user