Browse Source

[11.0][PORT] mail_move_message (#146)

pull/153/head
Aleksandr 6 years ago
committed by Ivan Yelizariev
parent
commit
2dfb242689
  1. 49
      mail_move_message/README.rst
  2. 2
      mail_move_message/__init__.py
  3. 30
      mail_move_message/__manifest__.py
  4. 21
      mail_move_message/__openerp__.py
  5. 2
      mail_move_message/controllers/__init__.py
  6. 57
      mail_move_message/controllers/main.py
  7. 4
      mail_move_message/data/mail_move_message_data.xml
  8. 35
      mail_move_message/doc/index.rst
  9. 162
      mail_move_message/mail_move_message_models.py
  10. 95
      mail_move_message/mail_move_message_views.xml
  11. BIN
      mail_move_message/static/description/delete-message.png
  12. BIN
      mail_move_message/static/description/icon.png
  13. BIN
      mail_move_message/static/description/inbox-move.png
  14. 72
      mail_move_message/static/description/index.html
  15. BIN
      mail_move_message/static/description/record-move-back.png
  16. 145
      mail_move_message/static/src/js/mail_move_message.js
  17. 8
      mail_move_message/static/src/xml/mail_move_message_main.xml

49
mail_move_message/README.rst

@ -1,10 +1,49 @@
Mail relocation
===============
.. image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: https://www.gnu.org/licenses/lgpl
:alt: License: LGPL-3
Demo: http://runbot.it-projects.info/demo/mail-addons/9.0
=================
Mail Relocation
=================
Description: https://www.odoo.com/apps/modules/9.0/mail_move_message/
The module allows to relocate messages between models
Credits
=======
Contributors
------------
* `Ivan Yelizariev <https://it-projects.info/team/yelizariev>`__
Sponsors
--------
* `IT-Projects LLC <https://it-projects.info>`__
Maintainers
-----------
* `IT-Projects LLC <https://it-projects.info>`__
To get a guaranteed support
you are kindly requested to purchase the module
at `odoo apps store <https://apps.odoo.com/apps/modules/11.0/mail_move_message/>`__.
Thank you for understanding!
`IT-Projects Team <https://www.it-projects.info/team>`__
Further information
===================
Demo: http://runbot.it-projects.info/demo/mail-addons/11.0
HTML Description: https://apps.odoo.com/apps/modules/11.0/mail_move_message/
Usage instructions: `<doc/index.rst>`_
Changelog: `<doc/changelog.rst>`_
Notifications on updates: `via Atom <https://github.com/it-projects-llc/mail-addons/commits/11.0/mail_move_message.atom>`_, `by Email <https://blogtrottr.com/?subscribe=https://github.com/it-projects-llc/mail-addons/commits/11.0/mail_move_message.atom>`_
Further information and discussion: http://yelizariev.github.io/odoo/module/2015/04/10/mail-relocation.html
Tested on Odoo 8.0 d023c079ed86468436f25da613bf486a4a17d625
Tested on Odoo 11.0 e9454e79e27d0b85546132cbe00b391e974c66bf

2
mail_move_message/__init__.py

@ -1,2 +1,4 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import controllers
from . import mail_move_message_models

30
mail_move_message/__manifest__.py

@ -0,0 +1,30 @@
# Copyright 2016 Ildar Nasyrov <https://it-projects.info/team/iledarn>
# Copyright 2017 Ilmir Karamov <https://it-projects.info/team/ilmir-k>
# Copyright 2017 Lilia Salihova
# Copyright 2016-2018 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Mail Relocation',
'version': '11.0.1.0.5',
'author': 'IT-Projects LLC, Ivan Yelizariev, Pavel Romanchenko',
'license': 'LGPL-3',
'category': 'Discuss',
'images': ['images/m1.png'],
"support": "apps@it-projects.info",
'website': 'https://twitter.com/yelizariev',
'price': 100.00,
'currency': 'EUR',
'depends': [
'mail_all',
],
'data': [
'mail_move_message_views.xml',
'data/mail_move_message_data.xml',
],
'qweb': [
'static/src/xml/mail_move_message_main.xml',
],
'installable': True,
}

21
mail_move_message/__openerp__.py

@ -1,21 +0,0 @@
{
'name': 'Mail relocation',
'version': '1.0.5',
'author': 'IT-Projects LLC, Ivan Yelizariev, Pavel Romanchenko',
'license': 'LGPL-3',
'category': 'Discuss',
'images': ['images/m1.png'],
"support": "apps@it-projects.info",
'website': 'https://twitter.com/yelizariev',
'price': 100.00,
'currency': 'EUR',
'depends': ['mail_all', 'web_polymorphic_field'],
'data': [
'mail_move_message_views.xml',
'data/mail_move_message_data.xml',
],
'qweb': [
'static/src/xml/mail_move_message_main.xml',
],
'installable': False,
}

