summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/js/mail_chat_backend.js
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2015-09-30 14:14:30 +0200
committerGéry Debongnie <ged@odoo.com>2015-10-01 14:00:18 +0200
commit2a5f07e0b919d4209c2cb72c6dfdc8b86cd5c7ff (patch)
tree54cbc12fb66b72ad21f94857ac24052a3abf3f6a /addons/mail/static/src/js/mail_chat_backend.js
parent62be162877f30a6ca0f61b38f0b070d56f7ab419 (diff)
[REF] mail: last part of the chat refactoring (client side)
Removal of old files and update of assets and imports Joint work with aab
Diffstat (limited to 'addons/mail/static/src/js/mail_chat_backend.js')
-rw-r--r--addons/mail/static/src/js/mail_chat_backend.js1051
1 files changed, 0 insertions, 1051 deletions
diff --git a/addons/mail/static/src/js/mail_chat_backend.js b/addons/mail/static/src/js/mail_chat_backend.js
deleted file mode 100644
index d0966dd3088..00000000000
--- a/addons/mail/static/src/js/mail_chat_backend.js
+++ /dev/null
@@ -1,1051 +0,0 @@
-odoo.define('mail.chat_backend', function (require) {
-"use strict";
-
-var core = require('web.core');
-var data = require('web.data');
-var framework = require('web.framework');
-var Model = require('web.Model');
-var pyeval = require('web.pyeval');
-var SystrayMenu = require('web.SystrayMenu');
-var Widget = require('web.Widget');
-var Dialog = require('web.Dialog');
-var ControlPanelMixin = require('web.ControlPanelMixin');
-var SearchView = require('web.SearchView');
-var Sidebar = require('web.Sidebar');
-var WebClient = require('web.WebClient');
-
-var session = require('web.session');
-var web_client = require('web.web_client');
-
-var mail_chat_common = require('mail.chat_common');
-var mail_thread = require('mail.thread');
-
-var _t = core._t;
-var QWeb = core.qweb;
-var internal_bus = core.bus;
-
-
-/**
- * Widget handeling the channels, in the backend
- *
- * Responsible to listen the bus and apply action with the received message. Add layer to coordinate the
- * folded conversation and trigger event for the InstantMessagingView client action (using internal
- * comminication bus). It is a component of the WebClient.
- **/
-var ConversationManagerBackend = mail_chat_common.ConversationManager.extend({
- _setup: function(init_data){
- var self = this;
- this._super.apply(this, arguments);
- _.each(init_data.notifications, function(n){
- self.on_notification(n);
- });
- },
- // window title
- window_title_change: function() {
- this._super.apply(this, arguments);
- var title;
- if (this.get("waiting_messages") !== 0) {
- title = _.str.sprintf(_t("%d Messages"), this.get("waiting_messages"));
- }
- web_client.set_title_part("im_messages", title);
- },
- // sessions and messages
- session_apply: function(active_session){
- // for chat windows
- if(active_session.is_minimized || (!active_session.is_minimized && active_session.state === 'closed')){
- this._super.apply(this, arguments);
- }
- // for client action
- if(!active_session.is_minimized){ // if not minimized,
- internal_bus.trigger('mail_session_receive', active_session);
- }
- },
- message_receive: function(message) {
- var actual_channel_ids = _.map(_.keys(this.sessions), function(item){
- return parseInt(item);
- });
- var message_channel_ids = message.channel_ids;
- if(_.intersection(actual_channel_ids, message_channel_ids).length){
- this._super.apply(this, arguments);
- }
- // broadcast the message to the NotificationButton and the InstantMessagingView
- internal_bus.trigger('mail_message_receive', message);
- // increment the needaction top counter
- if(message.needaction_partner_ids && _.contains(message.needaction_partner_ids, session.partner_id)){
- internal_bus.trigger('mail_needaction_new', 1);
- }
- },
-});
-
-
-/**
- * Widget Minimized Conversation
- *
- * Add layer of WebClient integration, and user fold state handling (comminication with server)
- **/
-mail_chat_common.Conversation.include({
- session_fold: function(state){
- var self = this;
- var args = arguments;
- var super_call = this._super;
- // broadcast the state changing
- return new Model("mail.channel").call("channel_fold", [], {"uuid" : this.get("session").uuid, "state" : state}).then(function(){
- super_call.apply(self, args);
- });
- },
-});
-
-/**
- * Widget : Patch for WebClient
- *
- * Create the conversation manager, and attach it to the web_client.
- **/
-WebClient.include({
- show_application: function(){
- var self = this;
- var args = arguments;
- var super_call = this._super;
- this.mail_conversation_manager = new ConversationManagerBackend(this);
- this.mail_conversation_manager.start().then(function(){
- super_call.apply(self, args);
- self.mail_conversation_manager.bus.start_polling();
- });
- },
-});
-
-
-/**
- * Widget Top Menu Notification Counter
- *
- * Counter of notification in the Systray Menu. Need to know if InstantMessagingView is displayed to
- * increment (or not) the counter. On click, should redirect to the client action.
- **/
-var NotificationTopButton = Widget.extend({
- template:'mail.chat.NotificationTopButton',
- events: {
- "click": "on_click",
- },
- init: function(){
- this._super.apply(this, arguments);
- this.set('counter', 0);
- },
- willStart: function(){
- var self = this;
- return $.when(session.rpc('/mail/needaction'), this._super()).then(function(needaction_count){
- self.set('counter', needaction_count);
- });
- },
- start: function() {
- this.on("change:counter", this, this.on_change_counter);
- // events
- internal_bus.on('mail_needaction_new', this, this.counter_increment);
- internal_bus.on('mail_needaction_done', this, this.counter_decrement);
- return this._super();
- },
- counter_increment: function(inc){
- this.set('counter', this.get('counter')+inc);
- },
- counter_decrement: function(dec){
- this.set('counter', this.get('counter')-dec);
- },
- on_change_counter: function() {
- this.$('.fa-comment').html(this.get('counter') || '');
- },
- on_click: function(e){
- e.preventDefault();
- this.do_action({
- type: 'ir.actions.client',
- tag: 'mail.chat.instant_messaging',
- params: {
- 'default_active_id': 'channel_inbox',
- },
- }, {
- clear_breadcrumbs: true,
- });
- },
-});
-
-SystrayMenu.Items.push(NotificationTopButton);
-
-
-/**
- * Abstract Class to 'Add More/Search' Widget
- *
- * Inputbox using jQueryUI autocomplete to fetch selection, like a Many2One field (on form view)
- * Used to create or pin a mail.channel or a res.partner on the InstantMessagingView
- **/
-var AbstractAddMoreSearch = Widget.extend({
- template: 'mail.chat.AbstractAddMoreSearch',
- events: {
- "click .o_mail_chat_add_more_text": "on_click_text",
- "blur .o_mail_chat_search_input": "_toggle_elements",
- },
- init: function(parent, options){
- this._super.apply(this, arguments);
- options = _.defaults(options || {}, {
- 'can_create': false,
- 'label': _t('+ Add More'),
- });
- this.limit = 10;
- this.can_create = options.can_create;
- this.label = options.label;
- },
- start: function(){
- this.last_search_val = false;
- this.$input = this.$('.o_mail_chat_search_input');
- this.$add_more_text = this.$('.o_mail_chat_add_more_text');
- this.$add_more_search_bar = this.$('.o_mail_chat_add_more_search_bar');
- this._bind_events();
- return this._super();
- },
- _bind_events: function(){
- // autocomplete
- var self = this;
- this.$input.autocomplete({
- source: function(request, response) {
- self.last_search_val = request.term;
- self.do_search(request.term).done(function(result){
- if(self.can_create){
- result.push({
- 'label': _.str.sprintf('<strong>'+_t("Create %s")+'</strong>', '<em>"'+self.last_search_val+'"</em>'),
- 'value': '_create',
- });
- }
- response(result);
- });
- },
- select: function(event, ui) {
- self.on_click_item(ui.item);
- },
- focus: function(event) {
- event.preventDefault();
- },
- html: true,
- });
- },
- // ui
- _toggle_elements: function(){
- this.$add_more_text.toggle();
- this.$add_more_search_bar.toggle();
- this.$input.val('');
- this.$input.focus();
- },
- on_click_text: function(event){
- event.preventDefault();
- this._toggle_elements();
- },
- // to be redefined
- do_search: function(){
- return $.when();
- },
- on_click_item: function(item){
- if(item.value === '_create'){
- if(this.last_search_val){
- this.trigger('item_create', this.last_search_val);
- }
- }else{
- this.trigger('item_clicked', item);
- }
- },
-});
-
-var PartnerAddMoreSearch = AbstractAddMoreSearch.extend({
- /**
- * Do the search call
- * @override
- */
- do_search: function(search_val){
- var Partner = new Model("res.partner");
- return Partner.call('im_search', [search_val, this.limit]).then(function(result){
- var values = [];
- _.each(result, function(user){
- values.push(_.extend(user, {
- 'value': user.name,
- 'label': user.name,
- }));
- });
- return values;
- });
- },
-});
-
-var ChannelAddMoreSearch = AbstractAddMoreSearch.extend({
- /**
- * Do the search call
- * @override
- */
- do_search: function(search_val){
- var Channel = new Model("mail.channel");
- return Channel.call('channel_search_to_join', [search_val]).then(function(result){
- var values = [];
- _.each(result, function(channel){
- values.push(_.extend(channel, {
- 'value': channel.name,
- 'label': channel.name,
- }));
- });
- return values;
- });
- },
-});
-
-var PrivateGroupAddMoreSearch = AbstractAddMoreSearch.extend({
- _bind_events: function(){
- // don't call the super to avoid autocomplete
- this.$input.on('keyup', this, this.on_keydown);
- },
- on_keydown: function(event){
- if(event.which === $.ui.keyCode.ENTER && this.$input.val()){
- this.trigger('item_create', this.$input.val());
- }
- },
-});
-
-
-/**
- * Widget : Invite People to Channel Dialog
- *
- * Popup containing a 'many2many_tags' custom input to select multiple partners.
- * Search user according to the input, and trigger event when selection is validated.
- **/
-var PartnerInviteDialog = Dialog.extend({
- dialog_title: _t('Invite people'),
- template: "mail.chat.PartnerInviteDialog",
- init: function(parent, options){
- options = _.defaults(options || {}, {
- buttons: [{
- text: _t("Invite"),
- close: true,
- classes: "btn-primary",
- click: _.bind(this.on_click_add, this),
- }],
- channel: undefined,
- });
- this._super.apply(this, arguments);
- this.set("partners", []);
- this.channel = options.channel;
- this.PartnersModel = new Model('res.partner');
- this.ChannelModel = new Model('mail.channel');
- this.limit = 20;
- },
- start: function(){
- var self = this;
- this.$partner_invite_input = this.$('.o_mail_chat_partner_invite_input');
- this.$partner_invite_input.select2({
- width: '100%',
- allowClear: true,
- multiple: true,
- formatResult: function(item){
- if(item.im_status === 'online'){
- return '<span class="fa fa-circle"> ' + item.text + '</span>';
- }
- return '<span class="fa fa-circle-o"> ' + item.text + '</span>';
- },
- query: function (query) {
- self.PartnersModel.call('im_search', [query.term, self.limit]).then(function(result){
- var data = [];
- _.each(result, function(partner){
- partner.text = partner.name;
- data.push(partner);
- });
- query.callback({results: data});
- });
- }
- });
- return this._super.apply(this, arguments);
- },
- on_click_add: function(){
- var self = this;
- var data = this.$partner_invite_input.select2('data');
- if(data.length >= 1){
- return this.ChannelModel.call('channel_invite', [], {"ids" : [this.channel.id], 'partner_ids': _.pluck(data, 'id')}).then(function(){
- var names = _.pluck(data, 'text').join(', ');
- self.do_notify(_t('New people'), _.str.sprintf(_t('You added <b>%s</b> to the conversation.'), names));
- });
- }
- },
-});
-
-/**
- * Client Action : Instant Messaging View, inspired by Slack.com
- *
- * Action replacing the Inbox, and the list of group (mailing list, multiple conversation, rooms, ...)
- * Includes real time messages (received and sent), creating group, channel, chat conversation, ...
- **/
-var ChatMailThread = Widget.extend(mail_thread.MailThreadMixin, ControlPanelMixin, {
- template: 'mail.chat.ChatMailThread',
- events: {
- "click .o_mail_thread_show_more > button": "message_load_history",
- // events from MailThreadMixin
- "click .o_mail_redirect": "on_click_redirect",
- "click .o_mail_expand": "on_message_body_toggle",
- "click .o_mail_thread_message_star": "on_message_star",
- // events specific for ChatMailThread
- "click .o_mail_chat_channel_item": "on_click_channel",
- "click .o_mail_chat_partner_item": "on_click_partner",
- "click .o_mail_chat_partner_unpin": "on_click_partner_unpin",
- "click .o_mail_thread_message_needaction": "on_message_needaction",
- },
- init: function (parent, action) {
- this._super.apply(this, arguments);
- // attributes
- this.action_manager = parent;
- this.help_message = action.help || '';
- this.context = action.context;
- this.action = action;
- this.chatter_needaction_auto = false;
- this.options = this.action.params;
- // mail thread mixin
- mail_thread.MailThreadMixin.init.call(this);
- // components : conversation manager and search widget (channel_type + '_search_widget')
- this.conv_manager = web_client.mail_conversation_manager;
- this.channel_search_widget = new ChannelAddMoreSearch(this, {'label': _t('+ Subscribe'), 'can_create': true});
- this.group_search_widget = new PrivateGroupAddMoreSearch(this, {'label': _t('+ New private group'), 'can_create': true});
- this.partner_search_widget = new PartnerAddMoreSearch(this);
- // options (update the default of MailThreadMixin)
- this.options = _.extend(this.options, {
- 'display_document_link': true,
- 'display_needaction_button': true,
- 'emoji_list': this.conv_manager.emoji_list,
- 'default_username': _t('Anonymous'),
- });
- this.emoji_set_substitution(this.conv_manager.emoji_list);
- // channel business
- this.channels = {};
- this.mapping = {}; // mapping partner_id/channel_id for 'direct message' channel
- this.set('current_channel_id', false);
- this.set('needaction_inbox_counter', 0);
- this.search_domain = [];
- // channel slots
- this.set('channel_channel', []);
- this.set('channel_direct_message', []);
- this.set('channel_private_group', []);
- this.set('partners', []);
- // models
- this.ChannelModel = new Model('mail.channel', this.context);
- // control panel items
- this.control_elements = {};
- },
- willStart: function(){
- var self = this;
- return session.rpc('/mail/client_action').then(function(result){
- self.chatter_needaction_auto = result.chatter_needaction_auto;
- self.set('needaction_inbox_counter', result.needaction_inbox_counter);
- self.set('partners', result.channel_slots.partners);
- self.mapping = result.channel_slots.mapping;
- self._channel_slot(_.omit(result.channel_slots, 'partners', 'mapping'));
- });
- },
- start: function(){
- var self = this;
- this._super.apply(this, arguments);
-
- this.$messages = this.$('.o_mail_chat_messages');
-
- mail_thread.MailThreadMixin.start.call(this);
- // channel business events
- this.on("change:current_channel_id", this, this.channel_change);
- this.on("change:channel_channel", this, function(){
- self.channel_render('channel_channel');
- });
- this.on("change:channel_private_group", this, function(){
- self.channel_render('channel_private_group');
- });
- this.on("change:partners", this, this.partner_render);
-
- // search widget for channel
- this.channel_search_widget.insertAfter(this.$('.o_mail_chat_channel_slot_channel_channel'));
- this.channel_search_widget.on('item_create', this, function(name){
- self.channel_create(name, 'public');
- });
- this.channel_search_widget.on('item_clicked', this, function(item){
- self.channel_join_and_get_info(item.id).then(function(channel){
- self.channel_apply(channel);
- });
- });
- // search widget for direct message
- this.partner_search_widget.insertAfter(this.$('.o_mail_chat_channel_slot_partners'));
- this.partner_search_widget.on('item_clicked', this, function(item){
- self.channel_get([item.id]);
- self.partner_add(item);
- });
- // search widget for private group
- this.group_search_widget.insertAfter(this.$('.o_mail_chat_channel_slot_channel_private_group'));
- this.group_search_widget.on('item_create', this, function(name){
- self.channel_create(name, 'private');
- });
-
- // needaction inbox counter
- this.on('change:needaction_inbox_counter', this, this.needaction_inbox_change);
-
- return $.when(this._super.apply(this, arguments), this.cp_render_searchview()).then(function(){
- // render control panel's elements
- self.cp_render_elements();
- // apply default channel
- var channel_id = self.context.active_id || self.action.params.default_active_id || 'channel_inbox';
- if(!_.isString(channel_id)){
- if(_.contains(_.keys(self.channels), channel_id)){
- self.set('current_channel_id', channel_id);
- }else{
- self.channel_info(channel_id).then(function(channel){
- self.channel_apply(channel);
- });
- }
- }else{
- self.set('current_channel_id', channel_id);
- }
- // internal communication (bind here to avoid receving message from bus when client action still not totally ready)
- internal_bus.on('mail_message_receive', self, self.message_receive);
- internal_bus.on('mail_session_receive', self, self.channel_receive);
- // needaction : the inbox has the same counter as the needaction top counter
- internal_bus.on('mail_needaction_new', this, function(inc){
- self.set('needaction_inbox_counter' , self.get('needaction_inbox_counter') + inc);
- });
- internal_bus.on('mail_needaction_done', this, function(dec){
- self.set('needaction_inbox_counter' , self.get('needaction_inbox_counter') - dec);
- });
- });
- },
- // event actions
- on_click_channel: function(event){
- event.preventDefault();
- var channel_id = this.$(event.currentTarget).data('channel-id');
- this.set('current_channel_id', channel_id);
- },
- on_click_partner: function(event){
- if(!this.$(event.target).hasClass('o_mail_chat_channel_unpin')){
- event.preventDefault();
- var partner_id = this.$(event.currentTarget).data('partner-id');
- if(this.mapping[partner_id]){ // don't fetch if channel already in local
- this.set('current_channel_id', this.mapping[partner_id]);
- }else{
- this.channel_get([partner_id]);
- }
- }
- },
- on_click_partner_unpin: function(event){
- event.preventDefault();
- var self = this;
- var $source = this.$(event.currentTarget);
- var partner_id = $source.data('partner-id');
- var channel_id = this.mapping[partner_id];
- var channel = this.channels[channel_id];
- this.channel_pin(channel.uuid, false).then(function(){
- self.set('partners', _.filter(self.get('partners'), function(p){ return p.id !== partner_id; }));
- self.channel_remove(channel_id);
- delete self.mapping[partner_id];
- // if unpin current channel, switch to inbox
- if(self.get('current_channel_id') === channel_id){
- self.set('current_channel_id', 'channel_inbox');
- }
- });
- },
- on_click_button_minimize: function(event){
- event.preventDefault();
- var current_channel = this.channels[this.get('current_channel_id')];
- if(current_channel){
- var channel_uuid = current_channel.uuid;
- return this.ChannelModel.call("channel_minimize", [channel_uuid, true]);
- }
- return $.Deferred().reject();
- },
- on_click_button_invite: function(){
- new PartnerInviteDialog(this, {
- title: _.str.sprintf(_t('Invite people to %s'), this.get_current_channel_name()),
- channel: this.channels[this.get('current_channel_id')],
- }).open();
- },
- on_click_button_unsubscribe: function(){
- var self = this;
- this.ChannelModel.call('action_unfollow', [[this.get('current_channel_id')]]).then(function(){
- var channel = self.channels[self.get('current_channel_id')];
- var slot = self.get_channel_slot(channel);
- self.set(slot, _.filter(self.get(slot), function(c){ return c.id !== channel.id; }));
- self.do_notify(_t('Unsubscribe'), _.str.sprintf(_t('You unsubscribe from <b>%s</b>.'), self.get_current_channel_name()));
- self.set('current_channel_id', 'channel_inbox'); // jump to inbox
- });
- },
- on_click_button_settings: function(){
- this.do_action({
- type: 'ir.actions.act_window',
- res_model: "mail.channel",
- res_id: this.get('current_channel_id'),
- views: [[false, 'form']],
- target: 'current'
- }, {
- 'on_reverse_breadcrumb': this.on_reverse_breadcrumb,
- });
- },
- on_message_needaction: function(event){
- var self = this;
- mail_thread.MailThreadMixin.on_message_needaction.call(this, event).then(function(message_id){
- // decrement the needaction top counter
- internal_bus.trigger('mail_needaction_done', 1);
- // decrement the channel labels
- var treated_messages = _.filter(self.get('messages'), function(m){ return m.id == message_id; });
- if(treated_messages.length){
- self.needaction_decrement(treated_messages[0].channel_ids || []);
- }
- });
- },
- // control panel
- cp_update: function(){
- // toggle cp elements
- var current_channel_id = this.get('current_channel_id');
- if(_.isString(current_channel_id)){
- this.control_elements.$buttons.hide();
- this.control_elements.$sidebar.hide();
- }else{
- this.control_elements.$buttons.show();
- if(this.channels[current_channel_id].channel_type === 'chat'){
- this.control_elements.$buttons.find('.o_mail_chat_button_invite').hide();
- this.control_elements.$sidebar.hide();
- } else {
- this.control_elements.$buttons.find('.o_mail_chat_button_invite').show();
- this.control_elements.$sidebar.show();
- }
- }
-
- // update control panel
- var status = {
- breadcrumbs: this.action_manager.get_breadcrumbs(),
- cp_content: {
- $buttons: this.control_elements.$buttons,
- $searchview: this.control_elements.$searchview,
- $searchview_buttons: this.control_elements.$searchview_buttons,
- $sidebar: this.control_elements.$sidebar,
- },
- searchview: this.searchview,
- };
- this.update_control_panel(status);
- },
- cp_render_elements: function() {
- this.control_elements.$buttons = $(QWeb.render("mail.chat.ControlButtons", {}));
- this.control_elements.$buttons.on('click', '.o_mail_chat_button_invite', _.bind(this.on_click_button_invite, this));
- this.control_elements.$buttons.on('click', '.o_mail_chat_button_minimize', _.bind(this.on_click_button_minimize, this));
-
- var $sidebar_container = $('<div>');
- new Sidebar(this, {
- sections: [
- {name: 'more', label: _t('More')},
- ],
- items: {
- more: [
- {label: _t('Unsubscribe'), classname: 'o_mail_chat_button_unsubscribe', callback: this.on_click_button_unsubscribe},
- {label: _t('Settings'), classname: 'o_mail_chat_button_settings', callback: this.on_click_button_settings},
- ],
- },
- }).appendTo($sidebar_container);
- this.control_elements.$sidebar = $sidebar_container.contents();
- },
- cp_render_searchview: function(){
- var self = this;
- var options = {
- $buttons: $("<div>"),
- action: this.action,
- disable_groupby: true,
- };
- var view_id = (this.action && this.action.search_view_id && this.action.search_view_id[0]) || false;
- this.searchview = new SearchView(this, this.MessageDatasetSearch, view_id, {}, options);
-
- this.searchview.on('search_data', this, this.on_search);
- return $.when(this.searchview.appendTo($("<div>"))).done(function() {
- self.control_elements.$searchview = self.searchview.$el;
- self.control_elements.$searchview_buttons = self.searchview.$buttons.contents();
- });
- },
- /**
- * Method call when action if done after redirecting (using 'on_click_redirect')
- * @override
- */
- on_reverse_breadcrumb: function(){
- var current_channel_id = this.get('current_channel_id');
- this.cp_update(); // do not reload the client action, just display it, but a refresh of the control panel is needed.
- // push state
- this.action_manager.do_push_state({
- action: this.action.id,
- active_id: current_channel_id,
- });
- },
- // messages search methods
- on_search: function(domains, contexts, groupbys){
- var self = this;
- return pyeval.eval_domains_and_contexts({
- domains: [[]].concat(domains || []),
- contexts: [this.context].concat(contexts || []),
- group_by_seq: groupbys || []
- }).done(function(results){
- if (results.error) {
- throw new Error(_.str.sprintf(_t("Failed to evaluate search criterions")+": \n%s", JSON.stringify(results.error)));
- }
- // modify the search domain and do search
- self.search_domain = results.domain;
- return self.message_load_new();
- });
- },
- // channels
- /**
- * Set the channel slot
- * @param {Object[]} fetch_result : should contains only the slot name (as key) and the list of channel header as value.
- */
- _channel_slot: function(fetch_result){
- var self = this;
- var channel_slots = _.keys(fetch_result);
- _.each(channel_slots, function(slot){
- // update the channel slot
- self.set(slot, fetch_result[slot]);
- // flatten the result : update the complete channel list
- _.each(fetch_result[slot], function(channel){
- self.channels[channel.id] = channel;
- });
- });
- },
- /**
- * Apply a channel means adding it, and swith to it
- * @param {Object} channel : channel header
- */
- channel_apply: function(channel){
- this.channel_add(channel);
- this.set('current_channel_id', channel.id);
- },
- /**
- * Add the given channel, or update it if already exists and loaded
- * @param {Object} channel : channel header to add
- */
- channel_add: function(channel){
- var channel_slot = this.get_channel_slot(channel);
- var existing = this.get(channel_slot);
- if(_.contains(_.pluck(existing, 'id'), channel.id)){
- // update the old channel
- var filtered_channels = _.filter(existing, function(item){ return item.id != channel.id; });
- this.set(channel_slot, filtered_channels.concat([channel]));
- }else{
- // simply add the reveiced channel
- this.set(channel_slot, existing.concat([channel]));
- }
- // also update the flatten list
- this.channels[channel.id] = channel;
-
- // update the mapping for 'direct message' channel, and the partner list
- if(channel_slot === 'channel_direct_message'){
- var partner = channel.direct_partner[0];
- this.mapping[partner.id] = channel.id;
- this.partner_add(partner);
- }
- },
- channel_remove: function(channel_id){
- var channel = this.channels[channel_id];
- var slot = this.get_channel_slot(channel);
- this.set(slot, _.filter(this.get(slot), function(c){ return c.id !== channel_id; }));
- delete this.channels[channel_id];
- },
- /**
- * Get the channel the current user has with the given partner, and get the channel header
- * @param {Number[]} partner_ids : list of res.partner identifier
- */
- channel_get: function(partner_ids){
- var self = this;
- return this.ChannelModel.call('channel_get', [partner_ids]).then(function(channel){
- self.channel_apply(channel);
- });
- },
- /**
- * Create a channel with the given name and type, and apply it
- * @param {String} channel_name : the name of the channel
- * @param {String} privacy : the privacy of the channel (groups, public, ...)
- */
- channel_create: function(channel_name, privacy){
- var self = this;
- return this.ChannelModel.call('channel_create', [channel_name, privacy]).then(function(channel){
- self.channel_apply(channel);
- });
- },
- channel_info: function(channel_id){
- return this.ChannelModel.call('channel_info', [[channel_id]]).then(function(channels){
- return channels[0];
- });
- },
- channel_pin: function(uuid, pinned){
- return this.ChannelModel.call('channel_pin', [uuid, pinned]);
- },
- channel_join_and_get_info: function(channel_id){
- return this.ChannelModel.call('channel_join_and_get_info', [[channel_id]]);
- },
- channel_change: function(){
- var self = this;
- var current_channel_id = this.get('current_channel_id');
- // mail chat compose message (destroy and replace it)
- if (this.mail_chat_compose_message) {
- this.mail_chat_compose_message.destroy();
- }
- this.mail_chat_compose_message = new mail_thread.MailComposeMessage(this, new data.DataSetSearch(this, 'mail.channel', this.context), {
- 'emoji_list': this.options.emoji_list,
- 'context': _.extend(this.context, {
- 'default_res_id': current_channel_id,
- }),
- 'display_mode': 'chat',
- });
- if(_.isString(current_channel_id)){
- this.$('.o_mail_chat_composer_wrapper').hide();
- }else{
- this.$('.o_mail_chat_composer_wrapper').show();
- }
- this.mail_chat_compose_message.appendTo(this.$('.o_mail_chat_composer_wrapper'));
- this.mail_chat_compose_message.focus();
-
- // push state (the action is referred by action_manager, and no reloaded when jumping
- // channel, so update context is required)
- this.action.context.active_id = current_channel_id;
- this.action.context.active_ids = [current_channel_id];
- web_client.action_manager.do_push_state({
- action: this.action.id,
- active_id: current_channel_id,
- });
-
- // update title (to display in the breadcrumbs) according to current channel
- this.set('title', this.get_current_channel_name());
-
- // update control panel
- this.cp_update();
-
- // fetch the messages
- return this.message_load_new().then(function(){
- // if normal channel, update last message id, and unbold
- var def = $.Deferred().resolve();
- if(_.isNumber(current_channel_id)){
- def = self.ChannelModel.call('channel_seen', [[current_channel_id]]);
- }else{
- // auto treat needaction from inbox
- if(current_channel_id === 'channel_inbox' && self.chatter_needaction_auto){
- def = self.MessageDatasetSearch._model.query(['id', 'channel_ids']).filter([['needaction', '=', true]]).all().then(function(messages){
- // get needaction message ids
- var message_ids = _.pluck(messages, 'id');
- if(message_ids){
- // call to unlink
- self.MessageDatasetSearch._model.call('set_message_done',[message_ids]).then(function(){
- // decrement channel items in batch
- var flatten_channel_ids = _.flatten(_.pluck(messages, 'channel_ids'));
- var channel_count = _.countBy(flatten_channel_ids, function(cid) {
- return cid;
- });
- _.each(_.keys(channel_count), function(cid){
- self.needaction_decrement([cid], channel_count[cid]);
- });
- // decrement the needaction top counter
- internal_bus.trigger('mail_needaction_done', message_ids.length);
- });
- }
- });
- }
- }
- def.then(function(){
- self._toggle_unread_message(current_channel_id, false, true);
- self._scroll();
- });
- });
- },
- channel_render: function(channel_slot){
- this.$('.o_mail_chat_channel_slot_' + channel_slot).replaceWith(QWeb.render("mail.chat.ChatMailThread.channels", {'widget': this, 'channel_slot': channel_slot}));
- },
- // partners
- partner_add: function(partner){
- var partners = _.filter(this.get('partners'), function(p){ return p.id != partner.id; });
- this.set('partners', partners.concat([partner]));
- },
- partner_render: function(){
- this.$('.o_mail_chat_channel_slot_partners').replaceWith(QWeb.render("mail.chat.ChatMailThread.partners", {'widget': this}));
- },
- // needaction
- needaction_increment: function(channel_ids, inc){
- var self = this;
- _.each(channel_ids, function(channel_id){
- if(self.channels[channel_id]){
- var count = (self.channels[channel_id].message_needaction_counter || 0) + (inc || 1);
- self.channels[channel_id].message_needaction_counter = count;
- self.$('.o_mail_chat_needaction[data-channel-id='+channel_id+']').html(count);
- self.$('.o_mail_chat_needaction[data-channel-id='+channel_id+']').show();
- }
- });
- },
- needaction_decrement: function(channel_ids, dec){
- var self = this;
- _.each(channel_ids, function(channel_id){
- if(self.channels[channel_id]){
- var count = (self.channels[channel_id].message_needaction_counter || 0) - (dec || 1);
- self.channels[channel_id].message_needaction_counter = count;
- self.$('.o_mail_chat_needaction[data-channel-id='+channel_id+']').html(count);
- if(count <= 0){
- self.$('.o_mail_chat_needaction[data-channel-id='+channel_id+']').show();
- }
- }
- });
- },
- needaction_inbox_change: function(){
- var count = this.get('needaction_inbox_counter');
- var $elem = this.$('.o_mail_chat_needaction[data-channel-id="channel_inbox"]');
- $elem.html(count);
- if(count > 0){
- $elem.show();
- }else{
- $elem.hide();
- }
- },
- // from bus
- channel_receive: function(channel){
- this.channel_add(channel);
- },
- message_receive: function(message){
- var self = this;
- var in_current_channel = _.contains(message.channel_ids, this.get('current_channel_id'));
- // if current channel should reveice message, give it to it
- if(in_current_channel){
- this.message_insert([message]);
- }
- // for other message channel, get the channel if not loaded yet, and bolded them
- var other_message_channel_ids = _.without(message.channel_ids, this.get('current_channel_id'));
- var active_channel_ids = _.map(_.keys(this.channels), function(cid){
- return parseInt(cid);
- }); // integer as key of a dict is cast as string in javascript
- var channel_to_fetch = _.difference(other_message_channel_ids, active_channel_ids);
- // fetch unloaded channels and add it
- var def = $.Deferred();
- if(channel_to_fetch.length >= 1){
- def = this.ChannelModel.call("channel_info", [], {"ids" : channel_to_fetch}).then(function(channels){
- _.each(channels, function(channel){
- self.channel_add(channel);
- });
- });
- }else{
- def.resolve([]);
- }
- // bold the channel to indicate unread messages
- def.then(function(){
- // bold channel having unread messages
- _.each(other_message_channel_ids, function(channel_id){
- self._toggle_unread_message(channel_id, true);
- });
- // auto scroll to bottom if the message arrived in the current channel
- if(in_current_channel){
- self._scroll();
- }
- });
- // if needaction, then increment the label
- if(message.needaction_partner_ids && _.contains(message.needaction_partner_ids, session.partner_id)){
- this.needaction_increment(message.channel_ids || []);
- }
- },
- // utils function
- get_channel_slot: function(channel){
- if(channel.channel_type === 'channel'){
- if(channel.public === 'private'){
- return 'channel_private_group';
- }
- return 'channel_channel';
- }
- if(channel.channel_type === 'chat'){
- return 'channel_direct_message';
- }
- },
- get_current_channel_name: function(){
- var current_channel_id = this.get('current_channel_id');
- var current_channel = this.channels[current_channel_id];
- var current_channel_name = current_channel && current_channel.name || _t('Unknown');
- // virtual channel id (for inbox, or starred channel)
- if(_.isString(current_channel_id)){
- if(current_channel_id == 'channel_inbox'){
- current_channel_name = _t('Inbox');
- }
- if(current_channel_id == 'channel_starred'){
- current_channel_name = _t('Starred');
- }
- }
- return current_channel_name;
- },
- _toggle_unread_message: function(channel_id, add_or_remove, set_as_active){
- var partner_id = false;
- var inverse_mapping = _.invert(this.mapping);
- // toggle bold channel/partner item
- this.$('.o_mail_chat_sidebar .o_mail_chat_channel_item[data-channel-id="'+channel_id+'"]').toggleClass('o_mail_chat_channel_unread', add_or_remove);
- if(_.contains(_.keys(inverse_mapping), channel_id.toString())){
- partner_id = parseInt(inverse_mapping[channel_id]);
- this.$('.o_mail_chat_sidebar .o_mail_chat_partner_item[data-partner-id="'+partner_id+'"]').toggleClass('o_mail_chat_channel_unread', add_or_remove);
- }
- // set the channel/partner item as the active one
- if(set_as_active){
- this.$('.o_mail_chat_sidebar .o_mail_chat_channel_item, .o_mail_chat_sidebar .o_mail_chat_partner_item').find('a').removeClass('active');
- this.$('.o_mail_chat_sidebar .o_mail_chat_channel_item[data-channel-id="'+channel_id+'"]').find('a').addClass('active');
- if(partner_id){
- this.$('.o_mail_chat_sidebar .o_mail_chat_partner_item[data-partner-id="'+partner_id+'"]').find('a').addClass('active');
- }
- }
- },
- _scroll: function(){
- var current_channel_id = this.get('current_channel_id');
- var current_channel = this.channels[current_channel_id];
- var last_seen_message;
- if(_.isNumber(current_channel_id)){
- if(current_channel.seen_message_id){
- last_seen_message = this.$(".o_mail_thread_message[data-message-id="+current_channel.seen_message_id+"]");
- if(last_seen_message.length){
- this.$messages.scrollTop(last_seen_message.offset().top);
- }else{
- this.$messages.scrollTop(0);
- }
- }else{
- this.$messages.scrollTop(this.$messages[0].scrollHeight);
- }
- current_channel.seen_message_id = false;
- }else{
- this.$messages.scrollTop(this.$messages[0].scrollHeight);
- }
- },
- /**
- * Render the messages
- * @override
- */
- message_render: function(){
- this.$messages.html(QWeb.render('mail.chat.ChatMailThread.content', {'widget': this}));
- },
- /**
- * Return the message domain for the current channel
- * @override
- */
- get_message_domain: function(){
- // default channel domain
- var current_channel_id = this.get('current_channel_id');
- var domain = [['channel_ids', 'in', current_channel_id]];
- // virtual channel id (for inbox, or starred channel)
- if(_.isString(current_channel_id)){
- if(current_channel_id == 'channel_inbox'){
- domain = [['needaction', '=', true]];
- }
- if(current_channel_id == 'channel_starred'){
- domain = [['starred', '=', true]];
- }
- }
- // add search domain
- domain = domain.concat(this.search_domain);
- return domain;
- },
- /**
- * Extend message_load_history to keep scroll position at last seen message
- */
- message_load_history: function() {
- var self = this;
- var oldest_msg_selector = '.o_mail_thread_message[data-message-id="' + this.get('messages')[0].id + '"]';
- var offset = -framework.getPosition(document.querySelector(oldest_msg_selector)).top;
- mail_thread.MailThreadMixin.message_load_history.call(this).then(function() {
- offset += framework.getPosition(document.querySelector(oldest_msg_selector)).top;
- self.$messages.scrollTop(offset);
- });
- },
-});
-
-core.action_registry.add('mail.chat.instant_messaging', ChatMailThread);
-
-
-return {
- ChatMailThread: ChatMailThread,
-};
-
-});