Browse Source

Merge pull request #182 from Ommo73/10.0-mail_private-add_channels

10.0 mail private add channels
pull/223/head
Bot 5 years ago
committed by GitHub
parent
commit
5a610a48b1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      mail_base/README.rst
  2. 1
      mail_base/__init__.py
  3. 6
      mail_base/__manifest__.py
  4. 3
      mail_base/controllers/main.py
  5. 4
      mail_base/doc/changelog.rst
  6. 7
      mail_base/models.py
  7. 6
      mail_base/static/lib/base.js
  8. 1
      mail_private/__init__.py
  9. 10
      mail_private/__manifest__.py
  10. 6
      mail_private/doc/changelog.rst
  11. 4
      mail_private/full_composer_wizard.xml
  12. 73
      mail_private/models.py
  13. 98
      mail_private/static/src/js/mail_private.js
  14. 16
      mail_private/static/src/xml/mail_private.xml
  15. 2
      mail_private/template.xml

2
mail_base/README.rst

@ -6,7 +6,7 @@ Mail Base
* fixes toggling left bar * fixes toggling left bar
* fixes Recipients field. Out-of-box this field could be empty. * fixes Recipients field. Out-of-box this field could be empty.
One can say, that the module do this todo from `addons/mail/static/src/js/chat_manager.js <https://github.com/odoo/odoo/blob/9.0/addons/mail/static/src/js/chat_manager.js#L57>`__
One can say, that the module do this todo from `addons/mail/static/src/js/chat_manager.js <https://github.com/odoo/odoo/blob/10.0/addons/mail/static/src/js/chat_manager.js#L57>`__
// to do: move this to mail.utils // to do: move this to mail.utils

1
mail_base/__init__.py

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html)
from . import models from . import models
from . import controllers from . import controllers

6
mail_base/__manifest__.py