2
mail_move_message/controllers/__init__.py

@ -1 +1,3 @@
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import main

57
mail_move_message/controllers/main.py

@ -1,6 +1,8 @@
from odoo.addons.web.controllers.main import DataSet
from odoo.tools.translate import _
from odoo import http
# Copyright 2016 Ildar Nasyrov <https://it-projects.info/team/iledarn>
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo.http import request
from odoo.addons.bus.controllers.main import BusController
@ -15,52 +17,3 @@ class MailChatController(BusController):
channels.append((request.db, 'mail_move_message'))
channels.append((request.db, 'mail_move_message.delete_message'))
return super(MailChatController, self)._poll(dbname, channels, last, options)
class DataSetCustom(DataSet):
def _extend_name(self, model, records):
Model = request.env[model]
fields = Model.fields_get()
contact_field = False
for n, f in fields.iteritems():
if f['type'] == 'many2one' and f['relation'] == 'res.partner':
contact_field = n
break
partner_info = {}
if contact_field:
partner_info = Model.browse([r[0] for r in records]).read([contact_field])
partner_info = dict([(p['id'], p[contact_field]) for p in partner_info])
res = []
for r in records:
if partner_info.get(r[0]):
res.append((r[0], _('%s [%s] ID %s') % (r[1], partner_info.get(r[0])[1], r[0])))
else:
res.append((r[0], _('%s ID %s') % (r[1], r[0])))
return res
@http.route('/web/dataset/call_kw/<model>/name_search', type='json', auth="user")
def name_search(self, model, method, args, kwargs):
context = kwargs.get('context')
if context and context.get('extended_name_with_contact'):
# add order by ID desc
Model = request.env[model]
search_args = list(kwargs.get('args') or [])
limit = int(kwargs.get('limit') or 100)
operator = kwargs.get('operator')
name = kwargs.get('name')
if Model._rec_name and (not name == '' and operator == 'ilike'):
search_args += [(Model._rec_name, operator, name)]
records = Model.search(search_args, limit=limit, order='id desc')
res = records.name_get()
return self._extend_name(model, res)
return self._call_kw(model, method, args, kwargs)
@http.route('/web/dataset/call_kw/<model>/name_get', type='json', auth="user")
def name_get(self, model, method, args, kwargs):
res = self._call_kw(model, method, args, kwargs)
context = kwargs.get('context')
if context and context.get('extended_name_with_contact'):
res = self._extend_name(model, res)
return res

4
mail_move_message/data/mail_move_message_data.xml

@ -1,4 +1,8 @@
<?xml version="1.0"?>
<!--# Copyright 2016 Ildar Nasyrov <https://it-projects.info/team/iledarn>
# Copyright 2017 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).-->
<openerp>
<data noupdate="1">
<record id="mail_relocation_models" model="ir.config_parameter">

35
mail_move_message/doc/index.rst

@ -0,0 +1,35 @@
=================
Mail Relocation
=================
Installation
============
* `Install <https://odoo-development.readthedocs.io/en/latest/odoo/usage/install-module.html>`__ this module in a usual way
Configuration
=============
* Open ``[[ Settings ]] >> Mail Relocation`` menu
* In **Model** field add models to be used for message relocation
* Check the box **[x] Move Followers** to move followers by default when relocation
Usage
=====
Move message
------------
* Open ``[[ Discuss ]] >> Inbox`` menu
* Click on icon of two cross arrows
* Select a record you need
* Click **Move**
RESULT: The message has been moved to the record selected.
Move to origin
--------------
* Open the record where the message was moved to
* Click on the two cross arrows icon highlighted as red
* Check the box **[x] Move to origin**
RESULT: The message has been returned back to the original record.

162
mail_move_message/mail_move_message_models.py

