[IMP] mail: extended composer for mailing channels

In Discuss, when the user opens a channel, the composer was the same,
regardless of the channel type.  This is fine for chat channels, because
we expect mostly small one liners to be written.  But for mailing
channels, it is a problem:  it is too easy to send a mail to everyone
just by typing ENTER, when the user wanted to go to the next line.

This commit introduces a new widget, the extended composer, to be used
for those channels.  It allows the edition of the subject line, and
don't sent messages when the enter key was pressed.
This commit is contained in:
Géry Debongnie
2015-12-23 14:37:41 +01:00
parent 9c2836090f
commit c4fb2b50e0
6 changed files with 98 additions and 30 deletions
@@ -552,6 +552,9 @@ var chat_manager = {
body: _.str.trim(data.content),
attachment_ids: data.attachment_ids,
};
if ('subject' in data) {
msg.subject = data.subject;
}
if ('channel_id' in options) {
// post a message in a channel
return ChannelModel.call('message_post', [options.channel_id], _.extend(msg, {
+2 -2
View File
@@ -2,7 +2,7 @@ odoo.define('mail.Chatter', function (require) {
"use strict";
var chat_manager = require('mail.chat_manager');
var ChatComposer = require('mail.ChatComposer');
var composer = require('mail.composer');
var ChatThread = require('mail.ChatThread');
var ajax = require('web.ajax');
@@ -432,7 +432,7 @@ var Followers = form_common.AbstractField.extend({
// popup when suggested partner is selected without email, or other
// informations), and the button to open the full composer wizard.
// -----------------------------------------------------------------------------
var ChatterComposer = ChatComposer.extend({
var ChatterComposer = composer.BasicComposer.extend({
template: 'mail.chatter.ChatComposer',
init: function (parent, dataset, options) {
+17 -11
View File
@@ -2,7 +2,7 @@ odoo.define('mail.chat_client_action', function (require) {
"use strict";
var chat_manager = require('mail.chat_manager');
var ChatComposer = require('mail.ChatComposer');
var composer = require('mail.composer');
var ChatThread = require('mail.ChatThread');
var config = require('web.config');
@@ -15,7 +15,6 @@ var Model = require('web.Model');
var pyeval = require('web.pyeval');
var SearchView = require('web.SearchView');
var session = require('web.session');
var Widget = require('web.Widget');
var QWeb = core.qweb;
@@ -163,7 +162,8 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
this.searchview = new SearchView(this, dataset, view_id, {}, options);
this.searchview.on('search_data', this, this.on_search);
this.composer = new ChatComposer(this);
this.basic_composer = new composer.BasicComposer(this);
this.extended_composer = new composer.ExtendedComposer(this);
this.thread = new ChatThread(this, {
display_help: true,
shorten_messages: false,
@@ -196,16 +196,19 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
this.thread.on('toggle_star_status', this, function (message_id) {
chat_manager.toggle_star_status(message_id);
});
this.composer.on('post_message', this, this.on_post_message);
this.composer.on('input_focused', this, this.on_composer_input_focused);
this.basic_composer.on('post_message', this, this.on_post_message);
this.basic_composer.on('input_focused', this, this.on_composer_input_focused);
this.extended_composer.on('post_message', this, this.on_post_message);
this.extended_composer.on('input_focused', this, this.on_composer_input_focused);
var def1 = this.thread.prependTo(this.$('.o_mail_chat_content'));
var def2 = this.composer.appendTo(this.$('.o_mail_chat_content'));
var def3 = this.searchview.appendTo($("<div>"));
var def2 = this.basic_composer.appendTo(this.$('.o_mail_chat_content'));
var def3 = this.extended_composer.appendTo(this.$('.o_mail_chat_content'));
var def4 = this.searchview.appendTo($("<div>"));
this.render_sidebar();
return $.when(def1, def2, def3)
return $.when(def1, def2, def3, def4)
.then(this.set_channel.bind(this, default_channel))
.then(function () {
chat_manager.bus.on('new_message', self, self.on_new_message);
@@ -369,7 +372,8 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
.find('.o_mail_chat_button_unstar_all')
.toggle(channel.id === "channel_starred");
self.$('.o_chat_composer').toggle(channel.type !== 'static');
self.basic_composer.toggle(channel.type !== 'static' && !channel.mass_mailing);
self.extended_composer.toggle(channel.type !== 'static' && channel.mass_mailing);
self.$('.o_mail_chat_channel_item')
.removeClass('o_active')
@@ -387,7 +391,8 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
// Update control panel before focusing the composer, otherwise focus is on the searchview
self.update_cp();
if (!config.device.touch) {
self.composer.focus();
var composer = channel.mass_mailing ? self.extended_composer : self.basic_composer;
composer.focus();
}
if (config.device.size_class === config.device.SIZES.XS) {
self.$('.o_mail_chat_sidebar').hide();
@@ -553,7 +558,8 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
},
on_composer_input_focused: function () {
var suggestions = chat_manager.get_mention_partner_suggestions(this.channel);
this.composer.mention_set_prefetched_partners(suggestions);
var composer = channel.mass_mailing ? self.extended_composer : self.basic_composer;
composer.mention_set_prefetched_partners(suggestions);
},
on_click_button_invite: function () {
+39 -3
View File
@@ -1,4 +1,4 @@
odoo.define('mail.ChatComposer', function (require) {
odoo.define('mail.composer', function (require) {
"use strict";
var chat_manager = require('mail.chat_manager');
@@ -310,7 +310,7 @@ var MentionManager = Widget.extend({
});
var Composer = Widget.extend({
var BasicComposer = Widget.extend({
template: "mail.ChatComposer",
events: {
@@ -395,6 +395,10 @@ var Composer = Widget.extend({
return this._super();
},
toggle: function(state) {
this.$el.toggle(state);
},
preprocess_message: function () {
// Return a deferred as this function is extended with asynchronous
// behavior for the chatter composer
@@ -655,6 +659,38 @@ var Composer = Widget.extend({
},
});
return Composer;
var ExtendedComposer = BasicComposer.extend({
init: function (parent, options) {
options = _.defaults(options || {}, {
input_min_height: 120,
});
this.extended = true;
return this._super(parent, options);
},
start: function () {
this.$subject_input = this.$(".o_composer_subject input");
return this._super.apply(this, arguments);
},
preprocess_message: function () {
var self = this;
return this._super().then(function (message) {
var subject = self.$subject_input.val();
self.$subject_input.val("");
message.subject = subject;
return message;
});
},
prevent_send: function () {
return true;
},
});
return {
BasicComposer: BasicComposer,
ExtendedComposer: ExtendedComposer,
};
});
+14 -2
View File
@@ -1,5 +1,17 @@
.o_composer .o_composer_input {
resize: none;
.o_composer_subject {
.o-flex-display();
padding-bottom: 5px;
> input {
.o-flex(1, 1, auto);
margin-right: 30px;
}
}
.o_composer {
.o_composer_input {
resize: none;
}
}
.o_composer_attachments_list {
+23 -12
View File
@@ -2,17 +2,21 @@
<templates xml:space="preserve">
<div t-name="mail.ChatComposer" class="o_chat_composer">
<div class="o_composer_attachments_list"/>
<div class="o_composer">
<textarea class="o_composer_input" placeholder="Write something..."/>
<div class="btn-group o_composer_buttons">
<button class="btn btn-sm btn-primary o_composer_button_send" type="button"><t t-esc="widget.options.send_text"/></button>
<button class="btn btn-sm btn-icon fa fa-smile-o o_composer_button_emoji" type="button" data-toggle="popover"/>
<button class="btn btn-sm btn-icon fa fa-paperclip o_composer_button_add_attachment" type="button"/>
</div>
</div>
<div class="o_composer_attachments_list"/>
<t t-if="widget.extended">
<div class="o_composer_subject">
<input placeholder="Subject"></input>
<t t-call="mail.ChatComposer.Buttons"></t>
</div>
</t>
<div class="o_composer">
<textarea class="o_composer_input" placeholder="Write something..."/>
<t t-if="!widget.extended">
<t t-call="mail.ChatComposer.Buttons"></t>
</t>
</div>
<span class="hide">
<span class="hide">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
@@ -20,10 +24,17 @@
<input type="hidden" name="id" value="0"/>
<input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
</t>
</span>
<span class="o_composer_emoji"></span>
</span>
<span class="o_composer_emoji"></span>
</div>
<t t-name="mail.ChatComposer.Buttons">
<div class="btn-group o_composer_buttons">
<button class="btn btn-sm btn-primary o_composer_button_send" type="button"><t t-esc="widget.options.send_text"/></button>
<button class="btn btn-sm btn-icon fa fa-smile-o o_composer_button_emoji" type="button" data-toggle="popover"/>
<button class="btn btn-sm btn-icon fa fa-paperclip o_composer_button_add_attachment" type="button"/>
</div>
</t>
<t t-name="mail.ChatComposer.emojis">
<t t-foreach="emojis" t-as="emoji">
<span t-att-data-emoji="emoji.source" class="o_mail_emoji" t-att-title="emoji.description">