Browse Source

Initial Commit

pull/81/head
SHEREEF PT 8 years ago
parent
commit
51a931ee0f
  1. 22
      sent_mails/__init__.py
  2. 41
      sent_mails/__openerp__.py
  3. BIN
      sent_mails/static/description/cybro_logo.png
  4. BIN
      sent_mails/static/description/icon.png
  5. 44
      sent_mails/static/description/index.html
  6. BIN
      sent_mails/static/description/sent_mails_demo.png
  7. 180
      sent_mails/static/scripts/openerp_mailgate.py
  8. 1100
      sent_mails/static/src/js/chat_manager_sent_mail.js
  9. 666
      sent_mails/static/src/js/client_action_sent_mail.js
  10. 19
      sent_mails/static/src/xml/client_action_sent_mails.xml
  11. 27
      sent_mails/views/get_sent_mails.xml

22
sent_mails/__init__.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2009-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
# Author: Nilmar Shereef(<http://www.cybrosys.com>)
# you can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# It is forbidden to publish, distribute, sublicense, or sell copies
# of the Software or modified copies of the Software.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

41
sent_mails/__openerp__.py

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2009-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
# Author: Nilmar Shereef(<http://www.cybrosys.com>)
# you can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# It is forbidden to publish, distribute, sublicense, or sell copies
# of the Software or modified copies of the Software.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Sent Mails',
'version': '1.0',
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
'website': 'http://www.cybrosys.com',
"category": "Discuss",
'depends': ['base', 'mail'],
'license': 'AGPL-3',
'data': [
'views/get_sent_mails.xml',
],
'qweb': [
'static/src/xml/client_action_sent_mails.xml',
],
'installable': True,
'auto_install': False
}

BIN
sent_mails/static/description/cybro_logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
sent_mails/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

44
sent_mails/static/description/index.html

@ -0,0 +1,44 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Show sent mails</h2>
<h3 class="oe_slogan">Shows the mails or discussions sent by current user</h3>
<h4 class="oe_slogan">Author : Cybrosys Techno Solutions, www.cybrosys.com</h4>
</div>
<div class="oe_row oe_spaced">
<div class="oe_span12">
<p class='oe_mt32'>
&#x261B;This module enables the feature to display the mails and discussions done by current user
</p>
<div class="oe_centeralign oe_websiteonly">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row">
<h2 class="oe_slogan">Sent Mail Menu Under Discuss</h2>
<div class="oe_span6">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="sent_mails_demo.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<h2 class="oe_slogan" style="margin-top:20px;" >Need Any Help?</h2>
<div class="oe_slogan" style="margin-top:10px !important;">
<a class="btn btn-primary btn-lg mt8"
style="color: #FFFFFF !important;" href="http://www.cybrosys.com"><i
class="fa fa-envelope"></i> Email </a> <a
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;"
href="http://www.cybrosys.com/contact/"><i
class="fa fa-phone"></i> Contact Us </a> <a
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;"
href="http://www.cybrosys.com/odoo-customization-and-installation/"><i
class="fa fa-check-square"></i> Request Customization </a>
</div>
<img src="cybro_logo.png" style="width: 190px; margin-bottom: 20px;" class="center-block">
</section>

BIN
sent_mails/static/description/sent_mails_demo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

180
sent_mails/static/scripts/openerp_mailgate.py