@ -1,19 +1,27 @@
from openerp import api
from openerp import fields
from openerp import models
from openerp.tools import email_split
from openerp.tools.translate import _
# Copyright 2016 Ildar Nasyrov <https://it-projects.info/team/iledarn>
# Copyright 2016-2018 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# Copyright 2016 intero-chz <https://github.com/intero-chz>
# Copyright 2016 manawi <https://github.com/manawi>
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import api
from odoo import fields
from odoo import models
from odoo.tools import email_split
from odoo.tools.translate import _
from odoo import exceptions
class Wizard(models.TransientModel):
_name = 'mail_move_message.wizard'
@api.model
def _model_selection(self):
selection = []
config_parameters = self.env['ir.config_parameter']
model_names = config_parameters.get_param('mail_relocation_models')
model_names = config_parameters.sudo().get_param('mail_relocation_models')
model_names = model_names.split(',') if model_names else []
if 'default_message_id' in self.env.context:
message = self.env['mail.message'].browse(self.env.context['default_message_id'])
if message.model and message.model not in model_names:
@ -22,16 +30,16 @@ class Wizard(models.TransientModel):
model_names.append(message.moved_from_model)
if model_names:
selection = [(m.model, m.display_name) for m in self.env['ir.model'].search([('model', 'in', model_names)])]
return selection
@api.model
def default_get(self, fields_list):
res = super(Wizard, self).default_get(fields_list)
model_fields = self.fields_get()
if model_fields['model']['selection']:
res['model'] = model_fields['model']['selection'] and model_fields['model']['selection'][0][0]
available_models = self._model_selection()
if len(available_models):
record = self.env[available_models[0][0]].search([], limit=1)
res['model_record'] = len(record) and (available_models[0][0] + ',' + str(record.id)) or False
if 'message_id' in res:
message = self.env['mail.message'].browse(res['message_id'])
@ -54,10 +62,9 @@ class Wizard(models.TransientModel):
res['res_id'] = res_id[0].id
config_parameters = self.env['ir.config_parameter']
res['move_followers'] = config_parameters.get_param('mail_relocation_move_followers')
res['move_followers'] = config_parameters.sudo().get_param('mail_relocation_move_followers')
res['uid'] = self.env.uid
return res
message_id = fields.Many2one('mail.message', string='Message')
@ -68,16 +75,19 @@ class Wizard(models.TransientModel):
message_moved_by_user_id = fields.Many2one('res.users', related='message_id.moved_by_user_id', string='Moved by', readonly=True)
message_is_moved = fields.Boolean(string='Is Moved', related='message_id.is_moved', readonly=True)
parent_id = fields.Many2one('mail.message', string='Search by name', )
model = fields.Selection(_model_selection, string='Model')
res_id = fields.Integer(string='Record')
can_move = fields.Boolean('Can move', compute='get_can_move')
model_record = fields.Reference(selection="_model_selection", string='Record')
model = fields.Char(compute="_compute_model_res_id", string='Model')
res_id = fields.Integer(compute="_compute_model_res_id", string='Record')
can_move = fields.Boolean('Can move', compute='_compute_get_can_move')
move_back = fields.Boolean('MOVE TO ORIGIN', help='Move message and submessages to original place')
partner_id = fields.Many2one('res.partner', string='Author')
filter_by_partner = fields.Boolean('Filter Records by partner')
message_email_from = fields.Char()
message_name_from = fields.Char()
# FIXME message_to_read should be True even if current message or any his childs are unread
message_to_read = fields.Boolean(related='message_id.needaction')
message_to_read = fields.Boolean(compute='_compute_is_read', string="Unread message",
help="Service field shows that this message were unread when moved")
uid = fields.Integer()
move_followers = fields.Boolean(
'Move Followers',
@ -85,12 +95,24 @@ class Wizard(models.TransientModel):
"You must use this option, if new record has restricted access.\n"
"You can change default value for this option at Settings/System Parameters")
@api.multi
@api.depends('model_record')
def _compute_model_res_id(self):
for rec in self:
rec.model = rec.model_record and rec.model_record._name or False
rec.res_id = rec.model_record and rec.model_record.id or False
@api.depends('message_id')
@api.multi
def get_can_move(self):
def _compute_get_can_move(self):
for r in self:
r.get_can_move_one()
@api.multi
def _compute_is_read(self):
messages = self.env['mail.message'].sudo().browse(self.message_id.all_child_ids.ids + [self.message_id.id])
self.message_to_read = True in [m.needaction for m in messages]
@api.multi
def get_can_move_one(self):
self.ensure_one()
@ -102,12 +124,11 @@ class Wizard(models.TransientModel):
if not self.move_back:
return
self.parent_id = self.message_id.moved_from_parent_id
model = self.message_id.moved_from_model
if self.message_id.is_moved:
self.model = model
self.res_id = self.message_id.moved_from_res_id
message = self.message_id
if message.is_moved:
self.model_record = self.env[message.moved_from_model].browse(message.moved_from_res_id)
@api.onchange('parent_id', 'res_id', 'model')
@api.onchange('parent_id', 'model_record')
def update_move_back(self):
model = self.message_id.moved_from_model
self.move_back = self.parent_id == self.message_id.moved_from_parent_id \
@ -129,7 +150,7 @@ class Wizard(models.TransientModel):
if self.model and self.filter_by_partner and self.partner_id:
fields = self.env[self.model].fields_get(False)
contact_field = False
for n, f in fields.iteritems():
for n, f in fields.items():
if f['type'] == 'many2one' and f['relation'] == 'res.partner':
contact_field = n
break
@ -178,6 +199,10 @@ class Wizard(models.TransientModel):
@api.multi
def move(self):
for r in self:
if not r.model:
raise exceptions.except_orm(_('Record field is empty!'), _('Select a record for relocation first'))
for r in self:
r.check_access()
if not r.parent_id or not (r.parent_id.model == r.model and
@ -185,15 +210,14 @@ class Wizard(models.TransientModel):
# link with the first message of record
parent = self.env['mail.message'].search([('model', '=', r.model), ('res_id', '=', r.res_id)], order='id', limit=1)
r.parent_id = parent.id or None
r.message_id.move(r.parent_id.id, r.res_id, r.model, r.move_back, r.move_followers, r.message_to_read)
r.message_id.move(r.parent_id.id, r.res_id, r.model, r.move_back, r.move_followers)
if not (r.model and r.res_id):
r.message_id.needaction = False
if r.model in ['mail.message', 'mail.channel', False]:
return {
'type': 'ir.actions.client',
'name': 'All messages',
'tag': 'reload',
'name': 'Chess game page',
'type': 'ir.actions.act_url',
'url': '/web',
'target': 'self',
}
return {
'name': _('Record'),
@ -238,7 +262,7 @@ class Wizard(models.TransientModel):
fields = model.fields_get()
contact_field = False
for n, f in fields.iteritems():
for n, f in fields.items():
if f['type'] == 'many2one' and f['relation'] == 'res.partner':
contact_field = n
break
@ -268,10 +292,11 @@ class MailMessage(models.Model):
moved_from_parent_id = fields.Many2one('mail.message', 'Parent Message (Original)', ondelete='set null')
moved_by_message_id = fields.Many2one('mail.message', 'Moved by message', ondelete='set null', help='Top message, that initate moving this message')
moved_by_user_id = fields.Many2one('res.users', 'Moved by user', ondelete='set null')
all_child_ids = fields.One2many('mail.message', string='All childs', compute='_get_all_childs', help='all childs, including subchilds')
all_child_ids = fields.One2many('mail.message', string='All childs', compute='_compute_get_all_childs', help='all childs, including subchilds')
moved_as_unread = fields.Boolean('Was Unread', default=False)
@api.multi
def _get_all_childs(self, include_myself=True):
def _compute_get_all_childs(self, include_myself=True):
for r in self:
r._get_all_childs_one(include_myself=include_myself)
@ -300,12 +325,12 @@ class MailMessage(models.Model):
self.env[model].browse(ids).message_subscribe([f.partner_id.id], [s.id for s in f.subtype_ids])
@api.multi
def move(self, parent_id, res_id, model, move_back, move_followers=False):
def move(self, parent_id, res_id, model, move_back, move_followers=False, message_to_read=False):
for r in self:
r.move_one(parent_id, res_id, model, move_back, move_followers=move_followers)
r.move_one(parent_id, res_id, model, move_back, move_followers=move_followers, message_to_read=message_to_read)
@api.multi
def move_one(self, parent_id, res_id, model, move_back, move_followers=False):
def move_one(self, parent_id, res_id, model, move_back, move_followers=False, message_to_read=False):
self.ensure_one()
if parent_id == self.id:
# if for any reason method is called to move message with parent
@ -322,6 +347,7 @@ class MailMessage(models.Model):
vals['moved_from_res_id'] = None
vals['moved_from_model'] = None
vals['moved_from_parent_id'] = None
vals['moved_as_unread'] = None
else:
vals['parent_id'] = parent_id
vals['res_id'] = res_id
@ -330,22 +356,34 @@ class MailMessage(models.Model):
vals['is_moved'] = True
vals['moved_by_user_id'] = self.env.user.id
vals['moved_by_message_id'] = self.id
# Update record_name in message
vals['record_name'] = self._get_record_name(vals)
vals['moved_as_unread'] = message_to_read
# Update record_name in message
vals['record_name'] = self._get_record_name(vals)
# unread message remains unread after moving back to origin
if self.moved_as_unread and move_back:
notification = {
'mail_message_id': self.id,
'res_partner_id': self.env.user.partner_id.id,
'is_read': False,
}
self.write({
'notification_ids': [(0, 0, notification)],
})
for r in self.all_child_ids:
r_vals = vals.copy()
if not r.is_moved:
# moved_from_* variables contain not last, but original
# reference
r_vals['moved_from_parent_id'] = r.parent_id.id
r_vals['moved_from_res_id'] = r.res_id
r_vals['moved_from_model'] = r.model
r_vals['moved_from_parent_id'] = r.parent_id.id or r.env.context.get('uid')
r_vals['moved_from_res_id'] = r.res_id or r.id
r_vals['moved_from_model'] = r.model or r._name
elif move_back:
r_vals['parent_id'] = r.moved_from_parent_id.id
r_vals['res_id'] = r.moved_from_res_id
r_vals['model'] = r.moved_from_model
r_vals['model'] = (r.moved_from_model and r.moved_from_model not in ['mail.message', 'mail.channel', False]) and r.moved_from_model
r_vals['record_name'] = r_vals['model'] and self.env[r.moved_from_model].browse(r.moved_from_res_id).name
if move_followers:
r.sudo().move_followers(r_vals.get('model'), r_vals.get('res_id'))
@ -361,7 +399,7 @@ class MailMessage(models.Model):
'res_id': vals.get('res_id'),
'model': vals.get('model'),
'is_moved': vals['is_moved'],
'record_name': vals['record_name']
'record_name': 'record_name' in vals and vals['record_name'],
}
self.env['bus.bus'].sendone((self._cr.dbname, 'mail_move_message'), notification)
@ -390,34 +428,32 @@ class MailMessage(models.Model):
class MailMoveMessageConfiguration(models.TransientModel):
_name = 'mail_move_message.config.settings'
_inherit = 'res.config.settings'
model_ids = fields.Many2many(comodel_name='ir.model', string='Models')
move_followers = fields.Boolean('Move Followers')
@api.model
def get_default_move_message_configs(self, fields):
config_parameters = self.env['ir.config_parameter']
model_obj = self.env['ir.model']
model_names = config_parameters.get_param('mail_relocation_models')
if not model_names:
return {}
def get_values(self):
res = super(MailMoveMessageConfiguration, self).get_values()
config_parameters = self.env["ir.config_parameter"].sudo()
model_names = config_parameters.sudo().get_param('mail_relocation_models')
model_names = model_names.split(',')
model_ids = model_obj.search([('model', 'in', model_names)])
return {
'model_ids': [m.id for m in model_ids],
'move_followers': config_parameters.get_param('mail_relocation_move_followers')
}
model_ids = self.env['ir.model'].sudo().search([('model', 'in', model_names)])
res.update(
model_ids=[m.id for m in model_ids],
move_followers=config_parameters.sudo().get_param('mail_relocation_move_followers'),
)
return res
@api.multi
def set_move_message_configs(self):
config_parameters = self.env['ir.config_parameter']
model_names = ''
def set_values(self):
super(MailMoveMessageConfiguration, self).set_values()
config_parameters = self.env["ir.config_parameter"].sudo()
for record in self:
model_names = ','.join([m.model for m in record.model_ids])
config_parameters.set_param('mail_relocation_models', model_names)
config_parameters.set_param('mail_relocation_move_followers', record.move_followers or '')
model_names = ','.join([x.model for x in record.model_ids])
config_parameters.set_param("mail_relocation_models", model_names or '')
config_parameters.set_param("mail_relocation_move_followers", record.move_followers or '')
class ResPartner(models.Model):

95
mail_move_message/mail_move_message_views.xml

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp><data>
<!--# Copyright 2016 Ildar Nasyrov <https://it-projects.info/team/iledarn>
# Copyright 2016 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).-->
<odoo>
<template id="assets_backend" name="custom bar assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
@ -29,9 +34,11 @@
</group>
<group attrs="{'invisible':[('can_move', '=', False)]}" colspan="2">
<label for="model"/>
<label for="model_record"/>
<div>
<field name="model" widget="polymorphic" polymorphic="res_id" class="oe_inline"/>
<field name="model_record" class="oe_inline"/>
<field name="model" invisible="1"/>
<field name="res_id" invisible="1"/>
</div>
<label for="filter_by_partner"/>
<div>
@ -41,11 +48,6 @@
class="oe_highlight oe_inline ml32"
special="quick_create" field="partner_id" context="{'force_email':True,'default_email':message_email_from,'default_name':message_name_from, 'update_message_author':True}" />
</div>
<label for="res_id"/>
<div>
<field name="res_id" context="{'extended_name_with_contact':1}" widget="many2one" attrs="{'readonly': [('model','=',False)]}" class="oe_inline"/>
<button string="Create new record" name="create_record" type="object" class="oe_highlight oe_inline ml32" attrs="{'invisible':['|',('model','=',False)]}" special="quick_create" field="res_id" use_for_mail_move_message="True"/>
</div>
<label for="move_back" attrs="{'invisible':[('message_is_moved','=',False)]}"/>
<div attrs="{'invisible':[('message_is_moved','=',False)]}">
<field name="move_back"/>
@ -86,39 +88,50 @@
</field>
</record>
<!-- Relocation config wizard -->
<record id="view_mail_move_message_config_settings" model="ir.ui.view">
<field name="name">relocation settings</field>
<field name="model">mail_move_message.config.settings</field>
<field name="arch" type="xml">
<form string="Configure Mail Relocation" class="oe_form_configuration">
<header>
<button string="Apply" type="object" name="execute" class="oe_highlight"/>
or
<button string="Cancel" type="object" name="cancel" class="oe_link"/>
</header>
<div name="general">
<separator string="Models"/>
<field name="model_ids" widget="many2many_tags"/>
<separator string="Options"/>
<label for="move_followers"/>
<field name="move_followers"/>
<!-- Relocation config wizard -->
<record id="view_mail_move_message_config_settings" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="55"/>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('settings')]" position="inside">
<div class="app_settings_block" data-string="Mail Relocation" string="Mail Relocation" data-key="mail_move_message">
<h2>Mail Relocation</h2>
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-6 o_setting_box" id="crm_lead">
<div class="o_setting_left_pane">
</div>
<div class="o_setting_right_pane">
<label for="model_ids"/>
<div class="text-muted">
Add models to be used for message relocation
</div>
<field name="model_ids" widget="many2many_tags"/>
</div>
</div>
</form>
</field>
</record>
<record id="action_mail_move_message_config" model="ir.actions.act_window">
<field name="name">Mail Relocation</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mail_move_message.config.settings</field>
<field name="view_id" ref="view_mail_move_message_config_settings"/>
<field name="view_mode">form</field>
<field name="target">inline</field>
</record>
<div class="col-xs-12 col-md-6 o_setting_box" id="crm_lead">
<div class="o_setting_left_pane">
<field name="move_followers"/>
</div>
<div class="o_setting_right_pane">
<label for="move_followers"/>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
<!-- Add menu entry in Settings/Email -->
<menuitem name="Mail Relocation" id="menu_mail_move_message" parent="base.menu_email" sequence="99" action="action_mail_move_message_config"/>
<record id="action_mail_move_message_config" model="ir.actions.act_window">
<field name="name">Mail Relocation</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.config.settings</field>
<field name="view_id" ref="view_mail_move_message_config_settings"/>
<field name="view_mode">form</field>
<field name="target">inline</field>
<field name="context">{'module' : 'mail_move_message'}</field>
</record>
</data>
</openerp>
</odoo>

