Browse Source

Merge pull request #180 from Ommo73/12.0-mail_private-port

⬆️1️⃣2️⃣ mail_private *Port*
pull/193/head
Ramil 6 years ago
committed by GitHub
parent
commit
db9903105a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      mail_multi_website/doc/changelog.rst
  2. 10
      mail_private/README.rst
  3. 1
      mail_private/__init__.py
  4. 33
      mail_private/__manifest__.py
  5. 3
      mail_private/full_composer_wizard.xml
  6. 77
      mail_private/models.py
  7. 137
      mail_private/static/src/js/mail_private.js
  8. 29
      mail_private/static/src/js/test_private.js
  9. 11
      mail_private/static/src/xml/mail_private.xml
  10. 3
      mail_private/template.xml
  11. 1
      mail_private/tests/__init__.py
  12. 14
      mail_private/tests/test_js.py

2
mail_multi_website/doc/changelog.rst

@ -1,7 +1,7 @@
`1.0.1` `1.0.1`
------- -------
- **Fix:** Issue related to module uninstallation
- **Fix:** Issue with module uninstallation
`1.0.0` `1.0.0`
------- -------

10
mail_private/README.rst

@ -25,7 +25,7 @@ Maintainers
To get a guaranteed support To get a guaranteed support
you are kindly requested to purchase the module you are kindly requested to purchase the module
at `odoo apps store <https://apps.odoo.com/apps/modules/11.0/mail_private/>`__.
at `odoo apps store <https://apps.odoo.com/apps/modules/12.0/mail_private/>`__.
Thank you for understanding! Thank you for understanding!
@ -34,14 +34,14 @@ Maintainers
Further information Further information
=================== ===================
Demo: http://runbot.it-projects.info/demo/mail-addons/11.0
Demo: http://runbot.it-projects.info/demo/mail-addons/12.0
HTML Description: https://apps.odoo.com/apps/modules/11.0/mail_private/
HTML Description: https://apps.odoo.com/apps/modules/12.0/mail_private/
Usage instructions: `<doc/index.rst>`_ Usage instructions: `<doc/index.rst>`_
Changelog: `<doc/changelog.rst>`_ Changelog: `<doc/changelog.rst>`_
Notifications on updates: `via Atom <https://github.com/it-projects-llc/mail-addons/commits/11.0/mail_private.atom>`_, `by Email <https://blogtrottr.com/?subscribe=https://github.com/it-projects-llc/mail-addons/commits/11.0/mail_private.atom>`_
Notifications on updates: `via Atom <https://github.com/it-projects-llc/mail-addons/commits/12.0/mail_private.atom>`_, `by Email <https://blogtrottr.com/?subscribe=https://github.com/it-projects-llc/mail-addons/commits/12.0/mail_private.atom>`_
Tested on Odoo 11.0 3d09560ffc779e169ed9488e4e07928204dd234d
Tested on Odoo 12.0 5240bc2303816348837425b88fc7ee3ff7de2336

1
mail_private/__init__.py

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

33
mail_private/__manifest__.py

@ -1,37 +1,52 @@
# 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'],
"version": "11.0.1.0.2",
# "live_test_url": "http://apps.it-projects.info/shop/product/DEMO-URL?version=12.0",
"images": [],
"version": "12.0.1.0.2",
"application": False, "application": False,
"author": "IT-Projects LLC, Pavel Romanchenko", "author": "IT-Projects LLC, Pavel Romanchenko",
"support": "apps@it-projects.info", "support": "apps@it-projects.info",
"website": "https://it-projects.info",
"license": "GPL-3",
"website": "https://it-projects.info/",
"license": "LGPL-3",
"price": 50.00, "price": 50.00,
"currency": "EUR", "currency": "EUR",
"depends": [ "depends": [
"mail",
"base",
"mail_base"
"mail"
], ],
"external_dependencies": {"python": [], "bin": []}, "external_dependencies": {"python": [], "bin": []},
"data": [ "data": [
'template.xml', 'template.xml',
'full_composer_wizard.xml', 'full_composer_wizard.xml',
], ],
"demo": [
],
"qweb": [ "qweb": [
'static/src/xml/mail_private.xml', 'static/src/xml/mail_private.xml',
], ],
"demo": [],
"post_load": None, "post_load": None,
"pre_init_hook": None, "pre_init_hook": None,
"post_init_hook": None, "post_init_hook": None,
"uninstall_hook": None,
"auto_install": False, "auto_install": False,
"installable": False,
"installable": True,
# "demo_title": "{MODULE_NAME}",
# "demo_addons": [
# ],
# "demo_addons_hidden": [
# ],
# "demo_url": "DEMO-URL",
# "demo_summary": "{SHORT_DESCRIPTION_OF_THE_MODULE}",
# "demo_images": [
# "images/MAIN_IMAGE",
# ]
} }