@ -0,0 +1,180 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
"""
openerp_mailgate.py
"""
import cgitb
import time
import optparse
import sys
import xmlrpclib
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
from email import Encoders
class DefaultConfig(object):
"""
Default configuration
"""
OPENERP_DEFAULT_USER_ID = 1
OPENERP_DEFAULT_PASSWORD = 'admin'
OPENERP_HOSTNAME = 'localhost'
OPENERP_PORT = 8069
OPENERP_DEFAULT_DATABASE = 'openerp'
MAIL_ERROR = 'error@example.com'
MAIL_SERVER = 'smtp.example.com'
MAIL_SERVER_PORT = 25
MAIL_ADMINS = ('info@example.com',)
config = DefaultConfig()
def send_mail(_from_, to_, subject, text, files=None, server=config.MAIL_SERVER, port=config.MAIL_SERVER_PORT):
assert isinstance(to_, (list, tuple))
if files is None:
files = []
msg = MIMEMultipart()
msg['From'] = _from_
msg['To'] = COMMASPACE.join(to_)
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject
msg.attach( MIMEText(text) )
for file_name, file_content in files:
part = MIMEBase('application', "octet-stream")
part.set_payload( file_content )
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"'
% file_name)
msg.attach(part)
smtp = smtplib.SMTP(server, port=port)
smtp.sendmail(_from_, to_, msg.as_string() )
smtp.close()
class RPCProxy(object):
def __init__(self, uid, passwd,
host=config.OPENERP_HOSTNAME,
port=config.OPENERP_PORT,
path='object',
dbname=config.OPENERP_DEFAULT_DATABASE):
self.rpc = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/%s' % (host, port, path), allow_none=True)
self.user_id = uid
self.passwd = passwd
self.dbname = dbname
def __call__(self, *request, **kwargs):
return self.rpc.execute(self.dbname, self.user_id, self.passwd, *request, **kwargs)
class EmailParser(object):
def __init__(self, uid, password, dbname, host, port, model=False, email_default=False):
self.rpc = RPCProxy(uid, password, host=host, port=port, dbname=dbname)
if model:
try:
self.model_id = int(model)
self.model = str(model)
except:
self.model_id = self.rpc('ir.model', 'search', [('model', '=', model)])[0]
self.model = str(model)
self.email_default = email_default
def parse(self, message, custom_values=None, save_original=None):
# pass message as bytes because we don't know its encoding until we parse its headers
# and hence can't convert it to utf-8 for transport
return self.rpc('mail.thread',
'message_process',
self.model,
xmlrpclib.Binary(message),
custom_values or {},
save_original or False)
def configure_parser():
parser = optparse.OptionParser(usage='usage: %prog [options]', version='%prog v1.1')
group = optparse.OptionGroup(parser, "Note",
"This program parse a mail from standard input and communicate "
"with the Odoo server for case management in the CRM module.")
parser.add_option_group(group)
parser.add_option("-u", "--user", dest="userid",
help="Odoo user id to connect with",
default=config.OPENERP_DEFAULT_USER_ID, type='int')
parser.add_option("-p", "--password", dest="password",
help="Odoo user password",
default=config.OPENERP_DEFAULT_PASSWORD)
parser.add_option("-o", "--model", dest="model",
help="Name or ID of destination model",
default="crm.lead")
parser.add_option("-m", "--default", dest="default",
help="Admin email for error notifications.",
default=None)
parser.add_option("-d", "--dbname", dest="dbname",
help="Odoo database name (default: %default)",
default=config.OPENERP_DEFAULT_DATABASE)
parser.add_option("--host", dest="host",
help="Odoo Server hostname",
default=config.OPENERP_HOSTNAME)
parser.add_option("--port", dest="port",
help="Odoo Server XML-RPC port number",
default=config.OPENERP_PORT)
parser.add_option("--custom-values", dest="custom_values",
help="Dictionary of extra values to pass when creating records",
default=None)
parser.add_option("-s", dest="save_original",
action="store_true",
help="Keep a full copy of the email source attached to each message",
default=False)
return parser
def main():
"""
Receive the email via the stdin and send it to the OpenERP Server
"""
parser = configure_parser()
(options, args) = parser.parse_args()
email_parser = EmailParser(options.userid,
options.password,
options.dbname,
options.host,
options.port,
model=options.model,
email_default= options.default)
msg_txt = sys.stdin.read()
custom_values = {}
try:
custom_values = dict(eval(options.custom_values or "{}" ))
except:
import traceback
traceback.print_exc()
try:
email_parser.parse(msg_txt, custom_values, options.save_original or False)
except Exception:
msg = '\n'.join([
'parameters',
'==========',
'%r' % (options,),
'traceback',
'=========',
'%s' % (cgitb.text(sys.exc_info())),
])
subject = '[Odoo]:ERROR: Mailgateway - %s' % time.strftime('%Y-%m-%d %H:%M:%S')
send_mail(
config.MAIL_ERROR,
config.MAIL_ADMINS,
subject, msg, files=[('message.txt', msg_txt)]
)
sys.stderr.write("Failed to deliver email to Odoo Server, sending error notification to %s\n" % config.MAIL_ADMINS)
if __name__ == '__main__':
main()