BIN
mail_move_message/static/description/delete-message.png

Before

Width: 1012  |  Height: 546  |  Size: 39 KiB

After

Width: 667  |  Height: 446  |  Size: 32 KiB

BIN
mail_move_message/static/description/icon.png

Before

Width: 149  |  Height: 149  |  Size: 1.5 KiB

After

Width: 100  |  Height: 100  |  Size: 2.1 KiB

BIN
mail_move_message/static/description/inbox-move.png

Before

Width: 1054  |  Height: 562  |  Size: 57 KiB

After

Width: 667  |  Height: 446  |  Size: 32 KiB

72
mail_move_message/static/description/index.html

@ -1,26 +1,27 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Mail relocation</h2>
<h2 class="oe_slogan">Mail Relocation</h2>
<h3 class="oe_slogan">Relocate customer's mails to a correct place (lead, task etc.)</h3>
</div>
<div class="oe_span12">
<p class="oe_mt32">
<div class="alert alert-success" style="padding:0.6em 0.6em; font-size: 120%;">
<p>
The module helps you to organise mails from customers.
</p>
<p>
If customer send mail to user's personal alias (e.g. admin@yourcompany.example.com), a user would be able to relocate such mail to corresponding record.
</p>
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<div class="oe_span12 text-center">
<h2>Usage</h2>
<p class="oe_mt32">
<p class="oe_mt32 text-center">
Click on an icon of two cross arrows.
</p>
</div>
@ -36,7 +37,7 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<p class="oe_mt32">
<p class="oe_mt32 text-center">
Find a record you need and click on "Move" button.
</p>
</div>
@ -52,7 +53,7 @@
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<p class="oe_mt32">
<p class="oe_mt32 text-center">
Done! You've attached mail and its child mails to the record.
</p>
</div>
@ -61,7 +62,7 @@
<div class="oe_demo oe_picture oe_screenshot">
<img src="record1.png?3"/>
</div>
<p class="oe_mt32">
<p class="oe_mt32 text-center">
Scroll down... Moved mails are marked by highlighted icon.
</p>
<div class="oe_demo oe_picture oe_screenshot">
@ -74,16 +75,16 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<p class="oe_mt32">
<p class="oe_mt32 text-center">
You could easily return mails back if you change your mind.
</p>
</div>
<div class="oe_span12">
<div class="oe_demo oe_picture oe_screenshot">
<div class="oe_demo oe_picture" style="margin-bottom: 4em;">
<img src="record-move-back.png?1"/>
</div>
<p class="oe_mt32">
<p class="oe_mt32 text-center">
Further information and discussion: <a href="https://yelizariev.github.io/odoo/module/2015/04/10/mail-relocation.html">https://yelizariev.github.io/odoo/module/2015/04/10/mail-relocation.html</a>
</p>
</div>
@ -93,30 +94,69 @@
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<div class="oe_span12 text-center">
<h2>Tips and tricks</h2>
</div>
<div class="oe_span12">
<p class="oe_mt32">
The module can be used to delete a message (it's available for superuser only)
</p>
<div class="oe_demo oe_picture oe_screenshot">
<div class="oe_demo oe_picture">
<img src="delete-message.png"/>
</div>
</div>
</div>
</section>
<br/>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<div class="oe_span8">
<h2>Need our service?</h2>
<p class="oe_mt32">Contact us by <a href="mailto:apps@it-projects.info">email</a> or fill out <a href="https://www.it-projects.info/page/website.contactus " target="_blank">request form</a></p>
<ul>
<li><a href="mailto:apps@it-projects.info">apps@it-projects.info <i class="fa fa-envelope-o"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">
https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
<li><a href="https://www.it-projects.info/page/website.contactus " target="_blank">https://www.it-projects.info/page/website.contactus <i class="fa fa-list-alt"></i></a></li>
</ul>
</div>
<div class="oe_span4">
<div class="stamp" style="width:200px;">
<div style="margin-top: 15px;
position: relative;
font-family:'Vollkorn', serif;
font-size: 16px;
line-height: 25px;
text-transform: uppercase;
font-weight: bold;
color: #75526b;
border: 3px dashed #75526b;
float: left;
padding: 4px 12px;
-webkit-transform: rotate(6deg);
-o-transform: rotate(6deg);
-moz-transform: rotate(6deg);
-ms-transform: rotate(6deg);">
Tested on Odoo<br/>11.0 community
</div>
<div style="margin-top: 15px;
position: relative;
font-family:'Vollkorn', serif;
font-size: 16px;
line-height: 25px;
text-transform: uppercase;
font-weight: bold;
color: #75526b;
border: 3px dashed #75526b;
float: left;
padding: 4px 12px;
-webkit-transform: rotate(-7deg);
-o-transform: rotate(-7deg);
-moz-transform: rotate(-7deg);
-ms-transform: rotate(-7deg);">
Tested on Odoo<br/>11.0 enterprise
</div>
</div>
</div>
</div>
</section>

BIN
mail_move_message/static/description/record-move-back.png

Before

Width: 904  |  Height: 482  |  Size: 42 KiB

After

Width: 658  |  Height: 465  |  Size: 44 KiB

145
mail_move_message/static/src/js/mail_move_message.js

@ -1,15 +1,27 @@
/*Copyright 2016 Ildar Nasyrov <https://it-projects.info/team/iledarn>
# Copyright 2016 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# Copyright 2016 Pavel Romanchenko
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). */
odoo.define('mail_move_message.relocate', function (require) {
"use strict";
var bus = require('bus.bus').bus;
var chat_manager = require('mail.chat_manager');
var base_obj = require('mail_base.base');
var chat_manager = require('mail_base.base').chat_manager;
var thread = require('mail.ChatThread');
var chatter = require('mail.Chatter');
var Model = require('web.Model');
var form_common = require('web.form_common');
var widgets = require('web.form_widgets');
var rpc = require('web.rpc');
var Basicmodel = require('web.BasicModel');
var view_dialogs = require('web.view_dialogs');
var field_utils_format = require('web.field_utils').format;
var BasicRenderer = require('web.BasicRenderer');
var core = require('web.core');
var form_widget = require('web.FormRenderer');
var session = require('web.Session');
var FormController = require('web.FormController');
var FormView = require('web.FormView');
var registry = require('web.field_registry');
var _t = core._t;
@ -33,7 +45,6 @@ odoo.define('mail_move_message.relocate', function (require) {
target: 'new',
context: {'default_message_id': message_id}
};
this.do_action(action, {
'on_close': function(){}
});
@ -44,12 +55,14 @@ odoo.define('mail_move_message.relocate', function (require) {
start: function() {
var result = this._super.apply(this, arguments);
// For show wizard in the form
this.thread.on('move_message', this, this.thread.on_move_message);
if (this.fields.thread && this.fields.thread.thread) {
var thread = this.fields.thread.thread;
thread.on('move_message', this, thread.on_move_message);
}
return $.when(result).done(function() {});
}
});
var ChatAction = core.action_registry.get('mail.chat.instant_messaging');
ChatAction.include({
start: function() {
@ -60,85 +73,45 @@ odoo.define('mail_move_message.relocate', function (require) {
}
});
base_obj.MailTools.include({
make_message: function(data){
var msg = this._super(data);
// Mark msg as moved after reload
msg.is_moved = data.is_moved || false;
return msg;
},
on_notification: function(notifications){
this._super(notifications);
var self = this;
_.each(notifications, function (notification) {
var model = notification[0][1];
var message_id = notification[1].id;
var message = base_obj.chat_manager.get_message(message_id);
if (model === 'mail_move_message' && message) {
message.res_id = notification[1].res_id;
message.model = notification[1].model;
message.record_name = notification[1].record_name;
// Mark message as moved after move
message.is_moved = notification[1].is_moved;
// Update cache and accordingly message in the thread
self.add_to_cache(message, []);
// Call thread.on_update_message(message)
chat_manager.bus.trigger('update_message', message);
} else if (model === 'mail_move_message.delete_message') {
self.remove_from_cache(message, []);
chat_manager.bus.trigger('update_message', message);
}
});
}
});
widgets.WidgetButton.include({
on_click: function(){
if(this.node.attrs.special == 'quick_create'){
var self = this;
var related_field = this.field_manager.fields[this.node.attrs.field];
var context_built = $.Deferred();
if(this.node.attrs.use_for_mail_move_message) {
var model = new Model(this.view.dataset.model);
var partner_id = self.field_manager.fields.partner_id.get_value();
var message_name_from = self.field_manager.fields.message_name_from.get_value();
var message_email_from = self.field_manager.fields.message_email_from.get_value();
context_built = model.call('create_partner', [
self.view.dataset.context.default_message_id,
related_field.field.relation,
partner_id,
message_name_from,
message_email_from
]);
}
else {
context_built.resolve(this.build_context());
}
$.when(context_built).pipe(function (context) {
if(self.node.attrs.use_for_mail_move_message) {
self.field_manager.fields.partner_id.set_value(context.partner_id);
}
var dialog = new form_common.FormViewDialog(self, {
res_model: related_field.field.relation,
res_id: false,
context: context,
title: _t("Create new record")
}).open();
dialog.on('closed', self, function () {
self.force_disabled = false;
self.check_disable();
});
dialog.on('create_completed', self, function(id) {
related_field.set_value(id);
if(self.field_manager.fields.filter_by_partner) {
self.field_manager.fields.filter_by_partner.set_value(true);
}
});
});
}
else {
this._super.apply(this, arguments);
// override methods of chat manager
var chat_manager_super_make_message = chat_manager.make_message;
chat_manager.make_message = function(data){
var msg = chat_manager_super_make_message(data);
// Mark msg as moved after reload
msg.is_moved = data.is_moved || false;
return msg;
};
var chat_manager_super_on_notification = chat_manager.on_notification;
chat_manager.on_notification = function(notifications){
chat_manager_super_on_notification(notifications);
var self = this;
_.each(notifications, function (notification) {
var model = notification[0][1];
var message_id = notification[1].id;
var message = chat_manager.get_message(message_id);
if (model === 'mail_move_message' && message) {
message.res_id = notification[1].res_id;
message.model = notification[1].model;
message.record_name = notification[1].record_name;
// Mark message as moved after move
message.is_moved = notification[1].is_moved;
// Update cache and accordingly message in the thread
self.add_to_cache(message, []);
// Call thread.on_update_message(message)
chat_manager.bus.trigger('update_message', message);
} else if (model === 'mail_move_message.delete_message') {
_.each(message.channel_ids, function(ch){
self.remove_message_from_channel(ch, message);
})
chat_manager.bus.trigger('update_message', message);
}
});
};
Basicmodel.include({
applyDefaultValues: function (recordID, values, options) {
delete values.model
return this._super(recordID, values, options)
}
});
});

8
mail_move_message/static/src/xml/mail_move_message_main.xml

@ -1,7 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--# Copyright 2016 Ildar Nasyrov <https://it-projects.info/team/iledarn>
# Copyright 2016 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# Copyright 2016 Pavel Romanchenko
# Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).-->
<template>
<t t-extend="mail.ChatThread.Message">
<t t-jquery='p.o_mail_info>span>i:first-child' t-operation="before">
<t t-jquery='p.o_mail_info span:last-child i:first-child' t-operation="before">
<i t-if="!message.is_system_notification" t-att-class="'fa fa-exchange oe_move' + (message.is_moved ? ' oe_moved' : '')"
t-att-data-message-id="message.id" title="Move to thread"/>
</t>

Loading…
Cancel
Save