@ -1,10 +1,14 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2016 x620 <https://github.com/x620>
# Copyright 2018 Ruslan Ronzhin <https://it-projects.info/team/rusllan/>
# Copyright 2016-2019 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html)
{ {
"name": "Mail Base", "name": "Mail Base",
"summary": """Makes Mail extendable""", "summary": """Makes Mail extendable""",
"category": "Discuss", "category": "Discuss",
"images": [], "images": [],
"version": "10.0.1.0.5",
"version": "10.0.1.1.0",
"author": "IT-Projects LLC, Pavel Romanchenko", "author": "IT-Projects LLC, Pavel Romanchenko",
"support": "apps@it-projects.info", "support": "apps@it-projects.info",

3
mail_base/controllers/main.py

@ -1,4 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2017 mikaelh <https://github.com/mikaelh>
# Copyright 2017-2019 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html)
from openerp.http import request from openerp.http import request
from openerp.addons.bus.controllers.main import BusController from openerp.addons.bus.controllers.main import BusController

4
mail_base/doc/changelog.rst

@ -1,3 +1,7 @@
`1.1.0`
-------
- **New**: added ability to select channels for private message sending.
`1.0.5` `1.0.5`
------- -------
**FIX**: polling errors on heavy server load **FIX**: polling errors on heavy server load

7
mail_base/models.py

@ -1,4 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2016 x620 <https://github.com/x620>
# Copyright 2017 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html)
from openerp import api, models from openerp import api, models
@ -13,8 +16,8 @@ class MailMessage(models.Model):
values['partner_ids'] = [] values['partner_ids'] = []
for triplet in values.get('needaction_partner_ids'): for triplet in values.get('needaction_partner_ids'):
if triplet[0] == 6: if triplet[0] == 6:
for id in triplet[2]:
values['partner_ids'].append((4, id, False))
for i in triplet[2]:
values['partner_ids'].append((4, i, False))
return super(MailMessage, self).write(values) return super(MailMessage, self).write(values)

6
mail_base/static/lib/base.js

@ -1,3 +1,6 @@
/* Copyright 2017 Artyom Losev <https://github.com/ArtyomLosev>
Copyright 2019 Artem Rafailov <https://github.com/Ommo73>
License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html). */
odoo.define('mail_base.base', function (require) { odoo.define('mail_base.base', function (require) {
"use strict"; "use strict";
@ -215,7 +218,7 @@ var MailComposer = composer.BasicComposer.extend({
var parsed_email = utils.parse_email(recipient[1]); var parsed_email = utils.parse_email(recipient[1]);
if (_.indexOf(email_addresses, parsed_email[1]) === -1) { if (_.indexOf(email_addresses, parsed_email[1]) === -1) {
self.suggested_partners.push({ self.suggested_partners.push({
checked: true,
checked: false,
partner_id: recipient[0], partner_id: recipient[0],
full_name: recipient[1], full_name: recipient[1],
name: parsed_email[0], name: parsed_email[0],
@ -1059,6 +1062,7 @@ chat_manager.post_message = function (data, options) {
options = options || {}; options = options || {};
var msg = { var msg = {
partner_ids: data.partner_ids, partner_ids: data.partner_ids,
channel_ids: data.channel_ids,
body: _.str.trim(data.content), body: _.str.trim(data.content),
attachment_ids: data.attachment_ids attachment_ids: data.attachment_ids
}; };

1
mail_private/__init__.py

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html)
from . import models from . import models

10
mail_private/__manifest__.py

@ -1,10 +1,18 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2016 x620 <https://github.com/x620>
# Copyright 2016 Ilmir Karamov <https://it-projects.info/team/ilmir-k>
# Copyright 2016 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# Copyright 2017 Artyom Losev <https://github.com/ArtyomLosev>
# Copyright 2018 Ruslan Ronzhin <https://it-projects.info/team/rusllan/>
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# Copyright 2019 Artem Rafailov <https://it-projects.info/team/Ommo73/>
# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html).
{ {
"name": """Internal Messaging""", "name": """Internal Messaging""",
"summary": """Send private messages to specified recipients, regardless of who are in followers list.""", "summary": """Send private messages to specified recipients, regardless of who are in followers list.""",
"category": "Discuss", "category": "Discuss",
"images": ['images/mail_private_image.png'], "images": ['images/mail_private_image.png'],
"version": "10.0.1.0.1",
"version": "10.0.1.1.0",
"application": False, "application": False,
"author": "IT-Projects LLC, Pavel Romanchenko", "author": "IT-Projects LLC, Pavel Romanchenko",

6
mail_private/doc/changelog.rst

@ -1,3 +1,9 @@
`1.1.0`
-------
- **New**: added ability to select channels for private message sending.
- **New**: internal users are flagged automatically.
`1.0.1` `1.0.1`
------- -------

4
mail_private/full_composer_wizard.xml

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--Copyright 2017 Artyom Losev <https://github.com/ArtyomLosev>
Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html).-->
<odoo> <odoo>
<record model="ir.ui.view" id="email_compose_message_wizard_form_private"> <record model="ir.ui.view" id="email_compose_message_wizard_form_private">

73
mail_private/models.py

@ -1,4 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2016 x620 <https://github.com/x620>
# Copyright 2016 manawi <https://github.com/manawi>
# Copyright 2017 Artyom Losev <https://github.com/ArtyomLosev>
# Copyright 2019 Artem Rafailov <https://it-projects.info/team/Ommo73/>
# License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html).
from odoo import models, fields, api from odoo import models, fields, api
@ -7,8 +13,75 @@ class MailComposeMessage(models.TransientModel):
is_private = fields.Boolean(string='Send Internal Message') is_private = fields.Boolean(string='Send Internal Message')
def get_internal_users_ids(self):
internal_users_ids = self.env['res.users'].search([('share', '=', False)]).ids
return internal_users_ids
@api.multi @api.multi
def send_mail(self, auto_commit=False): def send_mail(self, auto_commit=False):
for w in self: for w in self:
w.is_log = True if w.is_private else w.is_log w.is_log = True if w.is_private else w.is_log
super(MailComposeMessage, self).send_mail(auto_commit=False) super(MailComposeMessage, self).send_mail(auto_commit=False)
class MailMessage(models.Model):
_inherit = 'mail.message'
@api.multi
def _notify(self, force_send=False, send_after_commit=True, user_signature=True):
self_sudo = self.sudo()
if 'is_private' not in self_sudo._context or not self_sudo._context['is_private']:
super(MailMessage, self)._notify(force_send, send_after_commit, user_signature)
else:
self._notify_mail_private(force_send, send_after_commit, user_signature)
@api.multi
def _notify_mail_private(self, force_send=False, send_after_commit=True, user_signature=True):
""" The method was partially copied from Odoo.
In the current method, the way of getting channels for a private message is changed.
"""
# have a sudoed copy to manipulate partners (public can go here with
# website modules like forum / blog / ...
# TDE CHECK: add partners / channels as arguments to be able to notify a message with / without computation ??
self.ensure_one() # tde: not sure, just for testinh, will see
partners = self.env['res.partner'] | self.partner_ids
channels = self.env['mail.channel'] | self.channel_ids
# update message, with maybe custom values
message_values = {
'channel_ids': [(6, 0, channels.ids)],
'needaction_partner_ids': [(6, 0, partners.ids)]
}
if self.model and self.res_id and hasattr(self.env[self.model], 'message_get_message_notify_values'):
message_values.update(
self.env[self.model].browse(self.res_id).message_get_message_notify_values(self, message_values))
self.write(message_values)
# notify partners and channels
partners._notify(self, force_send=force_send, send_after_commit=send_after_commit,
user_signature=user_signature)
channels._notify(self)
# Discard cache, because child / parent allow reading and therefore
# change access rights.
if self.parent_id:
self.parent_id.invalidate_cache()
return True
class MailThread(models.AbstractModel):
_inherit = 'mail.thread'
@api.multi
@api.returns('self', lambda value: value.id)
def message_post(self, body='', subject=None, message_type='notification',
subtype=None, parent_id=False, attachments=None,
content_subtype='html', **kwargs):
if 'channel_ids' in kwargs:
kwargs['channel_ids'] = [(4, pid) for pid in kwargs['channel_ids']]
return super(MailThread, self).message_post(body, subject, message_type,
subtype, parent_id, attachments,
content_subtype, **kwargs)

98
mail_private/static/src/js/mail_private.js

@ -1,3 +1,9 @@
/* Copyright 2016 x620 <https://github.com/x620>
Copyright 2016 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
Copyright 2016 manawi <https://github.com/manawi>
Copyright 2017 Artyom Losev <https://github.com/ArtyomLosev>
Copyright 2019 Artem Rafailov <https://it-projects.info/team/Ommo73/>
License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html). */
odoo.define('mail_private', function (require) { odoo.define('mail_private', function (require) {
'use strict'; 'use strict';
@ -22,6 +28,7 @@ Chatter.include({
var self = this; var self = this;
if (this.private) { if (this.private) {
message.subtype = false; message.subtype = false;
message.channel_ids = this.get_checked_channels_ids();
} }
var options = {model: this.model, res_id: this.res_id}; var options = {model: this.model, res_id: this.res_id};
chat_manager.post_message(message, options).then( chat_manager.post_message(message, options).then(
@ -33,32 +40,38 @@ Chatter.include({
}).fail(function () { }).fail(function () {
// todo: display notification // todo: display notification
}); });
},
},
on_open_composer_private_message: function (event) { on_open_composer_private_message: function (event) {
var self = this; var self = this;
this.private = true; this.private = true;
this.get_recipients_for_internal_message().then(function (data) { this.get_recipients_for_internal_message().then(function (data) {
self.recipients_for_internal_message = data; self.recipients_for_internal_message = data;
self.open_composer({is_private: true});
return self.get_channels_for_internal_message();
}).then(function (data) {
self.channels_for_internal_message = data;
self.get_internal_users_ids().then(function(res_ids){
self.open_composer({is_private: true, internal_ids: res_ids});
});
}); });
}, },
on_open_composer_new_message: function () { on_open_composer_new_message: function () {
this._super.apply(this, arguments); this._super.apply(this, arguments);
this.private = false; this.private = false;
this.context.is_private = false;
}, },
open_composer: function (options) { open_composer: function (options) {
var self = this; var self = this;
this._super.apply(this, arguments); this._super.apply(this, arguments);
if (options && options.is_private) { if (options && options.is_private) {
self.internal_users_ids = options.internal_ids;
this.composer.options.is_private = options.is_private; this.composer.options.is_private = options.is_private;
_.each(self.recipients_for_internal_message, function (partner) { _.each(self.recipients_for_internal_message, function (partner) {
self.composer.suggested_partners.push({ self.composer.suggested_partners.push({
checked: (partner.user_ids.length > 0),
checked: _.intersection(self.internal_users_ids, partner.user_ids).length > 0,
partner_id: partner.id, partner_id: partner.id,
full_name: partner.name, full_name: partner.name,
name: partner.name, name: partner.name,
@ -68,6 +81,15 @@ Chatter.include({
:'Follower' :'Follower'
}); });
}); });
_.each(self.channels_for_internal_message, function (channel) {
self.composer.suggested_channels.push({
checked: true,
channel_id: channel.id,
full_name: channel.name,
name: ('# ' + channel.name),
});
});
} }
}, },
@ -101,13 +123,68 @@ Chatter.include({
}); });
}); });
}); });
}
},
get_channels_for_internal_message: function () {
var self = this;
self.result = {};
return new Model(this.context.default_model).query(
['message_follower_ids', 'partner_id']).filter(
[['id', '=', self.context.default_res_id]]).all()
.then(function (thread) {
var follower_ids = thread[0].message_follower_ids;
self.result[self.context.default_res_id] = [];
self.customer = thread[0].partner_id;
// Fetch channels ids
return new Model('mail.followers').call(
'read', [follower_ids, ['channel_id']]).then(function (res_channels) {
// Filter result and push to array
var res_channels_filtered = _.map(res_channels, function (channel) {
if (channel.channel_id[0]) {
return channel.channel_id[0];
}
}).filter(function (channel) {
return typeof channel !== 'undefined';
});
return new Model('mail.channel').call(
'read', [res_channels_filtered, ['name', 'id']]
).then(function (recipients) {
return recipients;
});
});
});
},
get_internal_users_ids: function () {
var ResUser = new Model('mail.compose.message');
this.users_ids = ResUser.call('get_internal_users_ids', [[]]).then( function (users_ids) {
return users_ids;
});
return this.users_ids;
},
get_checked_channels_ids: function () {
var self = this;
var checked_channels = [];
this.$('.o_composer_suggested_channels input:checked').each(function() {
var full_name = $(this).data('fullname').toString();
_.each(self.channels_for_internal_message, function(item) {
if (full_name === item.name) {
checked_channels.push(item.id);
}
});
});
return checked_channels;
},
}); });
MailComposer.include({ MailComposer.include({
init: function (parent, dataset, options) { init: function (parent, dataset, options) {
this._super(parent, dataset, options); this._super(parent, dataset, options);
this.events['click .oe_composer_uncheck'] = 'on_uncheck_recipients'; this.events['click .oe_composer_uncheck'] = 'on_uncheck_recipients';
this.suggested_channels = [];
}, },
@ -115,6 +192,17 @@ MailComposer.include({
this.$('.o_composer_suggested_partners input:checked').each(function() { this.$('.o_composer_suggested_partners input:checked').each(function() {
$(this).prop('checked', false); $(this).prop('checked', false);
}); });
this.$('.o_composer_suggested_channels input:checked').each(function() {
$(this).prop('checked', false);
});
},
preprocess_message: function () {
var self = this;
if (self.options.is_private) {
self.context.is_private = true;
}
return this._super();
}, },
on_open_full_composer: function() { on_open_full_composer: function() {

16
mail_private/static/src/xml/mail_private.xml

@ -1,4 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Copyright 2016 x620 <https://github.com/x620>
Copyright 2016 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
Copyright 2016 manawi <https://github.com/manawi>
Copyright 2017 Artyom Losev <https://github.com/ArtyomLosev>
Copyright 2019 Artem Rafailov <https://it-projects.info/team/Ommo73/>
License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html).-->
<template> <template>
<t t-extend="mail.Chatter"> <t t-extend="mail.Chatter">
@ -20,6 +26,16 @@
</span> </span>
</t> </t>
<t t-jquery="div[class='o_composer_suggested_partners']" t-operation="after"> <t t-jquery="div[class='o_composer_suggested_partners']" t-operation="after">
<div class="o_composer_suggested_channels">
<t t-foreach='widget.suggested_channels' t-as='channel'>
<div t-attf-title="Add as channel and follower">
<input type="checkbox"
t-att-checked="channel.checked ? 'checked' : undefined"
t-att-data-fullname="channel.full_name"/>
<t t-esc="channel.name"/>
</div>
</t>
</div>
<button class="btn btn-sm btn-link oe_composer_uncheck" t-if="widget.options.is_private">Uncheck all</button> <button class="btn btn-sm btn-link oe_composer_uncheck" t-if="widget.options.is_private">Uncheck all</button>
</t> </t>
</t> </t>

2
mail_private/template.xml

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--Copyright 2016 x620 <https://github.com/x620>
License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html).-->
<openerp> <openerp>
<data> <data>
<template <template

Loading…
Cancel
Save