3
mail_private/full_composer_wizard.xml

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--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> <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">

77
mail_private/models.py

@ -1,3 +1,8 @@
# Copyright 2016 x620 <https://github.com/x620>
# Copyright 2017 Artyom Losev <https://github.com/ArtyomLosev>
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# 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
@ -41,68 +46,18 @@ class MailMessage(models.Model):
return result return result
@api.multi @api.multi
def _notify(self, force_send=False, send_after_commit=True, user_signature=True):
def _notify(self, record, msg_vals, force_send=False, send_after_commit=True, model_description=False, mail_auto_delete=True):
self_sudo = self.sudo() self_sudo = self.sudo()
if not self_sudo.is_private:
super(MailMessage, self)._notify(force_send, send_after_commit, user_signature)
msg_vals = msg_vals if msg_vals else {}
if 'is_private' not in self_sudo._context or not self_sudo._context['is_private']:
return super(MailMessage, self)._notify(record, msg_vals, force_send, send_after_commit, model_description, mail_auto_delete)
else: else:
self._notify_mail_private(force_send, send_after_commit, user_signature)
rdata = self._notify_compute_internal_recipients(record, msg_vals)
return self._notify_recipients(rdata, record, msg_vals, force_send, send_after_commit, model_description, mail_auto_delete)
@api.multi @api.multi
def _notify_mail_private(self, force_send=False, send_after_commit=True, user_signature=True):
""" Compute recipients to notify based on specified recipients and document
followers. Delegate notification to partners to send emails and bus notifications
and to channels to broadcast messages on channels """
group_user = self.env.ref('base.group_user')
# have a sudoed copy to manipulate partners (public can go here with website modules like forum / blog / ... )
self_sudo = self.sudo()
self.ensure_one()
partners_sudo = self_sudo.partner_ids
channels_sudo = self_sudo.channel_ids
if self_sudo.subtype_id and self.model and self.res_id:
followers = self_sudo.env['mail.followers'].search([
('res_model', '=', self.model),
('res_id', '=', self.res_id),
('subtype_ids', 'in', self_sudo.subtype_id.id),
])
if self_sudo.subtype_id.internal:
followers = followers.filtered(lambda fol: fol.channel_id or (fol.partner_id.user_ids and group_user in fol.partner_id.user_ids[0].mapped('groups_id')))
channels_sudo |= followers.mapped('channel_id')
# remove author from notified partners
if not self._context.get('mail_notify_author', False) and self_sudo.author_id:
partners_sudo = partners_sudo - self_sudo.author_id
# update message, with maybe custom valuesz
message_values = {}
if channels_sudo:
message_values['channel_ids'] = [(6, 0, channels_sudo.ids)]
if partners_sudo:
message_values['needaction_partner_ids'] = [(6, 0, partners_sudo.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))
if message_values:
self.write(message_values)
# notify partners and channels
# those methods are called as SUPERUSER because portal users posting messages
# have no access to partner model. Maybe propagating a real uid could be necessary.
email_channels = channels_sudo.filtered(lambda channel: channel.email_send)
notif_partners = partners_sudo.filtered(lambda partner: 'inbox' in partner.mapped('user_ids.notification_type'))
if email_channels or partners_sudo - notif_partners:
partners_sudo.search([
'|',
('id', 'in', (partners_sudo - notif_partners).ids),
('channel_ids', 'in', email_channels.ids),
('email', '!=', self_sudo.author_id.email or self_sudo.email_from),
])._notify(self, force_send=force_send, send_after_commit=send_after_commit, user_signature=user_signature)
channels_sudo._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
def _notify_compute_internal_recipients(self, record, msg_vals):
recipient_data = super(MailMessage, self)._notify_compute_recipients(record, msg_vals)
pids = [x[1] for x in msg_vals.get('partner_ids')] if 'partner_ids' in msg_vals else self.sudo().partner_ids.ids
recipient_data['partners'] = [i for i in recipient_data['partners'] if i['id'] in pids]
return recipient_data