1100
sent_mails/static/src/js/chat_manager_sent_mail.js

File diff suppressed because it is too large

666
sent_mails/static/src/js/client_action_sent_mail.js

@ -0,0 +1,666 @@
odoo.define('mail.chat_client_action', function (require) {
"use strict";
var chat_manager = require('mail.chat_manager');
var composer = require('mail.composer');
var ChatThread = require('mail.ChatThread');
var config = require('web.config');
var ControlPanelMixin = require('web.ControlPanelMixin');
var core = require('web.core');
var data = require('web.data');
var Dialog = require('web.Dialog');
var framework = require('web.framework');
var Model = require('web.Model');
var pyeval = require('web.pyeval');
var SearchView = require('web.SearchView');
var Widget = require('web.Widget');
var QWeb = core.qweb;
var _t = core._t;
/**
* 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.PartnerInviteDialog",
init: function(parent, title, channel_id){
this.channel_id = channel_id;
this._super(parent, {
title: title,
size: "medium",
buttons: [{
text: _t("Invite"),
close: true,
classes: "btn-primary",
click: _.bind(this.on_click_add, this),
}],
});
this.PartnersModel = new Model('res.partner');
},
start: function(){
var self = this;
this.$input = this.$('.o_mail_chat_partner_invite_input');
this.$input.select2({
width: '100%',
allowClear: true,
multiple: true,
formatResult: function(item) {
var status = QWeb.render('mail.chat.UserStatus', {status: item.im_status});
return $('<span>').text(item.text).prepend(status);
},
query: function (query) {
self.PartnersModel.call('im_search', [query.term, 20]).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.$input.select2('data');
if(data.length >= 1){
var ChannelModel = new Model('mail.channel');
return ChannelModel.call('channel_invite', [], {ids : [this.channel_id], partner_ids: _.pluck(data, 'id')})
.then(function(){
var names = _.escape(_.pluck(data, 'text').join(', '));
var notification = _.str.sprintf(_t('You added <b>%s</b> to the conversation.'), names);
self.do_notify(_t('New people'), notification);
});
}
},
});
var ChatAction = Widget.extend(ControlPanelMixin, {
template: 'mail.client_action',
events: {
"click .o_mail_chat_channel_item": function (event) {
event.preventDefault();
var channel_id = this.$(event.currentTarget).data('channel-id');
this.set_channel(chat_manager.get_channel(channel_id));
},
"click .o_mail_sidebar_title .o_add": function (event) {
event.preventDefault();
var type = $(event.target).data("type");
this.$('.o_mail_add_channel[data-type=' + type + ']')
.show()
.find("input").focus();
},
"blur .o_mail_add_channel input": function () {
this.$('.o_mail_add_channel')
.hide();
},
"click .o_mail_partner_unpin": function (event) {
event.stopPropagation();
var channel_id = $(event.target).data("channel-id");
this.unsubscribe_from_channel(chat_manager.get_channel(channel_id));
},
"click .o_snackbar_undo": function (event) {
event.preventDefault();
var channel = this.channel;
this.$snackbar.remove();
this.clear_needactions_def.then(function (msgs_ids) {
chat_manager.undo_mark_as_read(msgs_ids, channel);
});
},
"click .o_mail_annoying_notification_bar .fa-close": function () {
this.$(".o_mail_annoying_notification_bar").slideUp();
},
"click .o_mail_request_permission": function (event) {
event.preventDefault();
this.$(".o_mail_annoying_notification_bar").slideUp();
var def = window.Notification.requestPermission();
if (def) {
def.then(function () {
chat_manager.send_native_notification('Permission granted', 'Odoo has now the permission to send you native notifications on this device.');
});
}
},
"keydown": function (event) {
if (event.which === $.ui.keyCode.ESCAPE && this.selected_message) {
this.unselect_message();
}
},
},
on_attach_callback: function () {
chat_manager.bus.trigger('client_action_open', true);
if (this.channel) {
this.thread.scroll_to({offset: this.channels_scrolltop[this.channel.id]});
}
},
on_detach_callback: function () {
chat_manager.bus.trigger('client_action_open', false);
this.channels_scrolltop[this.channel.id] = this.thread.get_scrolltop();
},
init: function(parent, action, options) {
this._super.apply(this, arguments);
this.action_manager = parent;
this.domain = [];
this.action = action;
this.options = options || {};
this.channels_scrolltop = {};
this.throttled_render_sidebar = _.throttle(this.render_sidebar.bind(this), 100, { leading: false });
this.notification_bar = (window.Notification && window.Notification.permission === "default");
this.selected_message = null;
},
willStart: function () {
return chat_manager.is_ready;
},
start: function() {
var self = this;
// create searchview
var options = {
$buttons: $("<div>"),
action: this.action,
disable_groupby: true,
};
var dataset = new data.DataSetSearch(this, 'mail.message');
var view_id = (this.action && this.action.search_view_id && this.action.search_view_id[0]) || false;
var default_channel_id = this.options.active_id ||
this.action.context.active_id ||
this.action.params.default_active_id ||
'channel_inbox';
var default_channel = chat_manager.get_channel(default_channel_id) ||
chat_manager.get_channel('channel_inbox');
this.searchview = new SearchView(this, dataset, view_id, {}, options);
this.searchview.on('search_data', this, this.on_search);
this.basic_composer = new composer.BasicComposer(this, {mention_partners_restricted: true});
this.extended_composer = new composer.ExtendedComposer(this, {mention_partners_restricted: true});
this.thread = new ChatThread(this, {
display_help: true,
shorten_messages: false,
});
this.$buttons = $(QWeb.render("mail.chat.ControlButtons", {}));
this.$buttons.find('button').css({display:"inline-block"});
this.$buttons.on('click', '.o_mail_chat_button_invite', this.on_click_button_invite);
this.$buttons.on('click', '.o_mail_chat_button_unsubscribe', this.on_click_button_unsubscribe);
this.$buttons.on('click', '.o_mail_chat_button_settings', this.on_click_button_settings);
this.$buttons.on('click', '.o_mail_toggle_channels', function () {
self.$('.o_mail_chat_sidebar').slideToggle(200);
});
this.$buttons.on('click', '.o_mail_chat_button_mark_read', function () {
chat_manager.mark_all_as_read(self.channel, self.domain);
});
this.$buttons.on('click', '.o_mail_chat_button_unstar_all', chat_manager.unstar_all);
this.$buttons.on('click', '.o_mail_chat_button_new_message', this.on_click_new_message);
this.$buttons.on('click', '.o_mail_chat_button_new_message_sent', this.on_click_new_message);
this.thread.on('redirect', this, function (res_model, res_id) {
chat_manager.redirect(res_model, res_id, this.set_channel.bind(this));
});
this.thread.on('redirect_to_channel', this, function (channel_id) {
chat_manager.join_channel(channel_id).then(this.set_channel.bind(this));
});
this.thread.on('load_more_messages', this, this.load_more_messages);
this.thread.on('mark_as_read', this, function (message_id) {
chat_manager.mark_as_read([message_id]);
});
this.thread.on('toggle_star_status', this, function (message_id) {
chat_manager.toggle_star_status(message_id);
});
this.thread.on('select_message', this, this.select_message);
this.thread.on('unselect_message', this, this.unselect_message);
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.appendTo(this.$('.o_mail_chat_content'));
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>")).then(function () {
self.$searchview_buttons = self.searchview.$buttons.contents();
});
this.render_sidebar();
return $.when(def1, def2, def3, def4)
.then(this.set_channel.bind(this, default_channel))
.then(function () {
chat_manager.bus.on('open_channel', self, self.set_channel);
chat_manager.bus.on('new_message', self, self.on_new_message);
chat_manager.bus.on('update_message', self, self.on_update_message);
chat_manager.bus.on('new_channel', self, self.on_new_channel);
chat_manager.bus.on('anyone_listening', self, function (channel, query) {
query.is_displayed = query.is_displayed || (channel.id === self.channel.id && self.thread.is_at_bottom());
});
chat_manager.bus.on('unsubscribe_from_channel', self, self.render_sidebar);
chat_manager.bus.on('update_needaction', self, self.throttled_render_sidebar);
chat_manager.bus.on('update_channel_unread_counter', self, self.throttled_render_sidebar);
chat_manager.bus.on('update_dm_presence', self, self.throttled_render_sidebar);
self.thread.$el.on("scroll", null, _.debounce(function () {
if (self.thread.is_at_bottom()) {
chat_manager.mark_channel_as_seen(self.channel);
}
}, 100));
});
},
select_message: function(message_id) {
this.$el.addClass('o_mail_selection_mode');
var message = chat_manager.get_message(message_id);
this.selected_message = message;
var subject = "Re: " + message.record_name;
this.extended_composer.set_subject(subject);
if (this.channel.type !== 'static') {
this.basic_composer.toggle(false);
}
this.extended_composer.toggle(true);
this.thread.scroll_to({id: message_id, duration: 200, only_if_necessary: true});
this.extended_composer.focus('body');
},
unselect_message: function() {
this.basic_composer.toggle(this.channel.type !== 'static' && !this.channel.mass_mailing);
this.extended_composer.toggle(this.channel.type !== 'static' && this.channel.mass_mailing);
if (!config.device.touch) {
var composer = this.channel.mass_mailing ? this.extended_composer : this.basic_composer;
composer.focus();
}
this.$el.removeClass('o_mail_selection_mode');
this.thread.unselect();
this.selected_message = null;
},
render_sidebar: function () {
var self = this;
var $sidebar = $(QWeb.render("mail.chat.Sidebar", {
active_channel_id: this.channel ? this.channel.id: undefined,
channels: chat_manager.get_channels(),
needaction_counter: chat_manager.get_needaction_counter(),
}));
this.$(".o_mail_chat_sidebar").html($sidebar.contents());
this.$('.o_mail_add_channel[data-type=public]').find("input").autocomplete({
source: function(request, response) {
self.last_search_val = _.escape(request.term);
self.do_search_channel(self.last_search_val).done(function(result){
result.push({
'label': _.str.sprintf('<strong>'+_t("Create %s")+'</strong>', '<em>"#'+self.last_search_val+'"</em>'),
'value': '_create',
});
response(result);
});
},
select: function(event, ui) {
if (self.last_search_val) {
if (ui.item.value === '_create') {
chat_manager.create_channel(self.last_search_val, "public");
} else {
chat_manager.join_channel(ui.item.id);
}
}
},
focus: function(event) {
event.preventDefault();
},
html: true,
});
this.$('.o_mail_add_channel[data-type=dm]').find("input").autocomplete({
source: function(request, response) {
self.last_search_val = _.escape(request.term);
chat_manager.search_partner(self.last_search_val).done(response);
},
select: function(event, ui) {
var partner_id = ui.item.id;
chat_manager.create_channel(partner_id, "dm");
},
focus: function(event) {
event.preventDefault();
},
html: true,
});
this.$('.o_mail_add_channel[data-type=private]').find("input").on('keyup', this, function (event) {
var name = _.escape($(event.target).val());
if(event.which === $.ui.keyCode.ENTER && name) {
chat_manager.create_channel(name, "private");
}
});
},
render_snackbar: function (template, context, timeout) {
if (this.$snackbar) {
this.$snackbar.remove();
}
timeout = timeout || 20000;
this.$snackbar = $(QWeb.render(template, context));
this.$('.o_mail_chat_content').append(this.$snackbar);
// Hide snackbar after [timeout] milliseconds (by default, 20s)
var $snackbar = this.$snackbar;
setTimeout(function() { $snackbar.fadeOut(); }, timeout);
},
do_search_channel: 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){
var escaped_name = _.escape(channel.name);
values.push(_.extend(channel, {
'value': escaped_name,
'label': escaped_name,
}));
});
return values;
});
},
set_channel: function (channel) {
var self = this;
// Store scroll position of previous channel
if (this.channel) {
this.channels_scrolltop[this.channel.id] = this.thread.get_scrolltop();
}
var new_channel_scrolltop = this.channels_scrolltop[channel.id];
this.channel = channel;
this.messages_separator_position = undefined; // reset value on channel change
this.unread_counter = this.channel.unread_counter;
this.last_seen_message_id = this.channel.last_seen_message_id;
this.clear_needactions_def = $.Deferred();
if (this.$snackbar) {
this.$snackbar.remove();
}
this.action.context.active_id = channel.id;
this.action.context.active_ids = [channel.id];
return this.fetch_and_render_thread().then(function () {
// Mark channel's messages as read and clear needactions
if (channel.type !== 'static') {
// Display snackbar if needactions have been cleared
if (channel.needaction_counter > 0) {
self.render_snackbar('mail.chat.UndoSnackbar', {
nb_needactions: channel.needaction_counter,
});
}
chat_manager.mark_channel_as_seen(channel);
self.clear_needactions_def = chat_manager.mark_all_as_read(channel);
}
// Update control panel
self.set("title", '#' + channel.name);
// Hide 'invite', 'unsubscribe' and 'settings' buttons in static channels and DM
self.$buttons
.find('.o_mail_chat_button_invite, .o_mail_chat_button_unsubscribe, .o_mail_chat_button_settings')
.toggle(channel.type !== "dm" && channel.type !== 'static');
self.$buttons
.find('.o_mail_chat_button_mark_read, .o_mail_chat_button_new_message')
.toggle(channel.id === "channel_inbox");
self.$buttons
.find('.o_mail_chat_button_new_message_sent')
.toggle(channel.id === "channel_sent");
self.$buttons
.find('.o_mail_chat_button_unstar_all')
.toggle(channel.id === "channel_starred");
self.$('.o_mail_chat_channel_item')
.removeClass('o_active')
.filter('[data-channel-id=' + channel.id + ']')
.removeClass('o_unread_message')
.addClass('o_active');
var $new_messages_separator = self.$('.o_thread_new_messages_separator');
if ($new_messages_separator.length) {
self.thread.$el.scrollTo($new_messages_separator);
} else {
self.thread.scroll_to({offset: new_channel_scrolltop});
}
// Update control panel before focusing the composer, otherwise focus is on the searchview
self.update_cp();
if (config.device.size_class === config.device.SIZES.XS) {
self.$('.o_mail_chat_sidebar').hide();
}
// Display and focus the adequate composer, and unselect possibly selected message
// to prevent sending messages as reply to that message
self.unselect_message();
self.action_manager.do_push_state({
action: self.action.id,
active_id: self.channel.id,
});
});
},
unsubscribe_from_channel: function (channel) {
var self = this;
chat_manager
.unsubscribe(channel)
.then(this.render_sidebar.bind(this))
.then(this.set_channel.bind(this, chat_manager.get_channel("channel_inbox")))
.then(function () {
if (_.contains(['public', 'private'], channel.type)) {
var msg = _.str.sprintf(_t('You unsubscribed from <b>%s</b>.'), channel.name);
self.do_notify(_t("Unsubscribed"), msg);
}
delete self.channels_scrolltop[channel.id];
});
},
get_thread_rendering_options: function (messages) {
// Compute position of the 'New messages' separator, only once when joining
// a channel to keep it in the thread when new messages arrive
if (_.isUndefined(this.messages_separator_position)) {
if (!this.unread_counter) {
this.messages_separator_position = false; // no unread message -> don't display separator
} else {
var msg = chat_manager.get_last_seen_message(this.channel);
this.messages_separator_position = msg ? msg.id : 'top';
}
}
return {
channel_id: this.channel.id,
display_load_more: !chat_manager.all_history_loaded(this.channel, this.domain),
display_needactions: this.channel.display_needactions,
messages_separator_position: this.messages_separator_position,
squash_close_messages: this.channel.type !== 'static' && !this.channel.mass_mailing,
display_empty_channel: !messages.length && !this.domain.length,
display_no_match: !messages.length && this.domain.length,
display_subject: this.channel.mass_mailing || this.channel.id === "channel_inbox",
display_reply_icon: true,
};
},
fetch_and_render_thread: function () {
var self = this;
return chat_manager.get_messages({channel_id: this.channel.id, domain: this.domain}).then(function(result) {
self.thread.render(result, self.get_thread_rendering_options(result));
self.update_button_status(result.length === 0);
});
},
update_button_status: function (disabled) {
if (this.channel.id === "channel_inbox") {
this.$buttons
.find('.o_mail_chat_button_mark_read')
.toggleClass('disabled', disabled);
}
if (this.channel.id === "channel_starred") {
this.$buttons
.find('.o_mail_chat_button_unstar_all')
.toggleClass('disabled', disabled);
}
},
load_more_messages: function () {
var self = this;
var oldest_msg_id = this.$('.o_thread_message').first().data('messageId');
var oldest_msg_selector = '.o_thread_message[data-message-id="' + oldest_msg_id + '"]';
var offset = -framework.getPosition(document.querySelector(oldest_msg_selector)).top;
return chat_manager
.get_messages({channel_id: this.channel.id, domain: this.domain, load_more: true})
.then(function(result) {
if (self.messages_separator_position === 'top') {
self.messages_separator_position = undefined; // reset value to re-compute separator position
}
self.thread.render(result, self.get_thread_rendering_options(result));
offset += framework.getPosition(document.querySelector(oldest_msg_selector)).top;
self.thread.scroll_to({offset: offset});
});
},
update_cp: function () {
this.update_control_panel({
breadcrumbs: this.action_manager.get_breadcrumbs(),
cp_content: {
$buttons: this.$buttons,
$searchview: this.searchview.$el,
$searchview_buttons: this.$searchview_buttons,
},
searchview: this.searchview,
});
},
do_show: function () {
this._super.apply(this, arguments);
this.update_cp();
this.action_manager.do_push_state({
action: this.action.id,
active_id: this.channel.id,
});
},
on_search: function (domains) {
var result = pyeval.sync_eval_domains_and_contexts({
domains: domains
});
this.domain = result.domain;
this.fetch_and_render_thread();
},
on_post_message: function (message) {
var self = this;
var options = this.selected_message ? {} : {channel_id: this.channel.id};
if (this.selected_message) {
message.subtype = 'mail.mt_comment';
message.subtype_id = false;
message.message_type = 'comment';
message.content_subtype = 'html';
options.model = this.selected_message.model;
options.res_id = this.selected_message.res_id;
}
chat_manager
.post_message(message, options)
.then(function() {
if (self.selected_message) {
self.render_snackbar('mail.chat.MessageSentSnackbar', {record_name: self.selected_message.record_name}, 5000);
self.unselect_message();
} else {
self.thread.scroll_to();
}
})
.fail(function () {
// todo: display notification
});
},
on_new_message: function (message) {
var self = this;
if (_.contains(message.channel_ids, this.channel.id)) {
if (this.channel.type !== 'static' && this.thread.is_at_bottom()) {
chat_manager.mark_channel_as_seen(this.channel);
}
var should_scroll = this.thread.is_at_bottom();
this.fetch_and_render_thread().then(function () {
if (should_scroll) {
self.thread.scroll_to({id: message.id});
}
});
}
// Re-render sidebar to indicate that there is a new message in the corresponding channels
this.render_sidebar();
// Dump scroll position of channels in which the new message arrived
this.channels_scrolltop = _.omit(this.channels_scrolltop, message.channel_ids);
},
on_update_message: function (message) {
var self = this;
var current_channel_id = this.channel.id;
if ((current_channel_id === "channel_starred" && !message.is_starred) ||
(current_channel_id === "channel_inbox" && !message.is_needaction)) {
chat_manager.get_messages({channel_id: this.channel.id, domain: this.domain}).then(function (messages) {
var options = self.get_thread_rendering_options(messages);
self.thread.remove_message_and_render(message.id, messages, options).then(function () {
self.update_button_status(messages.length === 0);
});
});
} else if (_.contains(message.channel_ids, current_channel_id)) {
this.fetch_and_render_thread();
}
},
on_new_channel: function (channel) {
this.render_sidebar();
if (channel.autoswitch) {
this.set_channel(channel);
}
},
on_composer_input_focused: function () {
var suggestions = chat_manager.get_mention_partner_suggestions(this.channel);
var composer = this.channel.mass_mailing ? this.extended_composer : this.basic_composer;
composer.mention_set_prefetched_partners(suggestions);
},
on_click_button_invite: function () {
var title = _.str.sprintf(_t('Invite people to #%s'), this.channel.name);
new PartnerInviteDialog(this, title, this.channel.id).open();
},
on_click_button_unsubscribe: function () {
this.unsubscribe_from_channel(this.channel);
},
on_click_button_settings: function() {
this.do_action({
type: 'ir.actions.act_window',
res_model: "mail.channel",
res_id: this.channel.id,
views: [[false, 'form']],
target: 'current'
});
},
on_click_new_message: function () {
this.do_action({
type: 'ir.actions.act_window',
res_model: 'mail.compose.message',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
target: 'new',
context: "{'default_no_auto_thread': False, 'active_model': 'mail.message'}",
});
},
destroy: function() {
this.$buttons.off().destroy();
this._super.apply(this, arguments);
},
});
core.action_registry.add('mail.chat.instant_messaging', ChatAction);
});

19
sent_mails/static/src/xml/client_action_sent_mails.xml

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-extend="mail.chat.Sidebar">
<t t-jquery="div.o_mail_chat_sidebar" t-operation="prepend">
<div t-attf-class="o_mail_chat_channel_item #{(active_channel_id == 'channel_sent') ? 'o_active': ''}"
data-channel-id="channel_sent">
<span class="o_channel_name"> <i class="fa fa-envelope-o"/> Sent </span>
</div>
</t>
</t>
<t t-extend="mail.chat.ControlButtons">
<t t-jquery="button.o_mail_chat_button_new_message" t-operation="before">
<button type="button" class="btn btn-primary btn-sm o_mail_chat_button_new_message_sent" title="Compose new messages">Send mails</button>
</t>
</t>
</templates>

27
sent_mails/views/get_sent_mails.xml

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="mail.assets_backend" name="mail assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/mail/static/src/js/many2many_tags_email.js"></script>
<script type="text/javascript" src="/mail/static/src/js/announcement.js"></script>
<script type="text/javascript" src="/sent_mails/static/src/js/client_action_sent_mail.js"></script>
<script type="text/javascript" src="/mail/static/src/js/chat_window.js"></script>
<script type="text/javascript" src="/mail/static/src/js/composer.js"></script>
<script type="text/javascript" src="/sent_mails/static/src/js/chat_manager_sent_mail.js"></script>
<script type="text/javascript" src="/mail/static/src/js/chatter.js"></script>
<script type="text/javascript" src="/mail/static/src/js/thread.js"></script>
<script type="text/javascript" src="/mail/static/src/js/systray.js"></script>
<script type="text/javascript" src="/mail/static/src/js/window_manager.js"></script>
<link rel="stylesheet" href="/mail/static/src/less/announcement.less"/>
<link rel="stylesheet" href="/mail/static/src/less/client_action.less" type="text/less"/>
<link rel="stylesheet" href="/mail/static/src/less/chat_window.less" type="text/less"/>
<link rel="stylesheet" href="/mail/static/src/less/composer.less" type="text/less"/>
<link rel="stylesheet" href="/mail/static/src/less/chatter.less" type="text/less"/>
<link rel="stylesheet" href="/mail/static/src/less/thread.less" type="text/less"/>
</xpath>
</template>
</data>
</openerp>
Loading…
Cancel
Save