[MERGE] Merged a Mail update
- fix of the behavior of the mailboxes, now more closely related to a todo-list - some code optimization to lessen the number of queries when displaying messages or for list view using the message_unread field - code update of chatter (mail.js) - added some demo data bzr revid: tde@openerp.com-20121112155148-ktljqs3w58cvsk6r
@@ -22,12 +22,12 @@
|
||||
import mail_message_subtype
|
||||
import mail_alias
|
||||
import mail_followers
|
||||
import mail_vote
|
||||
import mail_favorite
|
||||
import mail_message
|
||||
import mail_mail
|
||||
import mail_thread
|
||||
import mail_group
|
||||
import mail_vote
|
||||
import res_partner
|
||||
import res_users
|
||||
import report
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<field name="notification_email_send">none</field>
|
||||
</record>
|
||||
|
||||
<!-- Pushed to all employees -->
|
||||
<record id="message_blogpost0" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="res_id" ref="mail.group_all_employees"/>
|
||||
@@ -15,7 +16,6 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
</record>
|
||||
|
||||
<record id="message_blogpost0_comment0" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="res_id" ref="group_all_employees"/>
|
||||
@@ -24,7 +24,6 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
</record>
|
||||
|
||||
<record id="message_blogpost0_comment1" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="res_id" ref="group_all_employees"/>
|
||||
@@ -33,7 +32,7 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
</record>
|
||||
|
||||
<!-- This one is starred for having mailboxes with demo data -->
|
||||
<record id="message_blogpost0_comment2" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="res_id" ref="group_all_employees"/>
|
||||
@@ -41,8 +40,8 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company
|
||||
<field name="parent_id" ref="message_blogpost0"/>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="favorite_user_ids" eval="[(6, 0, [ref('base.user_root'), ref('base.user_demo')])]"/>
|
||||
</record>
|
||||
|
||||
<record id="message_blogpost0_comment3" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="res_id" ref="group_all_employees"/>
|
||||
@@ -52,5 +51,196 @@ This month you also get 250 EUR of eco-vouchers if you have been in the company
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
</record>
|
||||
|
||||
<!-- Demo user and admin conversation -->
|
||||
<record id="message_discussion" model="mail.message">
|
||||
<field name="body">Hello Demo User! I was wondering whether you had some issues with our secret task about putting cats everywhere in OpenERP.</field>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_root"/>
|
||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]"/>
|
||||
</record>
|
||||
<record id="message_discussion_answer1" model="mail.message">
|
||||
<field name="body">No specific issues, I think everything is clear.</field>
|
||||
<field name="parent_id" ref="message_discussion"/>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_root')])]"/>
|
||||
</record>
|
||||
<record id="message_discussion_answer2" model="mail.message">
|
||||
<field name="body">Ow, just to be sure... we were talking about lolcats, right ?</field>
|
||||
<field name="parent_id" ref="message_discussion"/>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_root')])]"/>
|
||||
</record>
|
||||
<record id="message_discussion_answer3" model="mail.message">
|
||||
<field name="body">Absolutely!</field>
|
||||
<field name="parent_id" ref="message_discussion"/>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_root"/>
|
||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]"/>
|
||||
</record>
|
||||
|
||||
<!-- External mail + reply with attachment conversation -->
|
||||
<record id="message_video2" model="mail.message">
|
||||
<field name="subject">Plan to install OpenERP</field>
|
||||
<field name="model">mail.message</field>
|
||||
<field name="body">
|
||||
<![CDATA[Email0 inquiry]]>
|
||||
<div><font size="2">Hello,</font></div><div><font size="2"><br></font></div>
|
||||
<div><font size="2">I am interested in your company's product and I plan to install OpenERP for my company and affordable price.</font></div><br/>
|
||||
<div><font size="2">Can you please send me services catalogue?</font></div><br/>
|
||||
Sophie
|
||||
</field>
|
||||
<field name="type">email</field>
|
||||
<field name="author_id" ref="base.res_partner_2"/>
|
||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo'), ref('base.partner_root')])]"/>
|
||||
</record>
|
||||
<record id="message_video2_attachment1" model="ir.attachment">
|
||||
<field name="model">ir.attachment</field>
|
||||
<field name="datas">bWlncmF0aW9uIHRlc3Q=</field>
|
||||
<field name="datas_fname">catalogue 2012.pdf</field>
|
||||
<field name="name">catalogue 2012.pdf</field>
|
||||
</record>
|
||||
<record id="message_video2_message1" model="mail.message">
|
||||
<field name="subject">Re: Plan to install OpenERP</field>
|
||||
<field name="body">
|
||||
Dear Customer,<br/>
|
||||
Thanks for showing interest in our products.<br/>
|
||||
We have attached the catalogue,<br/>
|
||||
We would like to know your interests, so let us know when we can call you for more details.<br/>
|
||||
Regards
|
||||
</field>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="parent_id" ref="message_video2"/>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="attachment_ids" eval="[(6, 0, [ref('message_video2_attachment1')])]"/>
|
||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo'),ref('base.partner_root'),ref('base.res_partner_2')])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Employee & other + attachments conversation -->
|
||||
<record id="message_video1_attachment1" model="ir.attachment">
|
||||
<field name="model">ir.attachment</field>
|
||||
<field name="datas">bWlncmF0aW9uIHRlc3Q=</field>
|
||||
<field name="datas_fname">migration.doc</field>
|
||||
<field name="name">migration.doc</field>
|
||||
</record>
|
||||
<record id="message_video1_attachment2" model="ir.attachment">
|
||||
<field name="model">ir.attachment</field>
|
||||
<field name="datas">
|
||||
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
|
||||
CAEAIAQAgP/Z
|
||||
</field>
|
||||
<field name="datas_fname">activity graph 2012.jpg</field>
|
||||
<field name="name">activity graph 2012</field>
|
||||
</record>
|
||||
<record id="message_video1" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="body">
|
||||
Hi,<br/>
|
||||
The beta OpenERP 7 is scheduled for November 12.<br/>
|
||||
You will find attached the document for migration from version 6 to 7, and the activity graph for the current year. Good reading.<br/>
|
||||
Sincerely
|
||||
</field>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="attachment_ids" eval="[(6, 0, [ref('message_video1_attachment1'), ref('message_video1_attachment2')])]"/>
|
||||
<field name="notified_partner_ids" eval="[(6, 0, [ref('base.partner_demo'), ref('base.partner_root')])]"/>
|
||||
</record>
|
||||
<record id="message_video1_message1" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="body">
|
||||
Thank you,<br/>
|
||||
Could you prepare and send us also the document for version 7.1 which will come soon?<br/>
|
||||
Sincerely
|
||||
</field>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="parent_id" ref="message_video1"/>
|
||||
<field name="author_id" ref="base.partner_root"/>
|
||||
<field name="notified_partner_ids" eval="[(6, 0, [ref('base.partner_demo'), ref('base.partner_root')])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Network admin & employee conversation -->
|
||||
<record id="message_video0" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="body">I changed the infrastructure of networks, if there are still changes to be made please do not hesitate to contact me.</field>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_root"/>
|
||||
<field name="notified_partner_ids" eval="[(6, 0, [ref('base.partner_demo'), ref('base.partner_root')])]"/>
|
||||
</record>
|
||||
<record id="message_video0_message1" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="body">Thank you, the networks is perfect now ! Could you add a IP phone for Jhon ?</field>
|
||||
<field name="parent_id" ref="message_video0"/>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="notified_partner_ids" eval="[(6, 0, [ref('base.partner_demo'), ref('base.partner_root')])]"/>
|
||||
</record>
|
||||
<record id="message_video0_message2" model="mail.message">
|
||||
<field name="model">mail.group</field>
|
||||
<field name="body">It's right, his internal phone number is 0093</field>
|
||||
<field name="parent_id" ref="message_video0"/>
|
||||
<field name="type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_root"/>
|
||||
<field name="notified_partner_ids" eval="[(6, 0, [ref('base.partner_demo'), ref('base.partner_root')])]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -61,10 +61,10 @@ class mail_notification(osv.Model):
|
||||
|
||||
_columns = {
|
||||
'partner_id': fields.many2one('res.partner', string='Contact',
|
||||
ondelete='cascade', required=True),
|
||||
'read': fields.boolean('Read'),
|
||||
ondelete='cascade', required=True, select=1),
|
||||
'read': fields.boolean('Read', select=1),
|
||||
'message_id': fields.many2one('mail.message', string='Message',
|
||||
ondelete='cascade', required=True),
|
||||
ondelete='cascade', required=True, select=1),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
@@ -102,7 +102,7 @@ class mail_notification(osv.Model):
|
||||
# some messages do not have notifications: find which one, create notification, update read status
|
||||
exist_notification = dict.fromkeys(msg_ids, False)
|
||||
for notification in self.browse(cr, uid, notif_ids, context=context):
|
||||
exist_notification[notification.message_id] = True
|
||||
exist_notification[notification.message_id.id] = True
|
||||
for msg_id in exist_notification.keys():
|
||||
self.create(cr, uid, {'partner_id': user_pid, 'read': read, 'message_id': msg_id}, context=context)
|
||||
return self.write(cr, uid, notif_ids, {'read': read}, context=context)
|
||||
|
||||
@@ -50,8 +50,9 @@ class mail_message(osv.Model):
|
||||
_description = 'Message'
|
||||
_inherit = ['ir.needaction_mixin']
|
||||
_order = 'id desc'
|
||||
_rec_name = 'record_name'
|
||||
|
||||
_message_read_limit = 10
|
||||
_message_read_limit = 30
|
||||
_message_read_fields = ['id', 'parent_id', 'model', 'res_id', 'body', 'subject', 'date', 'to_read', 'email_from',
|
||||
'type', 'vote_user_ids', 'attachment_ids', 'author_id', 'partner_ids', 'record_name', 'favorite_user_ids']
|
||||
_message_record_name_length = 18
|
||||
@@ -120,21 +121,26 @@ class mail_message(osv.Model):
|
||||
"message, comment for other messages such as user replies"),
|
||||
'email_from': fields.char('From',
|
||||
help="Email address of the sender. This field is set when no matching partner is found for incoming emails."),
|
||||
'author_id': fields.many2one('res.partner', 'Author',
|
||||
'author_id': fields.many2one('res.partner', 'Author', select=1,
|
||||
ondelete='set null',
|
||||
help="Author of the message. If not set, email_from may hold an email address that did not match any partner."),
|
||||
'partner_ids': fields.many2many('res.partner', string='Recipients'),
|
||||
'notified_partner_ids': fields.many2many('res.partner', 'mail_notification',
|
||||
'message_id', 'partner_id', 'Recipients'),
|
||||
'message_id', 'partner_id', 'Notified partners',
|
||||
help='Partners that have a notification pushing this message in their mailboxes'),
|
||||
'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel',
|
||||
'message_id', 'attachment_id', 'Attachments'),
|
||||
'parent_id': fields.many2one('mail.message', 'Parent Message', select=True, ondelete='set null', help="Initial thread message."),
|
||||
'parent_id': fields.many2one('mail.message', 'Parent Message', select=True,
|
||||
ondelete='set null', help="Initial thread message."),
|
||||
'child_ids': fields.one2many('mail.message', 'parent_id', 'Child Messages'),
|
||||
'model': fields.char('Related Document Model', size=128, select=1),
|
||||
'res_id': fields.integer('Related Document ID', select=1),
|
||||
'record_name': fields.function(_get_record_name, type='char',
|
||||
store=True, string='Message Record Name',
|
||||
help="Name get of the related document."),
|
||||
'notification_ids': fields.one2many('mail.notification', 'message_id', 'Notifications'),
|
||||
'notification_ids': fields.one2many('mail.notification', 'message_id',
|
||||
string='Notifications',
|
||||
help='Technical field holding the message notifications. Use notified_partner_ids to access notified partners.'),
|
||||
'subject': fields.char('Subject'),
|
||||
'date': fields.datetime('Date'),
|
||||
'message_id': fields.char('Message-Id', help='Message unique identifier', select=1, readonly=1),
|
||||
@@ -142,7 +148,8 @@ class mail_message(osv.Model):
|
||||
'to_read': fields.function(_get_to_read, fnct_search=_search_to_read,
|
||||
type='boolean', string='To read',
|
||||
help='Functional field to search for messages the current user has to read'),
|
||||
'subtype_id': fields.many2one('mail.message.subtype', 'Subtype'),
|
||||
'subtype_id': fields.many2one('mail.message.subtype', 'Subtype',
|
||||
ondelete='set null', select=1,),
|
||||
'vote_user_ids': fields.many2many('res.users', 'mail_vote',
|
||||
'message_id', 'user_id', string='Votes',
|
||||
help='Users that voted for this message'),
|
||||
@@ -200,67 +207,99 @@ class mail_message(osv.Model):
|
||||
# Message loading for web interface
|
||||
#------------------------------------------------------
|
||||
|
||||
def _message_get_dict(self, cr, uid, message, context=None):
|
||||
""" Return a dict representation of the message. This representation is
|
||||
used in the JS client code, to display the messages.
|
||||
def _message_read_dict_postprocess(self, cr, uid, messages, message_tree, context=None):
|
||||
""" Post-processing on values given by message_read. This method will
|
||||
handle partners in batch to avoid doing numerous queries.
|
||||
|
||||
:param dict message: read result of a mail.message
|
||||
:param list messages: list of message, as get_dict result
|
||||
:param dict message_tree: {[msg.id]: msg browse record}
|
||||
"""
|
||||
# TDE note: this method should be optimized, to lessen the number of queries, will be done ASAP
|
||||
is_author = False
|
||||
if message['author_id']:
|
||||
is_author = message['author_id'][0] == self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0]
|
||||
author_id = message['author_id']
|
||||
elif message['email_from']:
|
||||
author_id = (0, message['email_from'])
|
||||
res_partner_obj = self.pool.get('res.partner')
|
||||
ir_attachment_obj = self.pool.get('ir.attachment')
|
||||
pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=None)['partner_id'][0]
|
||||
|
||||
has_voted = False
|
||||
if uid in message.get('vote_user_ids'):
|
||||
has_voted = True
|
||||
# 1. Aggregate partners (author_id and partner_ids) and attachments
|
||||
partner_ids = set()
|
||||
attachment_ids = set()
|
||||
for key, message in message_tree.iteritems():
|
||||
if message.author_id:
|
||||
partner_ids |= set([message.author_id.id])
|
||||
if message.partner_ids:
|
||||
partner_ids |= set([partner.id for partner in message.partner_ids])
|
||||
if message.attachment_ids:
|
||||
attachment_ids |= set([attachment.id for attachment in message.attachment_ids])
|
||||
|
||||
is_favorite = False
|
||||
if uid in message.get('favorite_user_ids'):
|
||||
is_favorite = True
|
||||
# Filter author_ids uid can see
|
||||
# partner_ids = self.pool.get('res.partner').search(cr, uid, [('id', 'in', partner_ids)], context=context)
|
||||
partners = res_partner_obj.name_get(cr, uid, list(partner_ids), context=context)
|
||||
partner_tree = dict((partner[0], partner) for partner in partners)
|
||||
|
||||
is_private = True
|
||||
if message.get('model') and message.get('res_id'):
|
||||
is_private = False
|
||||
# 2. Attachments
|
||||
attachments = ir_attachment_obj.read(cr, uid, list(attachment_ids), ['id', 'datas_fname'], context=context)
|
||||
attachments_tree = dict((attachment['id'], {'id': attachment['id'], 'filename': attachment['datas_fname']}) for attachment in attachments)
|
||||
|
||||
try:
|
||||
attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, message['attachment_ids'], context=context)]
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
attachment_ids = []
|
||||
|
||||
# TDE note: should we send partner_ids ?
|
||||
# TDE note: shouldn't we separated followers and other partners ? costly to compute maybe ,
|
||||
try:
|
||||
partner_ids = self.pool.get('res.partner').name_get(cr, uid, message['partner_ids'], context=context)
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
# 3. Update message dictionaries
|
||||
for message_dict in messages:
|
||||
message_id = message_dict.get('id')
|
||||
message = message_tree[message_id]
|
||||
if message.author_id:
|
||||
author = partner_tree[message.author_id.id]
|
||||
else:
|
||||
author = (0, message.email_from)
|
||||
partner_ids = []
|
||||
for partner in message.partner_ids:
|
||||
if partner.id in partner_tree:
|
||||
partner_ids.append(partner_tree[partner.id])
|
||||
attachment_ids = []
|
||||
for attachment in message.attachment_ids:
|
||||
if attachment.id in attachments_tree:
|
||||
attachment_ids.append(attachments_tree[attachment.id])
|
||||
message_dict.update({
|
||||
'is_author': pid == author[0],
|
||||
'author_id': author,
|
||||
'partner_ids': partner_ids,
|
||||
'attachment_ids': attachment_ids,
|
||||
})
|
||||
return True
|
||||
|
||||
return {
|
||||
'id': message['id'],
|
||||
'type': message['type'],
|
||||
'attachment_ids': attachment_ids,
|
||||
'body': message['body'],
|
||||
'model': message['model'],
|
||||
'res_id': message['res_id'],
|
||||
'record_name': message['record_name'],
|
||||
'subject': message['subject'],
|
||||
'date': message['date'],
|
||||
'author_id': author_id,
|
||||
'is_author': is_author,
|
||||
'partner_ids': partner_ids,
|
||||
'parent_id': False,
|
||||
'vote_nb': len(message['vote_user_ids']),
|
||||
'has_voted': has_voted,
|
||||
'is_private': is_private,
|
||||
'is_favorite': is_favorite,
|
||||
'to_read': message['to_read'],
|
||||
}
|
||||
def _message_read_dict(self, cr, uid, message, parent_id=False, context=None):
|
||||
""" Return a dict representation of the message. This representation is
|
||||
used in the JS client code, to display the messages. Partners and
|
||||
attachments related stuff will be done in post-processing in batch.
|
||||
|
||||
def _message_read_add_expandables(self, cr, uid, message_list, read_messages,
|
||||
thread_level=0, message_loaded_ids=[], domain=[], parent_id=False, context=None, limit=None):
|
||||
:param dict message: mail.message browse record
|
||||
"""
|
||||
# private message: no model, no res_id
|
||||
is_private = False
|
||||
if not message.model or not message.res_id:
|
||||
is_private = True
|
||||
# votes and favorites: res.users ids, no prefetching should be done
|
||||
vote_nb = len(message.vote_user_ids)
|
||||
has_voted = uid in [user.id for user in message.vote_user_ids]
|
||||
is_favorite = uid in [user.id for user in message.favorite_user_ids]
|
||||
|
||||
return {'id': message.id,
|
||||
'type': message.type,
|
||||
'body': message.body,
|
||||
'model': message.model,
|
||||
'res_id': message.res_id,
|
||||
'record_name': message.record_name,
|
||||
'subject': message.subject,
|
||||
'date': message.date,
|
||||
'to_read': message.to_read,
|
||||
'parent_id': parent_id,
|
||||
'is_private': is_private,
|
||||
'author_id': False,
|
||||
'is_author': False,
|
||||
'partner_ids': [],
|
||||
'vote_nb': vote_nb,
|
||||
'has_voted': has_voted,
|
||||
'is_favorite': is_favorite,
|
||||
'attachment_ids': [],
|
||||
}
|
||||
|
||||
def _message_read_add_expandables(self, cr, uid, messages, message_tree, parent_tree,
|
||||
message_unload_ids=[], thread_level=0, domain=[], parent_id=False, context=None):
|
||||
""" Create expandables for message_read, to load new messages.
|
||||
1. get the expandable for new threads
|
||||
if display is flat (thread_level == 0):
|
||||
@@ -275,96 +314,82 @@ class mail_message(osv.Model):
|
||||
for each hole in the child list based on message displayed,
|
||||
create an expandable
|
||||
|
||||
:param list message_list:list of message structure for the Chatter
|
||||
:param list messages: list of message structure for the Chatter
|
||||
widget to which expandables are added
|
||||
:param dict read_messages: dict [id]: read result of the messages to
|
||||
easily have access to their values, given their ID
|
||||
:param dict message_tree: dict [id]: browse record of this message
|
||||
:param dict parent_tree: dict [parent_id]: [child_ids]
|
||||
:param list message_unload_ids: list of message_ids we do not want
|
||||
to load
|
||||
:return bool: True
|
||||
"""
|
||||
def _get_expandable(domain, message_nb, parent_id, id, model):
|
||||
def _get_expandable(domain, message_nb, parent_id, max_limit):
|
||||
return {
|
||||
'domain': domain,
|
||||
'nb_messages': message_nb,
|
||||
'type': 'expandable',
|
||||
'parent_id': parent_id,
|
||||
'id': id,
|
||||
# TDE note: why do we need model sometimes, and sometimes not ???
|
||||
'model': model,
|
||||
'max_limit': max_limit,
|
||||
}
|
||||
|
||||
# all_not_loaded_ids = []
|
||||
id_list = sorted(read_messages.keys())
|
||||
if not id_list:
|
||||
return message_list
|
||||
if not messages:
|
||||
return True
|
||||
message_ids = sorted(message_tree.keys())
|
||||
|
||||
# 1. get the expandable for new threads
|
||||
if thread_level == 0:
|
||||
exp_domain = domain + [('id', '<', min(message_loaded_ids + id_list))]
|
||||
exp_domain = domain + [('id', '<', min(message_unload_ids + message_ids))]
|
||||
else:
|
||||
exp_domain = domain + ['!', ('id', 'child_of', message_loaded_ids + id_list)]
|
||||
exp_domain = domain + ['!', ('id', 'child_of', message_unload_ids + parent_tree.keys())]
|
||||
ids = self.search(cr, uid, exp_domain, context=context, limit=1)
|
||||
if ids:
|
||||
message_list.append(_get_expandable(exp_domain, -1, parent_id, -1, None))
|
||||
# inside a thread: prepend
|
||||
if parent_id:
|
||||
messages.insert(0, _get_expandable(exp_domain, -1, parent_id, True))
|
||||
# new threads: append
|
||||
else:
|
||||
messages.append(_get_expandable(exp_domain, -1, parent_id, True))
|
||||
|
||||
# 2. get the expandables for new messages inside threads if display is not flat
|
||||
if thread_level == 0:
|
||||
return True
|
||||
for message_id in id_list:
|
||||
message = read_messages[message_id]
|
||||
for message_id in message_ids:
|
||||
message = message_tree[message_id]
|
||||
|
||||
# message is not a thread header (has a parent_id)
|
||||
# TDE note: parent_id is false is there is a parent we can not see -> ok
|
||||
if message.get('parent_id'):
|
||||
# generate only for thread header messages (TDE note: parent_id may be False is uid cannot see parent_id, seems ok)
|
||||
if message.parent_id:
|
||||
continue
|
||||
|
||||
# TDE note: check search is correctly implemented in mail.message
|
||||
not_loaded_ids = self.search(cr, uid, [
|
||||
('id', 'child_of', message['id']),
|
||||
('id', 'not in', message_loaded_ids),
|
||||
], context=context, limit=self._message_read_more_limit)
|
||||
if not not_loaded_ids:
|
||||
# check there are message for expandable
|
||||
child_ids = set([child.id for child in message.child_ids]) - set(message_unload_ids)
|
||||
child_ids = sorted(list(child_ids), reverse=True)
|
||||
if not child_ids:
|
||||
continue
|
||||
|
||||
# all_not_loaded_ids += not_loaded_ids
|
||||
# group childs not read
|
||||
id_min, id_max, nb = max(not_loaded_ids), 0, 0
|
||||
for not_loaded_id in not_loaded_ids:
|
||||
if not read_messages.get(not_loaded_id):
|
||||
# make groups of unread messages
|
||||
id_min, id_max, nb = max(child_ids), 0, 0
|
||||
for child_id in child_ids:
|
||||
if not child_id in message_ids:
|
||||
nb += 1
|
||||
if id_min > not_loaded_id:
|
||||
id_min = not_loaded_id
|
||||
if id_max < not_loaded_id:
|
||||
id_max = not_loaded_id
|
||||
if id_min > child_id:
|
||||
id_min = child_id
|
||||
if id_max < child_id:
|
||||
id_max = child_id
|
||||
elif nb > 0:
|
||||
exp_domain = [('id', '>=', id_min), ('id', '<=', id_max), ('id', 'child_of', message_id)]
|
||||
message_list.append(_get_expandable(exp_domain, nb, message_id, id_min, message.get('model')))
|
||||
id_min, id_max, nb = max(not_loaded_ids), 0, 0
|
||||
messages.append(_get_expandable(exp_domain, nb, message_id, False))
|
||||
id_min, id_max, nb = max(child_ids), 0, 0
|
||||
else:
|
||||
id_min, id_max, nb = max(not_loaded_ids), 0, 0
|
||||
id_min, id_max, nb = max(child_ids), 0, 0
|
||||
if nb > 0:
|
||||
exp_domain = [('id', '>=', id_min), ('id', '<=', id_max), ('id', 'child_of', message_id)]
|
||||
message_list.append(_get_expandable(exp_domain, nb, message_id, id_min, message.get('model')))
|
||||
|
||||
# message_loaded_ids = list(set(message_loaded_ids + read_messages.keys() + all_not_loaded_ids))
|
||||
idx = [msg.get('id') for msg in messages].index(message_id) + 1
|
||||
# messages.append(_get_expandable(exp_domain, nb, message_id, id_min))
|
||||
messages.insert(idx, _get_expandable(exp_domain, nb, message_id, False))
|
||||
|
||||
return True
|
||||
|
||||
def _get_parent(self, cr, uid, message, context=None):
|
||||
""" Tools method that tries to get the parent of a mail.message. If
|
||||
no parent, or if uid has no access right on the parent, False
|
||||
is returned.
|
||||
|
||||
:param dict message: read result of a mail.message
|
||||
"""
|
||||
if not message['parent_id']:
|
||||
return False
|
||||
parent_id = message['parent_id'][0]
|
||||
try:
|
||||
return self.read(cr, uid, parent_id, self._message_read_fields, context=context)
|
||||
except (orm.except_orm, osv.except_osv):
|
||||
return False
|
||||
|
||||
def message_read(self, cr, uid, ids=None, domain=None, message_unload_ids=None, thread_level=0, context=None, parent_id=False, limit=None):
|
||||
def message_read(self, cr, uid, ids=None, domain=None, message_unload_ids=None,
|
||||
thread_level=0, context=None, parent_id=False, limit=None):
|
||||
""" Read messages from mail.message, and get back a list of structured
|
||||
messages to be displayed as discussion threads. If IDs is set,
|
||||
fetch these records. Otherwise use the domain to fetch messages.
|
||||
@@ -388,46 +413,56 @@ class mail_message(osv.Model):
|
||||
ancestors and expandables
|
||||
:return list: list of message structure for the Chatter widget
|
||||
"""
|
||||
# print 'message_read', ids, domain, message_unload_ids, thread_level, context, parent_id, limit
|
||||
assert thread_level in [0, 1], 'message_read() thread_level should be 0 (flat) or 1 (1 level of thread); given %s.' % thread_level
|
||||
domain = domain if domain is not None else []
|
||||
message_unload_ids = message_unload_ids if message_unload_ids is not None else []
|
||||
if message_unload_ids:
|
||||
domain += [('id', 'not in', message_unload_ids)]
|
||||
limit = limit or self._message_read_limit
|
||||
read_messages = {}
|
||||
message_tree = {}
|
||||
message_list = []
|
||||
parent_tree = {}
|
||||
|
||||
# no specific IDS given: fetch messages according to the domain, add their parents if uid has access to
|
||||
if ids is None:
|
||||
ids = self.search(cr, uid, domain, context=context, limit=limit)
|
||||
for message in self.read(cr, uid, ids, self._message_read_fields, context=context):
|
||||
message_id = message['id']
|
||||
|
||||
# if not in tree and not in message_loaded list
|
||||
if not message_id in read_messages and not message_id in message_unload_ids:
|
||||
read_messages[message_id] = message
|
||||
message_list.append(self._message_get_dict(cr, uid, message, context=context))
|
||||
# fetch parent if threaded, sort messages
|
||||
for message in self.browse(cr, uid, ids, context=context):
|
||||
message_id = message.id
|
||||
if message_id in message_tree:
|
||||
continue
|
||||
message_tree[message_id] = message
|
||||
|
||||
# get the older ancestor the user can read, update its ancestor field
|
||||
if not thread_level:
|
||||
message_list[-1]['parent_id'] = parent_id
|
||||
continue
|
||||
parent = self._get_parent(cr, uid, message, context=context)
|
||||
while parent and parent.get('id') != parent_id:
|
||||
message_list[-1]['parent_id'] = parent.get('id')
|
||||
message = parent
|
||||
parent = self._get_parent(cr, uid, message, context=context)
|
||||
# if in thread: add its ancestor to the list of messages
|
||||
if not message['id'] in read_messages and not message['id'] in message_unload_ids:
|
||||
read_messages[message['id']] = message
|
||||
message_list.append(self._message_get_dict(cr, uid, message, context=context))
|
||||
# find parent_id
|
||||
if thread_level == 0:
|
||||
tree_parent_id = parent_id
|
||||
else:
|
||||
tree_parent_id = message_id
|
||||
parent = message
|
||||
while parent.parent_id and parent.parent_id.id != parent_id:
|
||||
parent = parent.parent_id
|
||||
tree_parent_id = parent.id
|
||||
if not parent.id in message_tree:
|
||||
message_tree[parent.id] = parent
|
||||
# newest messages first
|
||||
parent_tree.setdefault(tree_parent_id, [])
|
||||
if tree_parent_id != message_id:
|
||||
parent_tree[tree_parent_id].append(self._message_read_dict(cr, uid, message_tree[message_id], parent_id=tree_parent_id, context=context))
|
||||
|
||||
if thread_level:
|
||||
for key, message_id_list in parent_tree.iteritems():
|
||||
message_id_list.sort(key=lambda item: item['id'])
|
||||
message_id_list.insert(0, self._message_read_dict(cr, uid, message_tree[key], context=context))
|
||||
|
||||
parent_list = parent_tree.items()
|
||||
parent_list = sorted(parent_list, key=lambda item: max([msg.get('id') for msg in item[1]]) if item[1] else item[0], reverse=True)
|
||||
message_list = [message for (key, msg_list) in parent_list for message in msg_list]
|
||||
|
||||
# get the child expandable messages for the tree
|
||||
message_list = sorted(message_list, key=lambda k: k['id'])
|
||||
self._message_read_add_expandables(cr, uid, message_list, read_messages, thread_level=thread_level,
|
||||
message_loaded_ids=message_unload_ids, domain=domain, parent_id=parent_id, context=context, limit=limit)
|
||||
|
||||
self._message_read_dict_postprocess(cr, uid, message_list, message_tree, context=context)
|
||||
self._message_read_add_expandables(cr, uid, message_list, message_tree, parent_tree,
|
||||
thread_level=thread_level, message_unload_ids=message_unload_ids, domain=domain, parent_id=parent_id, context=context)
|
||||
return message_list
|
||||
|
||||
# TDE Note: do we need this ?
|
||||
@@ -461,7 +496,6 @@ class mail_message(osv.Model):
|
||||
- otherwise: remove the id
|
||||
"""
|
||||
# Rules do not apply to administrator
|
||||
# print '_search', uid, args
|
||||
if uid == SUPERUSER_ID:
|
||||
return super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order,
|
||||
context=context, count=count, access_rights_uid=access_rights_uid)
|
||||
|
||||
@@ -59,21 +59,26 @@
|
||||
<field name="type"/>
|
||||
<field name="author_id"/>
|
||||
<field name="partner_ids"/>
|
||||
<filter string="Read"
|
||||
name="message_read" help="Show messages to read"
|
||||
domain="[('to_read', '=', False)]"/>
|
||||
<filter string="Unread"
|
||||
name="message_unread" help="Show messages to read"
|
||||
domain="[('to_read', '=', True)]"/>
|
||||
<separator/>
|
||||
<filter string="Comments"
|
||||
name="comments" help="Comments"
|
||||
domain="[('type', '=', 'comment')]"/>
|
||||
<filter string="Has attachments"
|
||||
name="attachments"
|
||||
domain="[('attachment_ids', '!=', False)]"/>
|
||||
<filter string="Notifications"
|
||||
name="notifications" help="Notifications"
|
||||
domain="[('type', '=', 'notification')]"/>
|
||||
<filter string="Emails"
|
||||
name="emails" help="Emails"
|
||||
domain="[('type', '=', 'email')]"/>
|
||||
<separator/>
|
||||
<filter string="Has attachments"
|
||||
name="attachments"
|
||||
domain="[('attachment_ids', '!=', False)]"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
@@ -84,7 +89,6 @@
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_message_search"/>
|
||||
<field name="context">{'search_default_to_read_message':True}</field>
|
||||
</record>
|
||||
|
||||
<!-- Add menu entry in Settings/Email -->
|
||||
|
||||
@@ -74,17 +74,17 @@ class mail_thread(osv.AbstractModel):
|
||||
- message_unread: has uid unread message for the document
|
||||
- message_summary: html snippet summarizing the Chatter for kanban views """
|
||||
res = dict((id, dict(message_unread=False, message_summary='')) for id in ids)
|
||||
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
|
||||
# search for unread messages, by reading directly mail.notification, as SUPERUSER
|
||||
notif_obj = self.pool.get('mail.notification')
|
||||
notif_ids = notif_obj.search(cr, SUPERUSER_ID, [
|
||||
('partner_id.user_ids', 'in', [uid]),
|
||||
('message_id.res_id', 'in', ids),
|
||||
('message_id.model', '=', self._name),
|
||||
('read', '=', False)
|
||||
], context=context)
|
||||
for notif in notif_obj.browse(cr, SUPERUSER_ID, notif_ids, context=context):
|
||||
res[notif.message_id.res_id]['message_unread'] = True
|
||||
# search for unread messages, directly in SQL to improve performances
|
||||
cr.execute(""" SELECT m.res_id FROM mail_message m
|
||||
RIGHT JOIN mail_notification n
|
||||
ON (n.message_id = m.id AND n.partner_id = %s AND n.read = False)
|
||||
WHERE m.model = %s AND m.res_id in %s""",
|
||||
(user_pid, self._name, tuple(ids),))
|
||||
msg_ids = [result[0] for result in cr.fetchall()]
|
||||
for msg_id in msg_ids:
|
||||
res[msg_id]['message_unread'] = True
|
||||
|
||||
for thread in self.browse(cr, uid, ids, context=context):
|
||||
cls = res[thread.id]['message_unread'] and ' class="oe_kanban_mail_new"' or ''
|
||||
|
||||
@@ -4,42 +4,123 @@
|
||||
<record id="action_mail_inbox_feeds" model="ir.actions.client">
|
||||
<field name="name">Inbox</field>
|
||||
<field name="tag">mail.wall</field>
|
||||
<field name="params" eval=""{'domain': [('notification_ids.partner_id.user_ids', 'in', [uid]), ('to_read', '=', True)],
|
||||
'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'inbox'} }""/>
|
||||
<field name="res_model">mail.message</field>
|
||||
<field name="context">{
|
||||
'default_model': 'res.users',
|
||||
'default_res_id': uid
|
||||
}</field>
|
||||
<field name="params" eval=""{
|
||||
'domain': [
|
||||
('notification_ids.partner_id.user_ids', 'in', [uid]),
|
||||
('to_read', '=', True),
|
||||
('favorite_user_ids', 'not in', [uid])
|
||||
],
|
||||
'view_mailbox': True,
|
||||
'view_inbox': True,
|
||||
'read_action': 'read'
|
||||
}""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
<b>Hurray! No message here!</b>
|
||||
</p><p>
|
||||
Congratulations! You have processed all your incoming emails.
|
||||
Remember that when you receive new messages, you can either
|
||||
set them as done, or use the star button to send those messages
|
||||
into your <i>Todo</i> mailbox.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_mail_to_me_feeds" model="ir.actions.client">
|
||||
<field name="name">To: me</field>
|
||||
<field name="tag">mail.wall</field>
|
||||
<field name="params" eval=""{'domain': [('partner_ids.user_ids', 'in', [uid]), ('to_read', '=', True), ('author_id.user_ids', 'in', [uid])],
|
||||
'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'inbox'} }""/>
|
||||
<field name="res_model">mail.message</field>
|
||||
<field name="context">{
|
||||
'default_model': 'res.users',
|
||||
'default_res_id': uid,
|
||||
'search_default_message_unread': True
|
||||
}</field>
|
||||
<field name="params" eval=""{
|
||||
'domain': [('partner_ids.user_ids', 'in', [uid])],
|
||||
'view_mailbox': True,
|
||||
'read_action': 'read', }""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
No message here!
|
||||
</p><p>
|
||||
There are no new messages matching the current search
|
||||
that were directly sent to you.
|
||||
Remember you can always uncheck the Read filter to see
|
||||
messages sent to you that you already read.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_mail_star_feeds" model="ir.actions.client">
|
||||
<field name="name">Favorites</field>
|
||||
<field name="name">Todo</field>
|
||||
<field name="tag">mail.wall</field>
|
||||
<field name="params" eval=""{'domain': [('favorite_user_ids.user_ids', 'in', [uid])],
|
||||
'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'stared'} }""/>
|
||||
<field name="res_model">mail.message</field>
|
||||
<field name="context">{
|
||||
'default_model': 'res.users',
|
||||
'default_res_id': uid,
|
||||
'search_default_message_unread': True
|
||||
}</field>
|
||||
<field name="params" eval=""{
|
||||
'domain': [('favorite_user_ids', 'in', [uid])],
|
||||
'view_mailbox': True,
|
||||
'read_action': 'read', }""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
<b>Hurray! No message here!</b>
|
||||
</p><p>
|
||||
Congratulations! You have processed all your messages in
|
||||
your todo list, or at least those matching your search.
|
||||
Remember you can always search for read messages by
|
||||
unchecking the Read filter.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_mail_archives_feeds" model="ir.actions.client">
|
||||
<field name="name">Archives</field>
|
||||
<field name="tag">mail.wall</field>
|
||||
<field name="params" eval=""{'domain': [('notification_ids.partner_id.user_ids', 'in', [uid]), ('to_read', '=', False)],
|
||||
'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'archives'} }""/>
|
||||
<field name="context">{
|
||||
'default_model': 'res.users',
|
||||
'default_res_id': uid,
|
||||
'search_default_message_read': True
|
||||
}</field>
|
||||
<field name="params" eval=""{
|
||||
'domain': [('notification_ids.partner_id.user_ids', 'in', [uid])],
|
||||
'view_mailbox': True,
|
||||
'read_action': 'unread', }""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
There are no message for this search.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_mail_sent_feeds" model="ir.actions.client">
|
||||
<field name="name">Sent</field>
|
||||
<field name="tag">mail.wall</field>
|
||||
<field name="params" eval=""{'domain': [('author_id.user_ids', 'in', [uid])],
|
||||
'context': {'default_model': 'res.users', 'default_res_id': uid, 'typeof_thread': 'send'} }""/>
|
||||
<field name="context">{
|
||||
'default_model': 'res.users',
|
||||
'default_res_id': uid
|
||||
}</field>
|
||||
<field name="params" eval=""{
|
||||
'domain': [('author_id.user_ids', 'in', [uid])],
|
||||
'view_mailbox': True, }""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
There are no message for this search.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- MENU -->
|
||||
|
||||
<!-- Top menu item -->
|
||||
<menuitem name="Emails"
|
||||
<menuitem name="Messages"
|
||||
id="mail.mail_feeds_main"
|
||||
groups="base.group_user"
|
||||
sequence="10"/>
|
||||
@@ -61,7 +142,7 @@
|
||||
<field name="parent_id" ref="mail.mail_feeds"/>
|
||||
</record>
|
||||
<record id="mail_starfeeds" model="ir.ui.menu">
|
||||
<field name="name">Favorites</field>
|
||||
<field name="name">Todo</field>
|
||||
<field name="sequence" eval="14"/>
|
||||
<field name="action" ref="action_mail_star_feeds"/>
|
||||
<field name="parent_id" ref="mail.mail_feeds"/>
|
||||
|
||||
@@ -1,7 +1,36 @@
|
||||
/* ------------ TOPBAR MAIL BUTTON --------------- */
|
||||
|
||||
/* FIXME this css is not very pretty because it uses a
|
||||
* 'button' element wich comes with a lot of inappropriate
|
||||
* styling. Entypo is also a headache to center properly
|
||||
* */
|
||||
|
||||
.openerp .oe_topbar_item.oe_topbar_compose_full_email{
|
||||
padding: 0px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
.openerp .oe_topbar_item.oe_topbar_compose_full_email button{
|
||||
position: relative;
|
||||
top: -3px; /* centering entypo ... urgh */
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
color: white;
|
||||
background: none;
|
||||
text-shadow: 0px 1px 2px black;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0px;
|
||||
margin: 0px
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
/* ------------ MAIL WIDGET --------------- */
|
||||
.openerp .oe_mail, .openerp .oe_mail *{
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.openerp .oe_mail {
|
||||
display: block;
|
||||
@@ -42,9 +71,10 @@
|
||||
}
|
||||
.openerp .oe_mail .oe_msg .oe_msg_footer{
|
||||
padding-left: 4px;
|
||||
padding-top: 3px;
|
||||
overflow: hidden;
|
||||
opacity:0.8;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
margin-bottom: 4px;
|
||||
font-size: 11px;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg .oe_msg_content{
|
||||
display: block;
|
||||
@@ -80,18 +110,24 @@
|
||||
.openerp .oe_mail .oe_msg.oe_msg_indented .oe_msg_content{
|
||||
padding-top:2px;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg.oe_msg_indented .oe_msg_footer{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* b) Votes (likes) */
|
||||
|
||||
.openerp .oe_mail .oe_mail_vote_count{
|
||||
display: inline;
|
||||
position: relative;
|
||||
background: #7C7BAD;
|
||||
color: white;
|
||||
background: white;
|
||||
box-shadow: 0px 0px 0px 1px rgba(124, 123, 173, 0.36) inset;
|
||||
color: #7c7bad;
|
||||
text-shadow: none;
|
||||
border-radius: 3px;
|
||||
margin: 0px;
|
||||
padding-left: 3px;
|
||||
padding-right: 18px;
|
||||
margin-right: 3px;
|
||||
padding-right: 15px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.openerp .oe_mail .oe_mail_vote_count .oe_e{
|
||||
position: absolute;
|
||||
@@ -102,12 +138,6 @@
|
||||
|
||||
/* c) Message action icons */
|
||||
|
||||
.openerp .oe_mail .oe_msg.oe_msg_unread .oe_unread{
|
||||
display:none;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg.oe_msg_read .oe_read{
|
||||
display:none;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg .oe_msg_icons{
|
||||
float: right;
|
||||
margin-top: 4px;
|
||||
@@ -115,6 +145,9 @@
|
||||
margin-left: 8px;
|
||||
height: 24px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg .oe_msg_icons span{
|
||||
float:right;
|
||||
@@ -128,10 +161,16 @@
|
||||
color: #FFF;
|
||||
text-shadow: 0px 1px #AAA,0px -1px #AAA, -1px 0px #AAA, 1px 0px #AAA, 0px 3px 3px rgba(0,0,0,0.1);
|
||||
-webkit-transition: all 0.2s linear;
|
||||
-moz-transition: all 0.2s linear;
|
||||
-o-transition: all 0.2s linear;
|
||||
transition: all 0.2s linear;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg:hover .oe_msg_icons a{
|
||||
opacity: 1;
|
||||
-webkit-transition: all 0.1s linear;
|
||||
-moz-transition: all 0.1s linear;
|
||||
-o-transition: all 0.1s linear;
|
||||
transition: all 0.1s linear;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg .oe_msg_icons .oe_star:hover a{
|
||||
color: #FFF6C0;
|
||||
@@ -155,7 +194,7 @@
|
||||
}
|
||||
.openerp .oe_mail .oe_msg .oe_msg_content textarea{
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
height: 64px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
resize: vertical;
|
||||
@@ -171,6 +210,150 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* --------------------- ATTACHMENTS --------------------- */
|
||||
|
||||
.openerp .oe_mail .oe_msg_attachment_list{
|
||||
display: none;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_composer .oe_msg_attachment_list{
|
||||
display: block;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment{
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
margin: 2px;
|
||||
min-height: 80px;
|
||||
position: relative;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment .oe_name{
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
padding: 1px 3px;
|
||||
margin-top: 50px;
|
||||
margin-bottom: 5px;
|
||||
background: rgba(124, 123, 173, 0.13);
|
||||
overflow: hidden;
|
||||
color: #4c4c4c;
|
||||
text-shadow: none;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_attachment.oe_preview{
|
||||
background: url( data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAJ0lEQVQYV2MsLS39z4AGLCws0IUYGIeCwrVr12J45sSJE5ieGQIKAbuZKf/EMCs7AAAAAElFTkSuQmCC );
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment .oe_progress_bar{
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
left: 16px;
|
||||
right: 16px;
|
||||
height: 17px;
|
||||
line-height: 13px;
|
||||
padding: 0px;
|
||||
background: #4BBD00;
|
||||
color: white;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
border: solid 1px rgba(0,0,0,0.2);
|
||||
box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.34);
|
||||
-webkit-animation: oe_mail_attach_loading_anim 0.75s infinite linear;
|
||||
-moz-animation: oe_mail_attach_loading_anim 0.75s infinite linear;
|
||||
-o-animation: oe_mail_attach_loading_anim 0.75s infinite linear;
|
||||
animation: oe_mail_attach_loading_anim 0.75s infinite linear;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment.oe_uploading .oe_progress_bar{
|
||||
display: block;
|
||||
}
|
||||
@-webkit-keyframes oe_mail_attach_loading_anim{
|
||||
0% { background: #4BBD00 }
|
||||
50% { background: #009123 }
|
||||
100% { background: #4BBD00 }
|
||||
}
|
||||
@-moz-keyframes oe_mail_attach_loading_anim{
|
||||
0% { background: #4BBD00 }
|
||||
50% { background: #009123 }
|
||||
100% { background: #4BBD00 }
|
||||
}
|
||||
@-o-keyframes oe_mail_attach_loading_anim{
|
||||
0% { background: #4BBD00 }
|
||||
50% { background: #009123 }
|
||||
100% { background: #4BBD00 }
|
||||
}
|
||||
@keyframes oe_mail_attach_loading_anim{
|
||||
0% { background: #4BBD00 }
|
||||
50% { background: #009123 }
|
||||
100% { background: #4BBD00 }
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment.oe_preview .oe_name{
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
margin: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
max-height: 64px;
|
||||
background: rgba(0,0,0,0.8);
|
||||
color: white;
|
||||
border-top-left-radius: 0px;
|
||||
border-top-right-radius: 0px;
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment.oe_preview:hover .oe_name{
|
||||
opacity: 1;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment img{
|
||||
position: absolute;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
top: 0px;
|
||||
left: 50%;
|
||||
margin-left: -24px;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment.oe_preview img{
|
||||
display: block;
|
||||
position: relative;
|
||||
margin:0px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 3px;
|
||||
margin-left: -50px;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment .oe_delete{
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_composer .oe_attachment .oe_delete{
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
right: 0px;
|
||||
color: black;
|
||||
text-shadow: 1px 0px white, -1px 0px white, 0px 1px white, 0px -1px white;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_composer .oe_attachment:hover .oe_delete{
|
||||
opacity: 1;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
/* ---------------- MESSAGE QUICK COMPOSER --------------- */
|
||||
|
||||
.openerp .oe_mail .oe_msg_composer .oe_msg_footer{
|
||||
@@ -178,37 +361,6 @@
|
||||
padding-top: 2px;
|
||||
padding-bottom:6px;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_attachments.oe_hidden,
|
||||
.openerp .oe_mail .oe_msg_images.oe_hidden{
|
||||
margin:0px;
|
||||
border: none;
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_attachments{
|
||||
margin-bottom: 4px;
|
||||
margin-right: 0px;
|
||||
font-size: 12px;
|
||||
border-radius: 2px;
|
||||
border: solid 1px rgba(124,123,173,0.14);
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_attachments .oe_attachment{
|
||||
padding: 2px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_attachments .oe_attachment .oe_e{
|
||||
font-size: 23px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_attachments .oe_attachment .oe_e:hover{
|
||||
text-decoration: none;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_attachments .oe_attachment:nth-child(odd){
|
||||
background:white;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_attachments .oe_attachment:nth-child(even){
|
||||
background: #F4F5FA;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_images {
|
||||
display: block;
|
||||
}
|
||||
@@ -269,6 +421,7 @@
|
||||
|
||||
.openerp .oe_mail .oe_msg_content.oe_msg_more_message{
|
||||
text-align: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_content.oe_msg_more_message .oe_separator{
|
||||
height: 0;
|
||||
@@ -280,7 +433,7 @@
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_more_message .oe_msg_fetch_more {
|
||||
background: white;
|
||||
margin-right: 280px;
|
||||
margin-right: 210px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
text-decoration: none;
|
||||
@@ -298,6 +451,7 @@
|
||||
padding-top: 5px;
|
||||
width: 160px;
|
||||
float: right;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
/* a) THE FOLLOW BUTTON */
|
||||
@@ -308,9 +462,22 @@
|
||||
width:100%;
|
||||
}
|
||||
.openerp .oe_followers button.oe_follower.oe_following{
|
||||
color: white;
|
||||
background-color: #3465A4;
|
||||
background-image: -webkit-linear-gradient(top, #729FCF, #3465A4);
|
||||
background-image: -moz-linear-gradient(top, #729FCF, #3465A4);
|
||||
background-image: -ms-linear-gradient(top, #729FCF, #3465A4);
|
||||
background-image: -o-linear-gradient(top, #729FCF, #3465A4);
|
||||
background-image: linear-gradient(to bottom, #729FCF, #3465A4);
|
||||
}
|
||||
.openerp .oe_followers button.oe_follower.oe_following:hover{
|
||||
color: white;
|
||||
background-color: #A21A1A;
|
||||
background-image: -webkit-linear-gradient(top, #DF3F3F, #A21A1A);
|
||||
background-image: -moz-linear-gradient(top, #DF3F3F, #A21A1A);
|
||||
background-image: -ms-linear-gradient(top, #DF3F3F, #A21A1A);
|
||||
background-image: -o-linear-gradient(top, #DF3F3F, #A21A1A);
|
||||
background-image: linear-gradient(to bottom, #DF3F3F, #A21A1A);
|
||||
}
|
||||
|
||||
.openerp .oe_followers button.oe_follower .oe_follow,
|
||||
@@ -371,12 +538,13 @@
|
||||
|
||||
.openerp .oe_record_thread{
|
||||
display: block;
|
||||
margin-right: 180px;
|
||||
margin-left: 16px;
|
||||
margin-right: 212px;
|
||||
}
|
||||
|
||||
/* ----------- INBOX INTEGRATION ----------- */
|
||||
|
||||
.openerp .oe_mail_wall .oe_mail{
|
||||
margin: 16px;
|
||||
width: 720px;
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
@@ -30,6 +30,8 @@ openerp_mail_followers = function(session, mail) {
|
||||
this.ds_model = new session.web.DataSetSearch(this, this.view.model);
|
||||
this.ds_follow = new session.web.DataSetSearch(this, this.field.relation);
|
||||
this.ds_users = new session.web.DataSetSearch(this, 'res.users');
|
||||
|
||||
this.value = [];
|
||||
},
|
||||
|
||||
start: function() {
|
||||
@@ -41,6 +43,11 @@ openerp_mail_followers = function(session, mail) {
|
||||
this._super();
|
||||
},
|
||||
|
||||
set_value: function(_value) {
|
||||
this.value = _value;
|
||||
this._super(_value);
|
||||
},
|
||||
|
||||
_check_visibility: function() {
|
||||
this.$el.toggle(this.view.get("actual_mode") !== "create");
|
||||
},
|
||||
@@ -86,13 +93,14 @@ openerp_mail_followers = function(session, mail) {
|
||||
read_value: function () {
|
||||
var self = this;
|
||||
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).then(function (results) {
|
||||
self.set_value(results[0].message_follower_ids);
|
||||
self.value = results[0].message_follower_ids;
|
||||
self.render_value();
|
||||
});
|
||||
},
|
||||
|
||||
render_value: function () {
|
||||
this.reinit();
|
||||
return this.fetch_followers(this.get("value"));
|
||||
return this.fetch_followers(this.value);
|
||||
},
|
||||
|
||||
fetch_followers: function (value_) {
|
||||
@@ -111,7 +119,7 @@ openerp_mail_followers = function(session, mail) {
|
||||
event.preventDefault();
|
||||
return this.ds_users.call('read', [this.session.uid, ['partner_id']]).then(function (results) {
|
||||
var pid = results['partner_id'][0];
|
||||
self.message_is_follower = (_.indexOf(self.get('value'), pid) != -1);
|
||||
self.message_is_follower = (_.indexOf(self.value, pid) != -1);
|
||||
}).then(self.proxy('display_generic'));
|
||||
},
|
||||
_format_followers: function(count){
|
||||
@@ -131,7 +139,7 @@ openerp_mail_followers = function(session, mail) {
|
||||
display_generic: function () {
|
||||
var self = this;
|
||||
var node_user_list = this.$('.oe_follower_list').empty();
|
||||
this.$('.oe_follower_title').html(this._format_followers(this.get('value').length));
|
||||
this.$('.oe_follower_title').html(this._format_followers(this.value.length));
|
||||
},
|
||||
|
||||
/** Display the followers */
|
||||
@@ -206,7 +214,8 @@ openerp_mail_followers = function(session, mail) {
|
||||
$(record).attr('checked',false);
|
||||
});
|
||||
var context = new session.web.CompoundContext(this.build_context(), {});
|
||||
return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], [this.session.uid], context]).then(this.proxy('read_value'));
|
||||
return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], [this.session.uid], context])
|
||||
.then(this.proxy('read_value'));
|
||||
},
|
||||
|
||||
do_update_subscription: function (event) {
|
||||
@@ -220,7 +229,7 @@ openerp_mail_followers = function(session, mail) {
|
||||
});
|
||||
|
||||
var context = new session.web.CompoundContext(this.build_context(), {});
|
||||
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], this.message_is_follower ? checklist:undefined, context])
|
||||
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], this.message_is_follower ? checklist : undefined, context])
|
||||
.then(this.proxy('read_value'));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<template>
|
||||
|
||||
<!-- this template contains the mail widget and is used to namespace the css -->
|
||||
<t t-name="mail.Widget">
|
||||
<!--
|
||||
mail.Widget template used to namespace the css -->
|
||||
<t t-name="mail.Root">
|
||||
<div class="oe_mail">
|
||||
</div>
|
||||
</t>
|
||||
@@ -38,7 +39,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="widget.show_compact_message and !widget.show_composer" t-attf-class="oe_msg oe_msg_composer_compact #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''}">
|
||||
<textarea class="field_text oe_compact" placeholder="Write a reply..."/>
|
||||
<textarea t-if="!widget.options.view_mailbox" class="field_text oe_compact" placeholder="Write to the followers of this docmuent..."/>
|
||||
<textarea t-if="widget.options.view_mailbox" class="field_text oe_compact" placeholder="Write to my followers..."/>
|
||||
</div>
|
||||
<span t-if="!(widget.show_compact_message and !widget.show_composer) and !widget.show_composer" class="oe_placeholder_compose"></span>
|
||||
</t>
|
||||
@@ -69,33 +71,28 @@
|
||||
Template used to display attachments in a mail.message
|
||||
-->
|
||||
<t t-name="mail.thread.message.attachments">
|
||||
<span class="oe_msg_attachments">
|
||||
<t t-foreach="widget.attachment_ids" t-as="attachment" t-if="!attachment.is_image">
|
||||
<div class="oe_attachment">
|
||||
<span t-if="(attachment.upload and attachment.percent_loaded<100)" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}" t-attf-name="{attachment.name || attachment.filename}">
|
||||
<div class="oe_upload_in_process">
|
||||
<span>...Upload in progress...</span>
|
||||
</div>
|
||||
<t t-raw="attachment.name || attachment.filename"/>
|
||||
</span>
|
||||
<t t-if="(!attachment.upload or attachment.percent_loaded>=100)">
|
||||
<a t-att-href="attachment.url" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}">
|
||||
<t t-raw="attachment.name || attachment.filename"/>
|
||||
</a>
|
||||
</t>
|
||||
<t t-if="(widget.show_delete_attachment and (!attachment.upload or attachment.percent_loaded>=100))">
|
||||
<a class="oe_right oe_mail_attachment_delete oe_e" title="Delete this attachment" t-attf-data-id="{attachment.id}">[</a>
|
||||
</t>
|
||||
<t t-foreach='widget.attachment_ids' t-as='attachment'>
|
||||
<t t-if="attachment.filetype !== 'webimage'">
|
||||
<div t-attf-class="oe_attachment #{attachment.upload ? 'oe_uploading' : ''}">
|
||||
<a t-att-href='attachment.url'><img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img></a>
|
||||
<div class='oe_delete oe_e' title="Delete this attachment" t-attf-data-id="{attachment.id}">[</div>
|
||||
<div class='oe_name'><t t-raw='attachment.name' /></div>
|
||||
<div class='oe_progress_bar'>
|
||||
uploading
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</span>
|
||||
<span class="oe_msg_images">
|
||||
<t t-foreach="widget.attachment_ids" t-as="attachment" t-if="attachment.is_image">
|
||||
<a t-att-href="attachment.url" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}">
|
||||
<img t-if="attachment.is_image" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}" t-att-src="attachment.url"/>
|
||||
</a>
|
||||
<t t-if="attachment.filetype === 'webimage'">
|
||||
<div t-attf-class="oe_attachment oe_preview #{attachment.upload ? 'oe_uploading' : ''}">
|
||||
<a t-att-href='attachment.url'><img t-att-src="widget.attachments_resize_image(attachment.id, [100,100])"></img></a>
|
||||
<div class='oe_delete oe_e'>[</div>
|
||||
<div class='oe_name'><t t-raw='attachment.name' /></div>
|
||||
<div class='oe_progress_bar'>
|
||||
uploading
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</span>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="mail.thread.message.private">
|
||||
@@ -112,7 +109,7 @@
|
||||
<t t-name="mail.thread.list_recipients">
|
||||
<div class="oe_mail_list_recipients">
|
||||
To:
|
||||
<span t-if="!widget.is_private" class="oe_all_follower">Everyone</span>
|
||||
<span t-if="!widget.is_private" class="oe_all_follower">Followers <t t-raw="' of ' + (widget.parent_thread.parent_message.record_name ? '"' + widget.parent_thread.parent_message.record_name + '"' : 'this document')"/></span>
|
||||
<t t-if="!widget.is_private and widget.partner_ids.length"> and </t>
|
||||
<t t-set="inc" t-value="0"/>
|
||||
<t t-if="widget.partner_ids.length" t-foreach="widget.partner_ids" t-as="partner"><span t-attf-class="oe_partner_follower #{inc>=3?'oe_hidden':''}"><t t-if="inc" t-raw="', '"/><a t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-raw="partner[1]"/></a></span><t t-set="inc" t-value="inc+1"/>
|
||||
@@ -140,22 +137,20 @@
|
||||
<td colspan="2">
|
||||
<h2 class="oe_view_title">
|
||||
<span class="oe_view_title_text">
|
||||
News Feed
|
||||
<t t-if="widget.options.res_model"> / </t>
|
||||
<t t-if="widget.options.res_model" t-esc="widget.options.res_model"/>
|
||||
Email box
|
||||
</span>
|
||||
</h2>
|
||||
</td>
|
||||
<td><div class="oe_view_manager_view_search" t-opentag="true"/></td>
|
||||
</tr>
|
||||
<tr class="oe_header_row">
|
||||
<tr class="oe_header_row" t-if="widget.action.params.view_inbox" >
|
||||
<td colspan="2">
|
||||
<button type="button" class="oe_write_full oe_highlight">
|
||||
Compose a new message
|
||||
</button>
|
||||
<span class='oe_alternative'>
|
||||
or
|
||||
<a href='#' class='oe_write_onwall oe_bold' help='Your followers can read this message'>Write to your followers</a>
|
||||
<a href='#' class='oe_write_onwall oe_bold' help='Your followers can read this message'>Write to my followers</a>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -187,7 +182,7 @@
|
||||
|
||||
<!-- default layout -->
|
||||
<t t-name="mail.thread.message">
|
||||
<div t-attf-class="oe_msg #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''} oe_msg_#{widget.type} oe_msg_#{widget.to_read?'unread':'read'}">
|
||||
<div t-attf-class="oe_msg #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''} oe_msg_#{widget.type}">
|
||||
|
||||
<div class='oe_msg_left'>
|
||||
<a t-attf-href="#model=res.partner&id=#{widget.author_id[0]}" t-att-title="widget.author_id[1]">
|
||||
@@ -197,10 +192,11 @@
|
||||
|
||||
<div class="oe_msg_center">
|
||||
<div class='oe_msg_icons'>
|
||||
<span class='oe_read' t-if="widget.show_read_unread_button"><a title="Mark as read" class="oe_e">X</a></span>
|
||||
<span class='oe_unread' t-if="widget.show_read_unread_button"><a title="Mark as unread" class="oe_e">v</a></span>
|
||||
<span class='oe_reply' t-if="widget.show_reply_button"><a title="Reply" class="oe_e">(</a></span>
|
||||
<span t-attf-class="oe_star #{widget.is_favorite?'oe_starred':''}"><a title="Add To Favorites" class="oe_e">7</a></span>
|
||||
<span class='oe_read' t-if="widget.options.show_read"><a title="Done" class="oe_e">X</a></span>
|
||||
<span class='oe_unread' t-if="widget.is_favorite and widget.options.show_unread"><a title="Set back to Todo" class="oe_e">v</a></span>
|
||||
<span class='oe_unread' t-if="!widget.is_favorite and widget.options.show_unread"><a title="Set back to Inbox" class="oe_e">v</a></span>
|
||||
<span class='oe_reply' t-if="widget.options.show_reply_button"><a title="Reply" class="oe_e">(</a></span>
|
||||
<span t-attf-class="oe_star #{widget.is_favorite?'oe_starred':''}"><a title="Mark as Todo" class="oe_e">7</a></span>
|
||||
</div>
|
||||
<!-- message itself -->
|
||||
<div class="oe_msg_content">
|
||||
@@ -208,23 +204,26 @@
|
||||
<t t-raw="widget.subject"/>
|
||||
</h1>
|
||||
<div class="oe_msg_body">
|
||||
<t t-if="widget.options.show_record_name and widget.record_name and (!widget.subject) and !widget.options.thread_level and !widget.options.display_on_thread[0] and widget.model!='res.partner'">
|
||||
<t t-if="widget.show_record_name">
|
||||
<a class="oe_mail_action_model" t-attf-href="#model=#{widget.model}&id=#{widget.res_id}"><t t-raw="widget.record_name"/></a>
|
||||
</t>
|
||||
<t t-raw="widget.body"/>
|
||||
</div>
|
||||
<t t-if="widget.attachment_ids.length > 0">
|
||||
<t t-call="mail.thread.message.attachments"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="oe_msg_footer">
|
||||
<t t-if="widget.attachment_ids.length > 0">
|
||||
<div class="oe_msg_attachment_list"></div>
|
||||
</t>
|
||||
<a t-if="widget.author_id" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a>
|
||||
<span class='oe_subtle'>•</span>
|
||||
<span t-att-title="widget.date"><t t-raw="widget.timerelative"/></span>
|
||||
<a t-if="widget.attachment_ids.length > 0" class="oe_mail_msg_view_attachments">
|
||||
<t t-if='widget.attachment_ids.length > 0'>
|
||||
<span class='oe_subtle'>•</span>
|
||||
<a class="oe_view_attachments">
|
||||
<t t-if="widget.attachment_ids.length == 1">1 Attachment</t>
|
||||
<t t-if="widget.attachment_ids.length > 1"><t t-raw="widget.attachment_ids.length"/> Attachments</t>
|
||||
</a>
|
||||
</t>
|
||||
<span class='oe_subtle'>•</span>
|
||||
<t t-call="mail.thread.message.vote"/>
|
||||
</div>
|
||||
@@ -234,11 +233,12 @@
|
||||
|
||||
<!-- expandable message layout -->
|
||||
<t t-name="mail.thread.expandable">
|
||||
<div t-attf-class="oe_msg oe_msg_#{widget.type} #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''} oe_msg_unread">
|
||||
<div t-attf-class="oe_msg oe_msg_#{widget.type} #{widget.max_limit ? 'oe_max_limit' : ''} #{widget.thread_level and widget.options.display_indented_thread > -1 ? 'oe_msg_indented' : ''}">
|
||||
<div class="oe_msg_content oe_msg_more_message">
|
||||
<div class='oe_separator'></div>
|
||||
<a t-if="widget.nb_messages <= 0" class="oe_msg_fetch_more">show more message</a>
|
||||
<a t-if="widget.nb_messages === 1" class="oe_msg_fetch_more">show one more message</a>
|
||||
<a t-if="widget.nb_messages !== 1" class="oe_msg_fetch_more">show <t t-raw="widget.nb_messages" /> more messages</a>
|
||||
<a t-if="widget.nb_messages > 1" class="oe_msg_fetch_more">show <t t-raw="widget.nb_messages" /> more messages</a>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
@@ -247,9 +247,9 @@
|
||||
mail.compose_message.button_top_bar
|
||||
render of the button on the user bar for open wizard compose message
|
||||
-->
|
||||
<t t-name="mail.compose_message.button_top_bar">
|
||||
<div class="oe_topbar_compose_full_email">
|
||||
<!-- <button class="oe_button oe_highlight">Write an email</button> -->
|
||||
<t t-name="mail.ComposeMessageTopButton">
|
||||
<div title='Compose new Message' class="oe_topbar_item oe_topbar_compose_full_email">
|
||||
<button class="oe_e">%</button>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -257,12 +257,11 @@
|
||||
Template used to display Like/Unlike in a mail.message
|
||||
-->
|
||||
<span t-name="mail.thread.message.vote">
|
||||
|
||||
<span class="oe_mail_vote_count" t-if='widget.vote_nb > 0'>
|
||||
<t t-raw='widget.vote_nb' />
|
||||
<span class='oe_e'>8</span>
|
||||
</span>
|
||||
<a href='#' t-attf-class="oe_msg_vote">
|
||||
<a href='#' class="oe_msg_vote">
|
||||
<t t-if="!widget.has_voted">like</t>
|
||||
<t t-if="widget.has_voted">unlike</t>
|
||||
</a>
|
||||
|
||||
@@ -576,7 +576,7 @@ class test_mail(TestMailMockups):
|
||||
cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs
|
||||
pigs_domain = [('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)]
|
||||
|
||||
# Data: create a discussion in Pigs (2 messages, one with 2 and one with 3 answers)
|
||||
# Data: create a discussion in Pigs (3 threads, with respectively 0, 4 and 4 answers)
|
||||
msg_id0 = self.group_pigs.message_post(body='0', subtype='mt_comment')
|
||||
msg_id1 = self.group_pigs.message_post(body='1', subtype='mt_comment')
|
||||
msg_id2 = self.group_pigs.message_post(body='2', subtype='mt_comment')
|
||||
@@ -588,7 +588,8 @@ class test_mail(TestMailMockups):
|
||||
msg_id8 = self.group_pigs.message_post(body='2-1-1', subtype='mt_comment', parent_id=msg_id4)
|
||||
msg_id9 = self.group_pigs.message_post(body='1-1-1', subtype='mt_comment', parent_id=msg_id3)
|
||||
msg_id10 = self.group_pigs.message_post(body='2-1-1', subtype='mt_comment', parent_id=msg_id4)
|
||||
msg_ids = [msg_id0, msg_id1, msg_id2, msg_id3, msg_id4, msg_id5, msg_id6, msg_id7, msg_id8, msg_id9, msg_id10]
|
||||
msg_ids = [msg_id10, msg_id9, msg_id8, msg_id7, msg_id6, msg_id5, msg_id4, msg_id3, msg_id2, msg_id1, msg_id0]
|
||||
ordered_msg_ids = [msg_id2, msg_id4, msg_id6, msg_id8, msg_id10, msg_id1, msg_id3, msg_id5, msg_id7, msg_id9, msg_id0]
|
||||
|
||||
# Test: read some specific ids
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, ids=msg_ids[2:4], domain=[('body', 'like', 'dummy')])
|
||||
@@ -601,7 +602,8 @@ class test_mail(TestMailMockups):
|
||||
self.assertEqual(msg_ids, read_msg_ids, 'message_read flat with domain on Pigs should equal all messages of Pigs')
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=pigs_domain, limit=200, thread_level=1)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list]
|
||||
self.assertEqual(msg_ids, read_msg_ids, 'message_read threaded with domain on Pigs should equal all messages of Pigs')
|
||||
self.assertEqual(ordered_msg_ids, read_msg_ids,
|
||||
'message_read threaded with domain on Pigs should equal all messages of Pigs, and sort them with newer thread first, last message last in thread')
|
||||
|
||||
# ----------------------------------------
|
||||
# CASE1: message_read with domain, threaded
|
||||
@@ -611,6 +613,8 @@ class test_mail(TestMailMockups):
|
||||
# Do: read last message, threaded
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=pigs_domain, limit=1, thread_level=1)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# TDE TODO: test expandables order
|
||||
type_list = map(lambda item: item.get('type'), read_msg_list)
|
||||
# Test: structure content, ancestor is added to the read messages, ordered by id, ancestor is set, 2 expandables
|
||||
self.assertEqual(len(read_msg_list), 4, 'message_read on last Pigs message should return 2 messages and 2 expandables')
|
||||
self.assertEqual(set([msg_id2, msg_id10]), set(read_msg_ids), 'message_read on the last Pigs message should also get its parent')
|
||||
@@ -618,7 +622,7 @@ class test_mail(TestMailMockups):
|
||||
# Data: get expandables
|
||||
new_threads_exp, new_msg_exp = None, None
|
||||
for msg in read_msg_list:
|
||||
if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('id') == -1:
|
||||
if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('max_limit'):
|
||||
new_threads_exp = msg
|
||||
elif msg.get('type') == 'expandable':
|
||||
new_msg_exp = msg
|
||||
@@ -630,12 +634,20 @@ class test_mail(TestMailMockups):
|
||||
self.assertIn(('id', 'child_of', msg_id2), domain, 'new messages expandable domain should contain a child_of condition')
|
||||
self.assertIn(('id', '>=', msg_id4), domain, 'new messages expandable domain should contain an id greater than condition')
|
||||
self.assertIn(('id', '<=', msg_id8), domain, 'new messages expandable domain should contain an id less than condition')
|
||||
self.assertEqual(new_msg_exp.get('parent_id'), msg_id2, 'new messages expandable should have ancestor_id set to the thread header')
|
||||
# Do: message_read with domain, thread_level=0, parent_id=msg_id2 (should be imposed by JS)
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=200, thread_level=0, parent_id=msg_id2)
|
||||
self.assertEqual(new_msg_exp.get('parent_id'), msg_id2, 'new messages expandable should have parent_id set to the thread header')
|
||||
# Do: message_read with domain, thread_level=0, parent_id=msg_id2 (should be imposed by JS), 2 messages
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=2, thread_level=0, parent_id=msg_id2)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: other message in thread have been fetch
|
||||
self.assertEqual(set([msg_id4, msg_id6, msg_id8]), set(read_msg_ids), 'message_read in Pigs thread should return all the previous messages')
|
||||
new_msg_exp = [msg for msg in read_msg_list if msg.get('type') == 'expandable'][0]
|
||||
# Test: structure content, 2 messages and 1 thread expandable
|
||||
self.assertEqual(len(read_msg_list), 3, 'message_read in Pigs thread should return 2 messages and 1 expandables')
|
||||
self.assertEqual(set([msg_id6, msg_id8]), set(read_msg_ids), 'message_read in Pigs thread should return 2 more previous messages in thread')
|
||||
# Do: read the last message
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=new_msg_exp.get('domain'), limit=2, thread_level=0, parent_id=msg_id2)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: structure content, 1 message
|
||||
self.assertEqual(len(read_msg_list), 1, 'message_read in Pigs thread should return 1 message')
|
||||
self.assertEqual(set([msg_id4]), set(read_msg_ids), 'message_read in Pigs thread should return the last message in thread')
|
||||
|
||||
# Do: fetch a new thread, domain from expandable
|
||||
self.assertIsNotNone(new_threads_exp, 'message_read on last Pigs message should have returned a new threads expandable')
|
||||
@@ -643,7 +655,7 @@ class test_mail(TestMailMockups):
|
||||
# Test: expandable, conditions in domain
|
||||
for condition in pigs_domain:
|
||||
self.assertIn(condition, domain, 'new threads expandable domain should contain the message_read domain parameter')
|
||||
self.assertFalse(new_threads_exp.get('parent_id'), 'new threads expandable should not have an ancestor_id')
|
||||
self.assertFalse(new_threads_exp.get('parent_id'), 'new threads expandable should not have an parent_id')
|
||||
# Do: message_read with domain, thread_level=1 (should be imposed by JS)
|
||||
read_msg_list = self.mail_message.message_read(cr, uid, domain=domain, limit=1, thread_level=1)
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
@@ -654,7 +666,7 @@ class test_mail(TestMailMockups):
|
||||
# Data: get expandables
|
||||
new_threads_exp, new_msg_exp = None, None
|
||||
for msg in read_msg_list:
|
||||
if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('id') == -1:
|
||||
if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('max_limit'):
|
||||
new_threads_exp = msg
|
||||
elif msg.get('type') == 'expandable':
|
||||
new_msg_exp = msg
|
||||
@@ -701,7 +713,7 @@ class test_mail(TestMailMockups):
|
||||
# Data: get expandables
|
||||
new_threads_exp, new_msg_exp = None, None
|
||||
for msg in read_msg_list:
|
||||
if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('id') == -1:
|
||||
if msg.get('type') == 'expandable' and msg.get('nb_messages') == -1 and msg.get('max_limit'):
|
||||
new_threads_exp = msg
|
||||
|
||||
# Do: fetch new messages, domain from expandable
|
||||
@@ -715,7 +727,7 @@ class test_mail(TestMailMockups):
|
||||
read_msg_ids = [msg.get('id') for msg in read_msg_list if msg.get('type') != 'expandable']
|
||||
# Test: structure content, ancestor is added to the read messages, ordered by id, ancestor is set, 2 expandables
|
||||
self.assertEqual(len(read_msg_list), 9, 'message_read on Pigs should return 9 messages and 0 expandable')
|
||||
self.assertEqual([msg_id0, msg_id1, msg_id2, msg_id3, msg_id4, msg_id5, msg_id6, msg_id7, msg_id8], read_msg_ids,
|
||||
self.assertEqual([msg_id8, msg_id7, msg_id6, msg_id5, msg_id4, msg_id3, msg_id2, msg_id1, msg_id0], read_msg_ids,
|
||||
'message_read, More on flat, should return all remaning messages')
|
||||
|
||||
def test_40_needaction(self):
|
||||
|
||||
@@ -135,7 +135,12 @@ class mail_compose_message(osv.TransientModel):
|
||||
related to.
|
||||
:param int res_id: id of the document record this mail is related to
|
||||
"""
|
||||
return {'model': model, 'res_id': res_id}
|
||||
doc_name_get = self.pool.get(model).name_get(cr, uid, res_id, context=context)
|
||||
if doc_name_get:
|
||||
record_name = doc_name_get[0][1]
|
||||
else:
|
||||
record_name = False
|
||||
return {'model': model, 'res_id': res_id, 'record_name': record_name}
|
||||
|
||||
def get_message_data(self, cr, uid, message_id, context=None):
|
||||
""" Returns a defaults-like dict with initial values for the composition
|
||||
@@ -161,6 +166,7 @@ class mail_compose_message(osv.TransientModel):
|
||||
|
||||
# update the result
|
||||
result = {
|
||||
'record_name': message_data.record_name,
|
||||
'model': message_data.model,
|
||||
'res_id': message_data.res_id,
|
||||
'parent_id': message_data.id,
|
||||
|
||||
@@ -14,10 +14,19 @@
|
||||
<field name="parent_id" invisible="1"/>
|
||||
<field name="content_subtype" invisible="1"/>
|
||||
<!-- visible wizard -->
|
||||
<field name="partner_ids" widget="many2many_tags_email" placeholder="Add contacts to notify..."
|
||||
<label for="partner_ids" string="Recipients"/>
|
||||
<div>
|
||||
<span attrs="{'invisible':[('model', '=', False)]}">
|
||||
Followers of
|
||||
<field name="record_name" readonly="1" class="oe_inline"
|
||||
attrs="{'invisible':[('model', '=', False)]}"/>
|
||||
and
|
||||
</span>
|
||||
<field name="partner_ids" widget="many2many_tags_email" placeholder="Add contacts to notify..."
|
||||
context="{'force_email':True}" required="1"/>
|
||||
</div>
|
||||
<field name="subject" placeholder="Subject..."
|
||||
attrs="{'invisible':[('content_subtype', '=', 'plain')]}"/>
|
||||
attrs="{'invisible':[('content_subtype', '=', 'plain')]}"/>
|
||||
</group>
|
||||
<field name="body"/>
|
||||
<field name="attachment_ids" widget="one2many_binary" blockui="0"/>
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
<field name="memo" widget="html" class="oe_memo" editor_height="450px" />
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field class="oe_chatter" name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
||||