137
mail_private/static/src/js/mail_private.js

@ -2,19 +2,19 @@
Copyright 2016 manavi <https://github.com/manawi> Copyright 2016 manavi <https://github.com/manawi>
Copyright 2017-2018 Artyom Losev <https://github.com/ArtyomLosev> Copyright 2017-2018 Artyom Losev <https://github.com/ArtyomLosev>
Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr> Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
Copyright 2019 Artem Rafailov <https://it-projects.info/team/Ommo73/>
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). */ License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). */
odoo.define('mail_private', function (require) { odoo.define('mail_private', function (require) {
'use strict'; 'use strict';
var core = require('web.core'); var core = require('web.core');
var Chatter = require('mail.Chatter'); var Chatter = require('mail.Chatter');
var ChatterComposer = require('mail.ChatterComposer');
var chat_manager = require('mail_base.base').chat_manager;
var ChatterComposer = require('mail.composer.Chatter');
var session = require('web.session'); var session = require('web.session');
var rpc = require('web.rpc'); var rpc = require('web.rpc');
var config = require('web.config'); var config = require('web.config');
var utils = require('mail.utils');
var mailUtils = require('mail.utils');
Chatter.include({ Chatter.include({
@ -36,51 +36,55 @@ Chatter.include({
_openComposer: function (options) { _openComposer: function (options) {
var self = this; var self = this;
var old_composer = this.composer;
var old_composer = this._composer;
// create the new composer // create the new composer
this.composer = new ChatterComposer(this, this.record.model, options.suggested_partners || [], {
commands_enabled: false,
this._composer = new ChatterComposer(this, this.record.model, options.suggested_partners || [], {
commandsEnabled: false,
context: this.context, context: this.context,
input_min_height: 50,
input_max_height: Number.MAX_VALUE,
input_baseline: 14,
is_log: options && options.is_log,
record_name: this.record_name,
default_body: old_composer && old_composer.$input && old_composer.$input.val(),
default_mention_selections: old_composer && old_composer.mention_get_listener_selections(),
inputMinHeight: 50,
isLog: options && options.isLog,
recordName: this.recordName,
defaultBody: old_composer && old_composer.$input && old_composer.$input.val(),
defaultMentionSelections: old_composer && old_composer.getMentionListenerSelections(),
attachmentIds: (old_composer && old_composer.get('attachment_ids')) || [],
is_private: options.is_private is_private: options.is_private
}); });
this.composer.on('input_focused', this, function () {
this.composer.mention_set_prefetched_partners(this.mentionSuggestions || []);
this._composer.on('input_focused', this, function () {
this._composer.mentionSetPrefetchedPartners(this._mentionSuggestions || []);
}); });
this.composer.insertAfter(this.$('.o_chatter_topbar')).then(function () {
this._composer.insertAfter(this.$('.o_chatter_topbar')).then(function () {
// destroy existing composer // destroy existing composer
if (old_composer) { if (old_composer) {
old_composer.destroy(); old_composer.destroy();
} }
if (!config.device.touch) {
self.composer.focus();
}
self.composer.on('post_message', self, function (message) {
self._composer.focus();
self._composer.on('post_message', self, function (messageData) {
if (options.is_private) { if (options.is_private) {
self.composer.options.is_log = true;
self._composer.options.isLog = true;
} }
self.fields.thread.postMessage(message).then(function () {
self._closeComposer(true);
if (self.postRefresh === 'always' || (self.postRefresh === 'recipients' && message.partner_ids.length)) {
self.trigger_up('reload');
}
self._discardOnReload(messageData).then(function () {
self._disableComposer();
self.fields.thread.postMessage(messageData).then(function () {
self._closeComposer(true);
if (self._reloadAfterPost(messageData)) {
self.trigger_up('reload');
} else if (messageData.attachment_ids.length) {
self._reloadAttachmentBox();
self.trigger_up('reload', {fieldNames: ['message_attachment_count'], keepChanges: true});
}
}).fail(function () {
self._enableComposer();
});
}); });
}); });
var toggle_post_private = self.composer.options.is_private || false;
self.composer.on('need_refresh', self, self.trigger_up.bind(self, 'reload'));
self.composer.on('close_composer', null, self._closeComposer.bind(self, true));
var toggle_post_private = self._composer.options.is_private || false;
self._composer.on('need_refresh', self, self.trigger_up.bind(self, 'reload'));
self._composer.on('close_composer', null, self._closeComposer.bind(self, true));
self.$el.addClass('o_chatter_composer_active'); self.$el.addClass('o_chatter_composer_active');
self.$('.o_chatter_button_new_message, .o_chatter_button_log_note, .oe_compose_post_private').removeClass('o_active'); self.$('.o_chatter_button_new_message, .o_chatter_button_log_note, .oe_compose_post_private').removeClass('o_active');
self.$('.o_chatter_button_new_message').toggleClass('o_active', !self.composer.options.is_log && !self.composer.options.is_private);
self.$('.o_chatter_button_log_note').toggleClass('o_active', (self.composer.options.is_log && !options.is_private));
self.$('.o_chatter_button_new_message').toggleClass('o_active', !self._composer.options.isLog && !self._composer.options.is_private);
self.$('.o_chatter_button_log_note').toggleClass('o_active', self._composer.options.isLog && !options.is_private);
self.$('.oe_compose_post_private').toggleClass('o_active', toggle_post_private); self.$('.oe_compose_post_private').toggleClass('o_active', toggle_post_private);
}); });
}, },
@ -102,8 +106,8 @@ Chatter.include({
}); });
ChatterComposer.include({ ChatterComposer.include({
init: function (parent, model, suggested_partners, options) {
this._super(parent, model, suggested_partners, options);
init: function (parent, model, suggestedPartners, options) {
this._super(parent, model, suggestedPartners, options);
this.events['click .oe_composer_uncheck'] = 'on_uncheck_recipients'; this.events['click .oe_composer_uncheck'] = 'on_uncheck_recipients';
if (typeof options.is_private === 'undefined') { if (typeof options.is_private === 'undefined') {
// otherwise it causes an error in context creating function // otherwise it causes an error in context creating function
@ -111,40 +115,39 @@ ChatterComposer.include({
} }
}, },
preprocess_message: function () {
_preprocessMessage: function () {
var self = this; var self = this;
var def = $.Deferred(); var def = $.Deferred();
this._super().then(function (message) { this._super().then(function (message) {
message = _.extend(message, { message = _.extend(message, {
subtype: 'mail.mt_comment', subtype: 'mail.mt_comment',
message_type: 'comment', message_type: 'comment',
content_subtype: 'html',
context: self.context,
context: _.defaults({}, self.context, session.user_context),
}); });
// Subtype // Subtype
if (self.options.is_log) {
if (self.options.isLog) {
message.subtype = 'mail.mt_note'; message.subtype = 'mail.mt_note';
} }
if (self.options.is_private) { if (self.options.is_private) {
message.is_private = true;
message.context.is_private = true;
message.channel_ids = self.get_checked_channel_ids(); message.channel_ids = self.get_checked_channel_ids();
} }
// Partner_ids // Partner_ids
if (!self.options.is_log) {
var checked_suggested_partners = self.get_checked_suggested_partners();
self.check_suggested_partners(checked_suggested_partners).done(function (partner_ids) {
message.partner_ids = (message.partner_ids || []).concat(partner_ids);
if (self.options.isLog) {
def.resolve(message);
} else {
var check_suggested_partners = self._getCheckedSuggestedPartners();
self._checkSuggestedPartners(check_suggested_partners).done(function (partnerIDs) {
message.partner_ids = (message.partner_ids || []).concat(partnerIDs);
// update context // update context
message.context = _.defaults({}, message.context, { message.context = _.defaults({}, message.context, {
mail_post_autofollow: true, mail_post_autofollow: true,
}); });
def.resolve(message); def.resolve(message);
}); });
} else {
def.resolve(message);
} }
}); });
return def; return def;
@ -156,25 +159,30 @@ ChatterComposer.include({
}); });
}, },
on_open_full_composer: function() {
if (!this.do_check_attachment_upload()){
_onOpenFullComposer: function () {
if (!this._doCheckAttachmentUpload()){
return false; return false;
} }
var self = this; var self = this;
var recipient_done = $.Deferred();
if (this.options.is_log) {
recipient_done.resolve([]);
} else {
var checked_suggested_partners = this.get_checked_suggested_partners();
recipient_done = this.check_suggested_partners(checked_suggested_partners);
}
recipient_done.then(function (partner_ids) {
var recipientDoneDef = $.Deferred();
this.trigger_up('discard_record_changes', {
proceed: function () {
if (self.options.isLog) {
recipientDoneDef.resolve([]);
} else {
var checkedSuggestedPartners = self._getCheckedSuggestedPartners();
self._checkSuggestedPartners(checkedSuggestedPartners)
.then(recipientDoneDef.resolve.bind(recipientDoneDef));
}
},
});
recipientDoneDef.then(function (partnerIDs) {
var context = { var context = {
default_parent_id: self.id, default_parent_id: self.id,
default_body: utils.get_text2html(self.$input.val()),
default_body: mailUtils.getTextToHTML(self.$input.val()),
default_attachment_ids: _.pluck(self.get('attachment_ids'), 'id'), default_attachment_ids: _.pluck(self.get('attachment_ids'), 'id'),
default_partner_ids: partner_ids,
default_is_log: self.options.is_log,
default_partner_ids: partnerIDs,
default_is_log: self.options.isLog,
mail_post_autofollow: true, mail_post_autofollow: true,
is_private: self.options.is_private, is_private: self.options.is_private,
}; };
@ -187,7 +195,7 @@ ChatterComposer.include({
context.default_model = self.context.default_model; context.default_model = self.context.default_model;
context.default_res_id = self.context.default_res_id; context.default_res_id = self.context.default_res_id;
} }
self.do_action({
var action = {
type: 'ir.actions.act_window', type: 'ir.actions.act_window',
res_model: 'mail.compose.message', res_model: 'mail.compose.message',
view_mode: 'form', view_mode: 'form',
@ -195,17 +203,14 @@ ChatterComposer.include({
views: [[false, 'form']], views: [[false, 'form']],
target: 'new', target: 'new',
context: context, context: context,
}, {
on_close: function() {
self.trigger('need_refresh');
var parent = self.getParent();
chat_manager.get_messages({model: parent.model, res_id: parent.res_id});
},
};
self.do_action(action, {
on_close: self.trigger.bind(self, 'need_refresh'),
}).then(self.trigger.bind(self, 'close_composer')); }).then(self.trigger.bind(self, 'close_composer'));
}); });
}, },
get_checked_suggested_partners: function () {
_getCheckedSuggestedPartners: function () {
var checked_partners = this._super(this, arguments); var checked_partners = this._super(this, arguments);
// workaround: odoo code works only when all partners are checked intially, // workaround: odoo code works only when all partners are checked intially,
// while may select only some of them (internal recepients) // while may select only some of them (internal recepients)

29
mail_private/static/src/js/test_private.js

@ -1,17 +1,30 @@
/* Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
/* Copyright 2018-2019 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
Copyright 2019 Artem Rafailov <https://it-projects.info/team/Ommo73/>
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).*/ License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).*/
odoo.define('mail_private.tour', function (require) {
"use strict";
odoo.define('mail_private.tour', function(require) {
"use strict";
var tour = require("web_tour.tour");
var core = require('web.core'); var core = require('web.core');
var tour = require('web_tour.tour');
var _t = core._t; var _t = core._t;
var email = 'mail_private test email'; var email = 'mail_private test email';
var steps = [{
trigger: '.o_thread_message strong.o_mail_redirect:contains("Agrolait")',
content: _t("Open Partners Form"),
var steps = [tour.STEPS.SHOW_APPS_MENU_ITEM, {
trigger: '.fa.fa-cog.o_mail_channel_settings',
content: _t('Select channel settings'),
position: 'bottom', position: 'bottom',
}, {
trigger: '.nav-link:contains("Members")',
content: _t('Go to the list of subscribers'),
position: 'bottom',
}, {
trigger: '.o_data_cell:contains("YourCompany, Marc Demo")',
content: _t("Select a user"),
position: "bottom",
}, {
trigger: '.o_form_uri.o_field_widget:contains("YourCompany, Marc Demo")',
content: _t("Go to user page"),
position: "bottom"
}, { }, {
trigger: "button.oe_compose_post_private", trigger: "button.oe_compose_post_private",
content: _t("Click on Private mail creating button"), content: _t("Click on Private mail creating button"),
@ -26,7 +39,7 @@ odoo.define('mail_private.tour', function (require) {
content: _t("Uncheck all Followers"), content: _t("Uncheck all Followers"),
timeout: 10000, timeout: 10000,
}, { }, {
trigger: "div.o_composer_suggested_partners input:first",
trigger: "div.o_composer_suggested_partners",
content: _t("Check the first one"), content: _t("Check the first one"),
}, { }, {
trigger: "textarea.o_composer_text_field:first", trigger: "textarea.o_composer_text_field:first",

11
mail_private/static/src/xml/mail_private.xml

@ -1,13 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Copyright 2016-2017 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
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.Buttons">
<t t-extend="mail.chatter.Buttons">
<t t-jquery="button[title='Send a message']" t-operation="after"> <t t-jquery="button[title='Send a message']" t-operation="after">
<button class="btn btn-sm btn-link oe_compose_post_private" title="Send a message to specified recipients only">Send internal message</button>
<button class="btn btn-link oe_compose_post_private" title="Send a message to specified recipients only">Send internal message</button>
</t> </t>
</t> </t>
<t t-extend="mail.chatter.ChatComposer">
<t t-extend="mail.chatter.Composer">
<t t-jquery="small[class='o_chatter_composer_info']" t-operation="replace"> <t t-jquery="small[class='o_chatter_composer_info']" t-operation="replace">
<small class="o_chatter_composer_info" t-if="!widget.options.is_private"> <small class="o_chatter_composer_info" t-if="!widget.options.is_private">
To: Followers of To: Followers of
@ -20,7 +23,7 @@
</small> </small>
</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">
<button class="btn btn-sm btn-link oe_composer_uncheck" t-if="widget.options.is_private">Uncheck all</button>
<button class="btn btn-link oe_composer_uncheck" t-if="widget.options.is_private">Uncheck all</button>
</t> </t>
</t> </t>

3
mail_private/template.xml

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--Copyright 2016 x620 <https://github.com/x620>
Copyright 2019 Artem Rafailov <https://it-projects.info/team/Ommo73/>
License LGPL-3.0 (https://www.gnu.org/licenses/lgpl.html).-->
<odoo> <odoo>
<template <template
id="assets_backend" id="assets_backend"

1
mail_private/tests/__init__.py

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

14
mail_private/tests/test_js.py

@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr> # Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# Copyright 2019 Artem Rafailov <https://it-projects.info/team/Ommo73/>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
import odoo.tests import odoo.tests
from odoo.api import Environment
@odoo.tests.common.at_install(True) @odoo.tests.common.at_install(True)
@ -16,15 +15,8 @@ class TestUi(odoo.tests.HttpCase):
# that are returned by the backend in module_boot. Without # that are returned by the backend in module_boot. Without
# this you end up with js, css but no qweb. # this you end up with js, css but no qweb.
cr = self.registry.cursor() cr = self.registry.cursor()
env = Environment(cr, self.uid, {})
env['ir.module.module'].search([('name', '=', 'mail_private')], limit=1).state = 'installed'
cr.release()
env = Environment(self.registry.test_cr, self.uid, {})
partners = env['res.partner'].search([])
new_follower = env['res.partner'].search([('name', 'ilike', 'Ja')])
for partner in partners:
partner.message_subscribe(new_follower.ids, [])
self.env['ir.module.module'].search([('name', '=', 'mail_private')], limit=1).state = 'installed'
cr._lock.release()
self.phantom_js("/web", self.phantom_js("/web",
"odoo.__DEBUG__.services['web_tour.tour'].run('mail_private_tour', 1000)", "odoo.__DEBUG__.services['web_tour.tour'].run('mail_private_tour', 1000)",

Loading…
Cancel
Save