[MERGE] trunk
bzr revid: fp@tinyerp.com-20121011142308-vdynmuonffi31yug
This commit is contained in:
commit
cd014978dc
|
@ -21,7 +21,7 @@ class res_users(osv.Model):
|
|||
}
|
||||
|
||||
_sql_constraints = [
|
||||
('uniq_users_oauth_provider_oauht_uid', 'unique(auth_provider_id, auth_uid)', 'OAuth UID must be unique per provider'),
|
||||
('uniq_users_oauth_provider_oauth_uid', 'unique(oauth_provider_id, oauth_uid)', 'OAuth UID must be unique per provider'),
|
||||
]
|
||||
|
||||
def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None):
|
||||
|
|
|
@ -155,30 +155,6 @@ class document_file(osv.osv):
|
|||
res['value'].update({'name': datas_fname})
|
||||
return res
|
||||
|
||||
def _check_duplication(self, cr, uid, vals, ids=[], op='create'):
|
||||
name = vals.get('name', False)
|
||||
parent_id = vals.get('parent_id', False)
|
||||
res_model = vals.get('res_model', False)
|
||||
res_id = vals.get('res_id', 0)
|
||||
if op == 'write':
|
||||
for file in self.browse(cr, uid, ids): # FIXME fields_only
|
||||
if not name:
|
||||
name = file.name
|
||||
if not parent_id:
|
||||
parent_id = file.parent_id and file.parent_id.id or False
|
||||
if not res_model:
|
||||
res_model = file.res_model and file.res_model or False
|
||||
if not res_id:
|
||||
res_id = file.res_id and file.res_id or 0
|
||||
res = self.search(cr, uid, [('id', '<>', file.id), ('name', '=', name), ('parent_id', '=', parent_id), ('res_model', '=', res_model), ('res_id', '=', res_id)])
|
||||
if len(res):
|
||||
return False
|
||||
if op == 'create':
|
||||
res = self.search(cr, uid, [('name', '=', name), ('parent_id', '=', parent_id), ('res_id', '=', res_id), ('res_model', '=', res_model)])
|
||||
if len(res):
|
||||
return False
|
||||
return True
|
||||
|
||||
def check(self, cr, uid, ids, mode, context=None, values=None):
|
||||
"""Check access wrt. res_model, relax the rule of ir.attachment parent
|
||||
|
||||
|
@ -225,8 +201,6 @@ class document_file(osv.osv):
|
|||
res = self.search(cr, uid, [('id', 'in', ids)])
|
||||
if not len(res):
|
||||
return False
|
||||
if not self._check_duplication(cr, uid, vals, ids, 'write'):
|
||||
raise osv.except_osv(_('ValidateError'), _('File name must be unique!'))
|
||||
|
||||
# if nodes call this write(), they must skip the code below
|
||||
from_node = context and context.get('__from_node', False)
|
||||
|
@ -292,22 +266,8 @@ class document_file(osv.osv):
|
|||
else:
|
||||
if vals.get('file_size'):
|
||||
del vals['file_size']
|
||||
result = self._check_duplication(cr, uid, vals)
|
||||
if not result:
|
||||
domain = [
|
||||
('res_id', '=', vals['res_id']),
|
||||
('res_model', '=', vals['res_model']),
|
||||
('datas_fname', '=', vals['datas_fname']),
|
||||
]
|
||||
attach_ids = self.search(cr, uid, domain, context=context)
|
||||
super(document_file, self).write(cr, uid, attach_ids,
|
||||
{'datas' : vals['datas']},
|
||||
context=context)
|
||||
result = attach_ids[0]
|
||||
else:
|
||||
#raise osv.except_osv(_('ValidateError'), _('File name must be unique!'))
|
||||
result = super(document_file, self).create(cr, uid, vals, context)
|
||||
return result
|
||||
|
||||
return super(document_file, self).create(cr, uid, vals, context)
|
||||
|
||||
def __get_partner_id(self, cr, uid, res_model, res_id, context=None):
|
||||
""" A helper to retrieve the associated partner from any res_model+id
|
||||
|
|
|
@ -4,14 +4,8 @@ import textwrap
|
|||
import simplejson
|
||||
import werkzeug.wrappers
|
||||
|
||||
try:
|
||||
# embedded
|
||||
import openerp.addons.web.common.http as openerpweb
|
||||
import openerp.addons.web.controllers.main as webmain
|
||||
except ImportError:
|
||||
# standalone
|
||||
import web.common.http as openerpweb
|
||||
import web.controllers.main as webmain
|
||||
import openerp.addons.web.http as openerpweb
|
||||
import openerp.addons.web.controllers.main as webmain
|
||||
|
||||
class EDI(openerpweb.Controller):
|
||||
# http://hostname:8069/edi/view?db=XXXX&token=XXXXXXXXXXX
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
attrs="{'invisible':[('use_template','=',False)]}"
|
||||
on_change="onchange_template_id(use_template, template_id, composition_mode, model, res_id, context)"/>
|
||||
</xpath>
|
||||
<xpath expr="//button[@class='oe_mail_compose_message_attachment']" position="before">
|
||||
<xpath expr="//button[@name='dummy']" position="before">
|
||||
<button icon="/email_template/static/src/img/email_template.png"
|
||||
type="object" name="toggle_template" string=""
|
||||
help="Use a message template"
|
||||
|
|
|
@ -134,6 +134,7 @@ class mail_message(osv.Model):
|
|||
'subtype_id': fields.many2one('mail.message.subtype', 'Subtype'),
|
||||
'vote_user_ids': fields.many2many('res.users', 'mail_vote', 'message_id', 'user_id', string='Votes',
|
||||
help='Users that voted for this message'),
|
||||
'is_private': fields.boolean('Private message'),
|
||||
}
|
||||
|
||||
def _needaction_domain_get(self, cr, uid, context=None):
|
||||
|
@ -150,6 +151,7 @@ class mail_message(osv.Model):
|
|||
'date': lambda *a: fields.datetime.now(),
|
||||
'author_id': lambda self, cr, uid, ctx={}: self._get_default_author(cr, uid, ctx),
|
||||
'body': '',
|
||||
'is_private': True,
|
||||
}
|
||||
|
||||
#------------------------------------------------------
|
||||
|
@ -220,127 +222,12 @@ class mail_message(osv.Model):
|
|||
'unread': msg.unread and msg.unread['unread'] or False
|
||||
}
|
||||
|
||||
def message_read_tree_get_expandable(self, cr, uid, parent_message, last_message, domain=[], current_level=0, level=0, context=None):
|
||||
""" . """
|
||||
base_domain = [('id', '<', last_message['id'])]
|
||||
if parent_message and current_level < level:
|
||||
base_domain += [('parent_id', '=', parent_message['id'])]
|
||||
elif parent_message:
|
||||
base_domain += [('id', 'child_of', parent_message['id']), ('id', '!=', parent_message['id'])]
|
||||
if domain:
|
||||
base_domain += domain
|
||||
extension = { 'type': 'expandable',
|
||||
'domain': base_domain,
|
||||
'thread_level': current_level,
|
||||
'context': context,
|
||||
'id': -1,
|
||||
}
|
||||
return extension
|
||||
|
||||
def message_read_tree_flatten(self, cr, uid, parent_message, messages, domain=[], level=0, current_level=0, context=None, limit=None, add_expandable=True):
|
||||
""" Given a tree with several roots of following structure :
|
||||
[ {'id': 1, 'child_ids': [
|
||||
{'id': 11, 'child_ids': [...] },],
|
||||
{...} ]
|
||||
Flatten it to have a maximum number of levels, 0 being flat and
|
||||
sort messages in a level according to a key of the messages.
|
||||
Perform the flattening at leafs if above the maximum depth, then get
|
||||
back in the tree.
|
||||
:param context: ``sort_key``: key for sorting (id by default)
|
||||
:param context: ``sort_reverse``: reverser order for sorting (True by default)
|
||||
def _message_read_expandable(self, cr, uid, tree, result, message_loaded, domain, context, parent_id, limit):
|
||||
"""
|
||||
def _flatten(msg_dict):
|
||||
""" from {'id': x, 'child_ids': [{child1}, {child2}]}
|
||||
get [{'id': x, 'child_ids': []}, {child1}, {child2}]
|
||||
"""
|
||||
child_ids = msg_dict.pop('child_ids', [])
|
||||
msg_dict['child_ids'] = []
|
||||
return [msg_dict] + child_ids
|
||||
|
||||
context = context or {}
|
||||
limit = limit or self._message_read_limit
|
||||
|
||||
# Depth-first flattening
|
||||
for message in messages:
|
||||
if message.get('type') == 'expandable':
|
||||
continue
|
||||
message['child_ids'] = self.message_read_tree_flatten(cr, uid, message, message['child_ids'], domain, level, current_level + 1, context=context, limit=limit)
|
||||
for child in message['child_ids']:
|
||||
if child.get('type') == 'expandable':
|
||||
continue
|
||||
message['child_nbr'] += child['child_nbr']
|
||||
# Flatten if above maximum depth
|
||||
if current_level < level:
|
||||
return_list = messages
|
||||
else:
|
||||
return_list = [flat_message for message in messages for flat_message in _flatten(message)]
|
||||
|
||||
# Add expandable
|
||||
return_list = sorted(return_list, key=itemgetter(context.get('sort_key', 'id')), reverse=context.get('sort_reverse', True))
|
||||
if return_list and current_level == 0 and add_expandable:
|
||||
expandable = self.message_read_tree_get_expandable(cr, uid, parent_message, return_list and return_list[-1] or parent_message, domain, current_level, level, context=context)
|
||||
return_list.append(expandable)
|
||||
elif return_list and current_level <= level and add_expandable:
|
||||
expandable = self.message_read_tree_get_expandable(cr, uid, parent_message, return_list and return_list[-1] or parent_message, domain, current_level, level, context=context)
|
||||
return_list.append(expandable)
|
||||
return return_list
|
||||
|
||||
def message_read(self, cr, uid, ids=False, domain=[], level=0, context=None, parent_id=False, limit=None):
|
||||
""" Read messages from mail.message, and get back a structured tree
|
||||
of messages to be displayed as discussion threads. If IDs is set,
|
||||
fetch these records. Otherwise use the domain to fetch messages.
|
||||
After having fetch messages, their parents will be added to obtain
|
||||
well formed threads.
|
||||
|
||||
:param domain: optional domain for searching ids
|
||||
:param level: level of threads to display, 0 being flat
|
||||
:param limit: number of messages to fetch
|
||||
:param parent_id: if parent_id reached, stop searching for
|
||||
further parents
|
||||
:return list: list of trees of messages
|
||||
create the expandable message for all parent message read
|
||||
this function is used by message_read
|
||||
"""
|
||||
|
||||
message_loaded = context and context.get('message_loaded') or [0]
|
||||
|
||||
# don't read the message display by .js, in context message_loaded list
|
||||
if context and context.get('message_loaded'):
|
||||
domain += [ ['id','not in',message_loaded] ];
|
||||
|
||||
limit = limit or self._message_read_limit
|
||||
context = context or {}
|
||||
|
||||
tree = []
|
||||
result = []
|
||||
record = None
|
||||
|
||||
# select ids
|
||||
if ids:
|
||||
for msg in self.browse(cr, uid, ids, context=context):
|
||||
result.append(self._message_dict_get(cr, uid, msg, context=context))
|
||||
return result
|
||||
|
||||
# key: ID, value: record
|
||||
ids = self.search(cr, SUPERUSER_ID, domain, context=context, limit=limit)
|
||||
for msg in self.browse(cr, uid, ids, context=context):
|
||||
# if not in record and not in message_loded list
|
||||
if msg.id not in tree and msg.id not in message_loaded :
|
||||
record = self._message_dict_get(cr, uid, msg, context=context)
|
||||
tree.append(msg.id)
|
||||
result.append(record)
|
||||
|
||||
while msg.parent_id and msg.parent_id.id != parent_id:
|
||||
parent_id = msg.parent_id.id
|
||||
if msg.parent_id.id not in tree:
|
||||
msg = msg.parent_id
|
||||
tree.append(msg.id)
|
||||
# if not in record and not in message_loded list
|
||||
if msg.id not in message_loaded :
|
||||
record = self._message_dict_get(cr, uid, msg, context=context)
|
||||
result.append(record)
|
||||
|
||||
result = sorted(result, key=lambda k: k['id'])
|
||||
|
||||
|
||||
tree_not = []
|
||||
# expandable for not show message
|
||||
for id_msg in tree:
|
||||
|
@ -367,10 +254,12 @@ class mail_message(osv.Model):
|
|||
'parent_id': id_msg,
|
||||
'id': id_min
|
||||
})
|
||||
id_min=None
|
||||
id_max=None
|
||||
nb=0
|
||||
if nb>0:
|
||||
result.append({
|
||||
'domain': [['id','>=',id_min],['parent_id','=',id_msg]],
|
||||
'domain': [['id','>=',id_min],['id','<=',id_max],['parent_id','=',id_msg]],
|
||||
'nb_messages': nb,
|
||||
'type': 'expandable',
|
||||
'parent_id': id_msg,
|
||||
|
@ -395,6 +284,73 @@ class mail_message(osv.Model):
|
|||
|
||||
return result
|
||||
|
||||
def message_read(self, cr, uid, ids=False, domain=[], level=0, context=None, parent_id=False, limit=None):
|
||||
""" Read messages from mail.message, and get back a structured tree
|
||||
of messages to be displayed as discussion threads. If IDs is set,
|
||||
fetch these records. Otherwise use the domain to fetch messages.
|
||||
After having fetch messages, their parents will be added to obtain
|
||||
well formed threads.
|
||||
|
||||
:param domain: optional domain for searching ids
|
||||
:param limit: number of messages to fetch
|
||||
:param parent_id: if parent_id reached, stop searching for
|
||||
further parents
|
||||
:return list: list of trees of messages
|
||||
"""
|
||||
message_loaded = context and context.get('message_loaded') or [0]
|
||||
|
||||
# don't read the message display by .js, in context message_loaded list
|
||||
if context and context.get('message_loaded'):
|
||||
domain += [ ['id','not in',message_loaded] ];
|
||||
|
||||
limit = limit or self._message_read_limit
|
||||
context = context or {}
|
||||
|
||||
tree = []
|
||||
result = []
|
||||
record = None
|
||||
|
||||
# select ids
|
||||
if ids and ids!=[None]:
|
||||
for msg in self.browse(cr, uid, ids, context=context):
|
||||
result.append(self._message_dict_get(cr, uid, msg, context=context))
|
||||
return result
|
||||
|
||||
# key: ID, value: record
|
||||
ids = self.search(cr, SUPERUSER_ID, domain, context=context, limit=limit)
|
||||
for msg in self.browse(cr, uid, ids, context=context):
|
||||
# if not in record and not in message_loded list
|
||||
if msg.id not in tree and msg.id not in message_loaded :
|
||||
record = self._message_dict_get(cr, uid, msg, context=context)
|
||||
tree.append(msg.id)
|
||||
result.append(record)
|
||||
|
||||
while msg.parent_id and msg.parent_id.id != parent_id:
|
||||
parent_id = msg.parent_id.id
|
||||
if msg.parent_id.id not in tree:
|
||||
msg = msg.parent_id
|
||||
tree.append(msg.id)
|
||||
# if not in record and not in message_loded list
|
||||
if msg.id not in message_loaded :
|
||||
record = self._message_dict_get(cr, uid, msg, context=context)
|
||||
result.append(record)
|
||||
|
||||
result = sorted(result, key=lambda k: k['id'])
|
||||
|
||||
result = self._message_read_expandable(cr, uid, tree, result, message_loaded, domain, context, parent_id, limit)
|
||||
|
||||
return result
|
||||
|
||||
def user_free_attachment(self, cr, uid, context=None):
|
||||
attachment_list = []
|
||||
|
||||
attachment = self.pool.get('ir.attachment')
|
||||
attachment_ids = attachment.search(cr, uid, [('res_model','=',''),('create_uid','=',uid)])
|
||||
if len(attachment_ids):
|
||||
attachment_list = [{'id': attach.id, 'name': attach.name, 'date': attach.create_date} for attach in attachment.browse(cr, uid, attachment_ids, context=context)]
|
||||
|
||||
return attachment_list
|
||||
|
||||
#------------------------------------------------------
|
||||
# Email api
|
||||
#------------------------------------------------------
|
||||
|
@ -525,11 +481,9 @@ class mail_message(osv.Model):
|
|||
self.pool.get('ir.attachment').unlink(cr, uid, attachments_to_delete, context=context)
|
||||
return super(mail_message, self).unlink(cr, uid, ids, context=context)
|
||||
|
||||
def _notify(self, cr, uid, newid, context=None):
|
||||
def _notify_followers(self, cr, uid, newid, message, context=None):
|
||||
""" Add the related record followers to the destination partner_ids.
|
||||
Call mail_notification.notify to manage the email sending
|
||||
"""
|
||||
message = self.browse(cr, uid, newid, context=context)
|
||||
partners_to_notify = set([])
|
||||
# message has no subtype_id: pure log message -> no partners, no one notified
|
||||
if not message.subtype_id:
|
||||
|
@ -550,6 +504,14 @@ class mail_message(osv.Model):
|
|||
self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(4, p_id) for p_id in missing_notified]}, context=context)
|
||||
partners_to_notify |= extra_notified
|
||||
|
||||
def _notify(self, cr, uid, newid, context=None):
|
||||
""" Add the related record followers to the destination partner_ids if is not a private message.
|
||||
Call mail_notification.notify to manage the email sending
|
||||
"""
|
||||
message = self.browse(cr, uid, newid, context=context)
|
||||
if message and (message.is_private!=False and message.is_private!=None):
|
||||
self._notify_followers(cr, uid, newid, message, context=context)
|
||||
|
||||
# add myself if I wrote on my wall,
|
||||
# unless remove myself author
|
||||
if ((message.model=="res.partner" and message.res_id==message.author_id.id)):
|
||||
|
|
|
@ -88,21 +88,21 @@
|
|||
<field name="name">Inbox</field>
|
||||
<field name="tag">mail.wall</field>
|
||||
<field name="params" eval=""{'domain': [('notification_ids.partner_id.user_ids', 'in', [uid]),('unread', '=', True)],
|
||||
'context': {'default_model': 'res.users', 'default_res_id': uid} }""/>
|
||||
'context': {'default_model': 'res.partner'} }""/>
|
||||
</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]),('unread', '=', False)],
|
||||
'context': {'default_model': 'res.users', 'default_res_id': uid} }""/>
|
||||
'context': {'default_model': 'res.partner'} }""/>
|
||||
</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} }""/>
|
||||
'context': {'default_model': 'res.partner'} }""/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -623,11 +623,10 @@ class mail_thread(osv.AbstractModel):
|
|||
:param str subject: optional subject
|
||||
:param str type: mail_message.type
|
||||
:param int parent_id: optional ID of parent message in this thread
|
||||
:param tuple(str,str) attachments: list of attachment tuples in the form
|
||||
:param tuple(str,str) attachments or list id: list of attachment tuples in the form
|
||||
``(name,content)``, where content is NOT base64 encoded
|
||||
:return: ID of newly created mail.message
|
||||
"""
|
||||
|
||||
context = context or {}
|
||||
attachments = attachments or []
|
||||
assert (not thread_id) or isinstance(thread_id, (int, long)) or \
|
||||
|
@ -635,7 +634,7 @@ class mail_thread(osv.AbstractModel):
|
|||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id and thread_id[0]
|
||||
|
||||
attachment_ids = []
|
||||
attachment_ids=[]
|
||||
for name, content in attachments:
|
||||
if isinstance(content, unicode):
|
||||
content = content.encode('utf-8')
|
||||
|
@ -679,6 +678,13 @@ class mail_thread(osv.AbstractModel):
|
|||
'attachment_ids': attachment_ids,
|
||||
'subtype_id': subtype_id,
|
||||
})
|
||||
|
||||
# if the parent is private, the message must be private
|
||||
if parent_id:
|
||||
msg = messages.browse(cr, uid, parent_id, context=context)
|
||||
if msg.is_private:
|
||||
values["is_private"] = msg.is_private
|
||||
|
||||
# Avoid warnings about non-existing fields
|
||||
for x in ('from', 'to', 'cc'):
|
||||
values.pop(x, None)
|
||||
|
@ -691,10 +697,23 @@ class mail_thread(osv.AbstractModel):
|
|||
|
||||
def message_post_api(self, cr, uid, thread_id, body='', subject=False, type='notification',
|
||||
subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
|
||||
added_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type=type,
|
||||
subtype=subtype, parent_id=parent_id, attachments=attachments, context=context)
|
||||
added_message = self.pool.get('mail.message').message_read(cr, uid, [added_message_id])
|
||||
# if the user write on his wall
|
||||
if self._name=='res.partner' and not thread_id:
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
thread_id = user.partner_id.id
|
||||
|
||||
added_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type=type,
|
||||
subtype=subtype, parent_id=parent_id, context=context)
|
||||
|
||||
attachment_ids=[]
|
||||
if attachments:
|
||||
ir_attachment = self.pool.get('ir.attachment')
|
||||
attachment_ids = ir_attachment.search(cr, 1, [('res_model', '=', ""), ('res_id', '=', ""), ('user_id', '=', uid), ('id', 'in', attachments)], context=context)
|
||||
if attachment_ids:
|
||||
self.pool.get('ir.attachment').write(cr, 1, attachment_ids, { 'res_model': self._name, 'res_id': thread_id }, context=context)
|
||||
self.pool.get('mail.message').write(cr, 1, [added_message_id], {'attachment_ids': [(6, 0, [pid for pid in attachment_ids])]} )
|
||||
|
||||
added_message = self.pool.get('mail.message').message_read(cr, uid, [added_message_id])
|
||||
return added_message
|
||||
|
||||
def get_message_subtypes(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -20,13 +20,13 @@
|
|||
</record>
|
||||
<record id="mail_archivesfeeds" model="ir.ui.menu">
|
||||
<field name="name">Archives</field>
|
||||
<field name="sequence" eval="11"/>
|
||||
<field name="sequence" eval="12"/>
|
||||
<field name="action" ref="action_mail_archives_feeds"/>
|
||||
<field name="parent_id" ref="mail_feeds"/>
|
||||
</record>
|
||||
<record id="mail_sentfeeds" model="ir.ui.menu">
|
||||
<field name="name">Sent</field>
|
||||
<field name="sequence" eval="12"/>
|
||||
<field name="sequence" eval="13"/>
|
||||
<field name="action" ref="action_mail_sent_feeds"/>
|
||||
<field name="parent_id" ref="mail_feeds"/>
|
||||
</record>
|
||||
|
|
|
@ -82,9 +82,13 @@
|
|||
overflow: auto;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_record_wall {
|
||||
margin: auto;
|
||||
width: 560px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_record_wall > .oe_mail_wall_threads {
|
||||
float: left;
|
||||
width: 560px;
|
||||
}
|
||||
|
||||
.openerp div.oe_mail_recthread_aside {
|
||||
|
@ -145,6 +149,10 @@
|
|||
z-index: 5;
|
||||
}
|
||||
.openerp .oe_mouse_subtypes .oe_recthread_subtypes {
|
||||
background: #fff;
|
||||
padding: 2px;
|
||||
border: 1px solid #aaaaaa;
|
||||
border-top: 0px;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
@ -160,7 +168,6 @@
|
|||
/* ------------------------------------------------------------ */
|
||||
|
||||
.openerp div.oe_mail_thread_action {
|
||||
display: none;
|
||||
white-space: normal;
|
||||
padding: 8px;
|
||||
z-index:5;
|
||||
|
@ -173,16 +180,6 @@
|
|||
clear: both;
|
||||
}
|
||||
|
||||
/* default textarea (oe_mail_compose_textarea), and body textarea for compose form view */
|
||||
.openerp .oe_mail_msg_content textarea.oe_mail_compose_textarea,
|
||||
.openerp .oe_mail_msg_content div.oe_mail_compose_message_body textarea {
|
||||
width: 474px;
|
||||
height: 60px;
|
||||
padding: 4px;
|
||||
font-size: 12px;
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
/* default textarea (oe_mail_compose_textarea), and body textarea for compose form view */
|
||||
.openerp .oe_mail_msg_content textarea.oe_mail_compose_textarea:focus,
|
||||
.openerp .oe_mail_msg_content div.oe_mail_compose_message_body textarea:focus {
|
||||
|
@ -206,6 +203,10 @@
|
|||
margin-left: 66px;
|
||||
}
|
||||
|
||||
.openerp li.oe_mail_thread_msg {
|
||||
width: 560px;
|
||||
}
|
||||
|
||||
.openerp div.oe_thread_placeholder li.oe_mail_thread_msg:last-child {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
@ -223,13 +224,18 @@
|
|||
|
||||
.openerp li.oe_mail_thread_msg.oe_mail_read,
|
||||
.openerp li.oe_mail_thread_msg.oe_mail_read div {
|
||||
background-color: #F0F0F0;
|
||||
border-left: #F0F0F0;
|
||||
}
|
||||
.openerp li.oe_mail_thread_msg.oe_mail_read li.oe_mail_thread_msg.oe_mail_unread,
|
||||
.openerp li.oe_mail_thread_msg.oe_mail_read li.oe_mail_thread_msg.oe_mail_unread div {
|
||||
background-color: #F6F6F6;
|
||||
}
|
||||
|
||||
.openerp li.oe_mail_thread_msg.oe_mail_unread>div>ul>li.oe_unread,
|
||||
.openerp li.oe_mail_thread_msg.oe_mail_read>div>ul>li.oe_read {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.openerp li.oe_mail_thread_msg > div:after {
|
||||
content: "";
|
||||
display: block;
|
||||
|
@ -247,7 +253,7 @@
|
|||
.openerp .oe_mail_msg_email {
|
||||
padding: 8px;
|
||||
background: white;
|
||||
border-top: 1px solid #ebebeb;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_notification:after,
|
||||
|
@ -259,7 +265,7 @@
|
|||
}
|
||||
|
||||
.openerp div.oe_mail_msg_content {
|
||||
float: right;
|
||||
float: left;
|
||||
position: relative;
|
||||
width: 486px;
|
||||
}
|
||||
|
@ -309,76 +315,6 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* mail.compose.message form view & OpenERP hacks
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* form_view: delete white background */
|
||||
.openerp .oe_mail_msg_content div.oe_formview {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content div.oe_form_nosheet {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content table.oe_form_group {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content table.oe_form_field,
|
||||
.openerp .oe_mail_msg_content div.oe_form_field {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content td.oe_form_group_cell {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
/* subject: change width */
|
||||
.openerp .oe_mail_msg_content .oe_form .oe_form_field input {
|
||||
width: 472px;
|
||||
}
|
||||
|
||||
/* body_html: cleditor */
|
||||
.openerp .oe_mail_msg_content div.cleditorMain {
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
/* destination_partner_ids */
|
||||
.openerp .oe_mail_msg_content div.text-core {
|
||||
height: 22px !important;
|
||||
width: 472px;
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
.openerp .oe_mail_msg_content .oe_mail_compose_message_icons button.oe_form_button {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
/* attachment button: override of openerp values */
|
||||
.openerp .oe_mail_msg_content .oe_mail_compose_message_icons div.oe_hidden_input_file {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 2px;
|
||||
}
|
||||
.openerp .oe_mail_msg_content .oe_mail_compose_message_icons div.oe_hidden_input_file button {
|
||||
margin: 0px;
|
||||
}
|
||||
.openerp .oe_mail_msg_content .oe_mail_compose_message_icons input.oe_form_binary_file {
|
||||
bottom: 0px;
|
||||
top: auto;
|
||||
left: auto;
|
||||
right: 28px;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
min-width: 22px;
|
||||
font-size: 0px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* Messages layout
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -413,39 +349,27 @@
|
|||
}
|
||||
|
||||
/* Dropdown menu */
|
||||
/*.openerp .oe_mail_msg_content .oe_dropdown_toggle {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 3px;
|
||||
}*/
|
||||
|
||||
.openerp .oe_mail .oe_semantic_html_override {
|
||||
.openerp .oe_mail ul.oe_mail_thread_display ul.oe_mail_thread_display {
|
||||
position: relative;
|
||||
border-left: 1px #DDD dashed;
|
||||
}
|
||||
|
||||
.openerp .oe_mail ul.oe_header {
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
top: -6px;
|
||||
display: none;
|
||||
z-index: 10;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail ul.oe_header a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_semantic_html_override:hover > ul.oe_header {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.openerp .oe_mail ul.oe_header>li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content .oe_dropdown_arrow:after {
|
||||
border-top: 4px solid #404040;
|
||||
height: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Message footer */
|
||||
|
@ -465,16 +389,36 @@
|
|||
|
||||
/* Attachments list */
|
||||
.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments {
|
||||
display: none;
|
||||
width: 100%;
|
||||
border-top: 1px solid #CCC;
|
||||
margin: .5em 0 0 0;
|
||||
padding: .5em 0;
|
||||
list-style-position: inside;
|
||||
}
|
||||
.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments.oe_hidden {
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments li {
|
||||
float: none;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: square;
|
||||
}
|
||||
.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments .oe_upload_in_process {
|
||||
float: right;
|
||||
width: 200px;
|
||||
height: 16px;
|
||||
}
|
||||
.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments .oe_upload_in_process div {
|
||||
float: left;
|
||||
width: 38px;
|
||||
height: 16px;
|
||||
margin-right: 2px;
|
||||
background: #66FF66;
|
||||
}
|
||||
.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments .oe_upload_in_process span {
|
||||
color: #aaaaaa;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,166 @@
|
|||
/* ------------------------------ */
|
||||
/* Compose Message Wizard Form */
|
||||
/* Compose Message */
|
||||
/* ------------------------------ */
|
||||
|
||||
.openerp .oe_mail_compose_message_icons {
|
||||
text-align: right;
|
||||
.openerp .oe_mail_msg_content .oe_mail_compose_message_footer {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_compose_message_icons img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
.openerp .oe_mail_msg_content .oe_mail_compose_message_footer button.oe_mail_compose_message_button_send {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_mail_compose_textarea
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_mail_compose_textarea .oe_mail_post_header,
|
||||
.openerp .oe_mail .oe_mail_compose_textarea .oe_mail_post_footer,
|
||||
{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_mail_compose_textarea a.oe_cancel {
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
top: -8px;
|
||||
}
|
||||
.openerp .oe_mail .oe_mail_compose_textarea a.oe_cancel:first-of-type {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_mail_compose_textarea button.oe_full {
|
||||
float: right;
|
||||
position: relative;
|
||||
right: -10px;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* mail.compose.message : list_recipients
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
.openerp .oe_mail .oe_mail_list_recipients {
|
||||
display: inline;
|
||||
}
|
||||
.openerp .oe_mail .oe_mail_list_recipients .oe_all_follower {
|
||||
color: blue;
|
||||
}
|
||||
.openerp .oe_mail .oe_mail_list_recipients .oe_partner_follower a {
|
||||
color: red;
|
||||
}
|
||||
.openerp .oe_mail .oe_mail_list_recipients .oe_hidden,
|
||||
.openerp .oe_mail .oe_mail_list_recipients .oe_more_hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* mail.compose.message : attachment
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
.openerp .oe_mail .oe_attachment_file {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_attachment_file .oe_add {
|
||||
float: left;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
left: +2px;
|
||||
top: +7px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* attachment button: override of openerp values */
|
||||
.openerp .oe_mail .oe_attachment_file .oe_add button,
|
||||
.openerp .oe_mail .oe_attachment_file .oe_add input.oe_insert_file {
|
||||
position: absolute;
|
||||
bottom: +0px;
|
||||
left: +0px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment_file .oe_add input.oe_insert_file {
|
||||
z-index:2;
|
||||
width: 300px;
|
||||
left: -100px;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: transparent;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment_file .oe_add button span {
|
||||
position: relative;
|
||||
bottom: +4px;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_mail_msg_attachments input {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_mail_compose_attachment_list {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* mail.compose.message
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* default textarea (oe_mail_compose_textarea), and body textarea for compose form view */
|
||||
.openerp .oe_mail.oe_semantic_html_override .oe_mail_compose_textarea textarea.field_text,
|
||||
.openerp .oe_mail div.oe_mail_compose_message_body textarea.field_text {
|
||||
width: 100%;
|
||||
min-height: 120px;
|
||||
height: auto;
|
||||
padding: 4px;
|
||||
font-size: 12px;
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
/* not top textarea */
|
||||
.openerp .oe_mail.oe_semantic_html_override .oe_semantic_html_override .oe_mail_compose_textarea textarea.field_text {
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
/* form_view: delete white background */
|
||||
.openerp .oe_mail_msg_content div.oe_formview {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content div.oe_form_nosheet {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content table.oe_form_group {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content table.oe_form_field,
|
||||
.openerp .oe_mail_msg_content div.oe_form_field {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content td.oe_form_group_cell {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
/* subject: change width */
|
||||
.openerp .oe_mail_msg_content .oe_form .oe_form_field input[type='text'] {
|
||||
width: 472px;
|
||||
}
|
||||
|
||||
/* body_html: cleditor */
|
||||
.openerp .oe_mail_msg_content div.cleditorMain {
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
/* destination_partner_ids */
|
||||
.openerp .oe_mail_msg_content div.text-core {
|
||||
height: 22px !important;
|
||||
width: 472px;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -40,6 +40,7 @@ openerp_mail_followers = function(session, mail) {
|
|||
this._check_visibility();
|
||||
this.reinit();
|
||||
this.bind_events();
|
||||
this.display_subtypes();
|
||||
},
|
||||
|
||||
_check_visibility: function() {
|
||||
|
@ -53,31 +54,15 @@ openerp_mail_followers = function(session, mail) {
|
|||
|
||||
bind_events: function() {
|
||||
var self = this;
|
||||
this.$('div.oe_mouse_subtypes')
|
||||
.on('mouseover', function () {
|
||||
$(this).removeClass('oe_mouseout').addClass('oe_mouseover');
|
||||
self.display_subtypes();
|
||||
})
|
||||
.on('mouseleave', function () {
|
||||
$(this).removeClass('oe_mouseover').addClass('oe_mouseout');
|
||||
self.display_subtypes();
|
||||
});
|
||||
|
||||
this.$('button.oe_follower')
|
||||
.on('click', function () {
|
||||
if($(this).hasClass('oe_notfollow'))
|
||||
self.do_follow();
|
||||
else
|
||||
self.do_unfollow();
|
||||
})
|
||||
.on('mouseover', function () {
|
||||
$(this).removeClass('oe_mouseout').addClass('oe_mouseover');
|
||||
})
|
||||
.on('mouseleave', function () {
|
||||
$(this).removeClass('oe_mouseover').addClass('oe_mouseout');
|
||||
});
|
||||
|
||||
this.$el.on('click', 'ul.oe_subtypes input', function () { self.do_update_subscription(); })
|
||||
this.$el.on('click', 'ul.oe_subtypes input', self.do_update_subscription );
|
||||
|
||||
this.$el.on('click', 'button.oe_invite', function(event) {
|
||||
action = {
|
||||
|
@ -173,7 +158,8 @@ openerp_mail_followers = function(session, mail) {
|
|||
|
||||
set_subtypes:function(data){
|
||||
var self = this;
|
||||
var records = data[this.view.datarecord.id].message_subtype_data;
|
||||
var records = (data[this.view.datarecord.id] || data[null]).message_subtype_data;
|
||||
|
||||
_(records).each(function (record, record_name) {
|
||||
record.name = record_name;
|
||||
record.followed = record.followed || undefined;
|
||||
|
@ -194,16 +180,10 @@ openerp_mail_followers = function(session, mail) {
|
|||
},
|
||||
|
||||
do_follow: function () {
|
||||
var self =this;
|
||||
_(this.$('.oe_msg_subtype_check')).each(function(record){
|
||||
$(record).attr('checked','checked');
|
||||
});
|
||||
var context = new session.web.CompoundContext(this.build_context(), {});
|
||||
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], undefined, undefined, context]).pipe(function(value_){
|
||||
self.read_value(value_);
|
||||
if(!self.$('.oe_recthread_subtypes').is(":visible"))
|
||||
self.display_subtypes(true);
|
||||
});
|
||||
this.do_update_subscription();
|
||||
},
|
||||
|
||||
do_unfollow: function () {
|
||||
|
@ -211,23 +191,28 @@ 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], undefined, context]).pipe(this.proxy('read_value'));
|
||||
return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], [this.session.uid], context]).pipe(this.proxy('read_value'));
|
||||
},
|
||||
|
||||
do_update_subscription: function () {
|
||||
var context = new session.web.CompoundContext(this.build_context(), {});
|
||||
do_update_subscription: function (event) {
|
||||
var self = this;
|
||||
|
||||
var checklist = new Array();
|
||||
_(this.$('.oe_msg_subtype_check')).each(function(record){
|
||||
_(this.$('.oe_mail_recthread_actions input[type="checkbox"]')).each(function(record){
|
||||
if($(record).is(':checked')) {
|
||||
checklist.push(parseInt($(record).data('id')))}
|
||||
});
|
||||
|
||||
if(!checklist.length)
|
||||
return this.do_unfollow();
|
||||
else
|
||||
return this.ds_model.call('message_subscribe_users',[[self.view.datarecord.id], undefined, checklist, context]).pipe(this.proxy('read_value'));
|
||||
else{
|
||||
var context = new session.web.CompoundContext(this.build_context(), {});
|
||||
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], undefined, context]).pipe(function(value_){
|
||||
self.read_value(value_);
|
||||
self.display_subtypes(true);
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
});
|
||||
|
|
|
@ -1,11 +1,118 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<template>
|
||||
|
||||
<!--
|
||||
mail.compose_message template
|
||||
This template holds the composition form to write a note or send
|
||||
an e-mail. It contains by default a textarea, that will be replaced
|
||||
by another composition form in the main wall composition form, or
|
||||
for main thread composition form in document form view.
|
||||
-->
|
||||
<t t-name="mail.compose_message">
|
||||
<div class="oe_mail_compose_textarea">
|
||||
<img class="oe_mail_icon oe_mail_frame oe_left" alt="User img"/>
|
||||
<div class="oe_mail_msg_content">
|
||||
<!-- contains the composition form -->
|
||||
<!-- default content: old basic textarea -->
|
||||
<div class="oe_mail_post_header">
|
||||
<t t-call="mail.thread.list_recipients"/>
|
||||
<a class="oe_cancel oe_e">X</a>
|
||||
</div>
|
||||
<textarea class="field_text" placeholder="Add your comment here..."/>
|
||||
<div class="oe_mail_post_footer">
|
||||
<div class="oe_mail_compose_attachment_list"/>
|
||||
<button class="oe_full">Full mail message</button>
|
||||
<button class="oe_post">Post message</button>
|
||||
<t t-call="mail.compose_message.add_attachment"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
mail.compose_message.add_attachment template
|
||||
Small template to be inserted in the composition for add attachments
|
||||
-->
|
||||
<t t-name="mail.compose_message.add_attachment">
|
||||
<div class="oe_attachment_file">
|
||||
<div class="oe_add">
|
||||
<!-- uploader of file -->
|
||||
<button><span class="oe_e">p</span></button>
|
||||
<t t-call="HiddenInputFile">
|
||||
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
|
||||
<t t-set="fileupload_action">/web/binary/upload_attachment</t>
|
||||
<input type="hidden" name="model" value=""/>
|
||||
<input type="hidden" name="id" value="0"/>
|
||||
<input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
mail.thread.message.attachments template
|
||||
Template used to display attachments in a mail.message
|
||||
-->
|
||||
<t t-name="mail.thread.message.attachments">
|
||||
<ul t-attf-class="oe_mail_msg_attachments #{widget.attachment_ids[0] and widget.options.thread.show_attachment_link?'':'oe_hidden'}">
|
||||
<t t-foreach="widget.attachment_ids" t-as="attachment">
|
||||
<li>
|
||||
<span t-if="(attachment.upload or 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>...wait upload...</span>
|
||||
<div t-attf-style="{attachment.percent_loaded>0?'':'display:none;'}"/>
|
||||
<div t-attf-style="{attachment.percent_loaded>20?'':'display:none;'}"/>
|
||||
<div t-attf-style="{attachment.percent_loaded>40?'':'display:none;'}"/>
|
||||
<div t-attf-style="{attachment.percent_loaded>60?'':'display:none;'}"/>
|
||||
<div t-attf-style="{attachment.percent_loaded>80?'':'display:none;'}"/>
|
||||
</div>
|
||||
<t t-raw="attachment.name || attachment.filename"/>
|
||||
</span>
|
||||
<a t-if="(!attachment.upload or attachment.percent_loaded>=100)" 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-if="widget.options.thread.show_attachment_delete and (!attachment.upload or attachment.percent_loaded>=100)">
|
||||
<a class="oe_right oe_mail_attachment_delete" title="Delete this attachmentt" t-attf-data-id="{attachment.id}">x</a>
|
||||
</t>
|
||||
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</t>
|
||||
|
||||
<t t-name="mail.thread.message.private">
|
||||
<div>
|
||||
<span class="oe_placeholder_checkbox_private"/>
|
||||
<span class="oe_send_private">This email is private.</span>
|
||||
<span class="oe_send_public">I wrote for contacts and all my followers.</span>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
template to the recipients list
|
||||
-->
|
||||
<t t-name="mail.thread.list_recipients">
|
||||
<div class="oe_mail_list_recipients">
|
||||
Post to:
|
||||
<span t-if="!widget.is_private" class="oe_all_follower">All Followers</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"/>
|
||||
</t>
|
||||
<t t-if="widget.partner_ids.length>=3">
|
||||
<span class="oe_more">, <a><t t-raw="widget.partner_ids.length-3"/> others...</a></span>
|
||||
<a class="oe_more_hidden"><<<</a>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
wall main template
|
||||
Template used to display the communication history in the wall.
|
||||
-->
|
||||
<div t-name="mail.wall" class="oe_view_manager oe_mail_wall oe_view_manager_current">
|
||||
<div t-name="mail.wall" class="oe_view_manager oe_mail_wall oe_view_manag
|
||||
er_current">
|
||||
<table class="oe_view_manager_header">
|
||||
<colgroup>
|
||||
<col width="33%"/>
|
||||
|
@ -25,21 +132,30 @@
|
|||
</td>
|
||||
<td><div class="oe_view_manager_view_search" t-opentag="true"/></td>
|
||||
</tr>
|
||||
<tr class="oe_header_row">
|
||||
<td colspan="2">
|
||||
<button type="button" class="oe_write_full oe_highlight">
|
||||
Compose a new message
|
||||
</button>
|
||||
<button type="button" class="oe_write_onwall" help="Your followers can read this message">
|
||||
Write to your followers
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<ul class="oe_mail_wall_threads">
|
||||
<!-- contains threads -->
|
||||
</ul>
|
||||
<!-- placeholder for the wall threads -->
|
||||
<div class="oe_mail_wall_threads"/>
|
||||
<div class="oe_mail_wall_aside">
|
||||
<!-- contains currently nothing -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
wall_thread_container template for the wall
|
||||
Each discussion thread is contained inside this template
|
||||
display message on the wall when there are no message
|
||||
-->
|
||||
<li t-name="mail.wall_thread_container" class="oe_mail_wall_thread">
|
||||
<li t-name="mail.wall_no_message" class="oe_wall_no_message">
|
||||
You have no messages
|
||||
</li>
|
||||
|
||||
<!--
|
||||
|
@ -54,39 +170,6 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
mail.compose_message template
|
||||
This template holds the composition form to write a note or send
|
||||
an e-mail. It contains by default a textarea, that will be replaced
|
||||
by another composition form in the main wall composition form, or
|
||||
for main thread composition form in document form view.
|
||||
-->
|
||||
<t t-name="mail.compose_message">
|
||||
<div class="oe_mail_compose_textarea">
|
||||
<img class="oe_mail_icon oe_mail_frame oe_left" alt="User img"/>
|
||||
<div class="oe_mail_msg_content">
|
||||
<!-- contains the composition form -->
|
||||
<!-- default content: old basic textarea -->
|
||||
<textarea placeholder="Add your comment here..."/>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
mail.compose_message.add_attachment template
|
||||
Small template to be inserted in the composition form to add attachments
|
||||
-->
|
||||
<t t-name="mail.compose_message.add_attachment">
|
||||
<t t-call="HiddenInputFile">
|
||||
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
|
||||
<t t-set="fileupload_action">/web/binary/upload_attachment</t>
|
||||
<input type="hidden" name="model" t-att-value="widget.form_view.model"/>
|
||||
<input type="hidden" name="id" t-att-value="widget.form_view.datarecord.id || 0"/>
|
||||
<input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
thread template
|
||||
This template holds a thread of comments. It begins with an actions
|
||||
|
@ -96,7 +179,6 @@
|
|||
<div t-name="mail.thread" class="oe_mail oe_mail_thread oe_semantic_html_override">
|
||||
<div class="oe_mail_thread_action">
|
||||
<!-- contains the composition box (form + image) -->
|
||||
<t t-call="mail.compose_message"/>
|
||||
</div>
|
||||
<ul class="oe_mail_thread_display">
|
||||
<!-- contains the threads -->
|
||||
|
@ -104,16 +186,15 @@
|
|||
</div>
|
||||
|
||||
<!-- default layout -->
|
||||
<li t-name="mail.thread.message" t-attf-class="oe_mail oe_mail_thread_msg #{widget.unread?'oe_mail_unread':'oe_mail_read'}" t-attf-data-msg_id="{widget.id}">
|
||||
<li t-name="mail.thread.message" t-attf-class="oe_mail oe_mail_thread_msg #{widget.unread?'oe_mail_unread':'oe_mail_read'}">
|
||||
<div t-attf-class="oe_mail_msg_#{widget.type} oe_semantic_html_override">
|
||||
<!-- message actions (read/unread, reply, delete...) -->
|
||||
<ul class="oe_header">
|
||||
<li class="placeholder-mail-vote"><t t-call="mail.thread.message.vote"/></li>
|
||||
<li t-if="!widget.options.thread.display_on_flat and widget.unread" title="Read"><a class="oe_read oe_e">W</a></li>
|
||||
<li t-if="!widget.options.thread.display_on_flat and !widget.unread" title="Set back to unread"><a class="oe_unread oe_e">h</a></li>
|
||||
<li t-if="!widget.options.message.show_reply_by_email" title="Reply"><a class="oe_reply oe_e">)</a></li>
|
||||
<li t-if="widget.options.message.show_reply_by_email"><a class="oe_reply_by_email oe_e" title="Reply by mail">)</a></li>
|
||||
<t t-if="(widget.options.message.show_reply || widget.options.message.show_reply_by_email || (widget.is_author and widget.options.message.show_dd_delete) || widget.type == 'email')">
|
||||
<li t-if="!widget.options.thread.display_on_flat" title="Read" class="oe_read"><a class="oe_read oe_e">W</a></li>
|
||||
<li t-if="!widget.options.thread.display_on_flat" title="Set back to unread" class="oe_unread"><a class="oe_unread oe_e">h</a></li>
|
||||
<li title="Quick reply"><a class="oe_reply oe_e">)</a></li>
|
||||
<t t-if="(widget.is_author and widget.options.message.show_dd_delete) or widget.type == 'email'">
|
||||
<li>
|
||||
<span class="oe_dropdown_toggle">
|
||||
<a class="oe_e" title="More options">í</a>
|
||||
|
@ -123,8 +204,6 @@
|
|||
<li t-if="display['show_hide']">
|
||||
<a href="#" class="oe_mail_msg_hide_type" t-attf-data-subtype='{widget.subtype}'>Hide '<t t-esc="widget.subtype"/>' for this document</a>
|
||||
</li> -->
|
||||
<li t-if="widget.options.message.show_reply" title="Reply"><a class="oe_reply oe_full_reply">Full reply</a></li>
|
||||
<li t-if="widget.options.message.show_reply_by_email"><a class="oe_reply_by_email oe_full_reply" title="Reply by mail">Full reply</a></li>
|
||||
<li t-if="widget.type == 'email'"><a class="oe_mail_msg_details" t-attf-href="#model=mail.message&id=#{widget.id}" >Details</a></li>
|
||||
</ul>
|
||||
</span>
|
||||
|
@ -145,7 +224,6 @@
|
|||
<ul class="oe_mail_msg_footer">
|
||||
<li t-if="widget.author_id"><a t-attf-href="#model=res.partner&id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a></li>
|
||||
<li><span t-att-title="widget.date"><t t-raw="widget.timerelative"/></span></li>
|
||||
|
||||
<li t-if="widget.attachment_ids.length > 0">
|
||||
<a class="oe_mail_msg_view_attachments">
|
||||
<t t-if="widget.attachment_ids.length == 1">1 Attachment</t>
|
||||
|
@ -155,7 +233,7 @@
|
|||
</ul>
|
||||
<div class="oe_clear"/>
|
||||
<div class="oe_mail_msg_body">
|
||||
<t t-if="widget.options.message.show_record_name and widget.record_name and (!widget.subject) and widget.options.thread._parents.length<=widget.options.thread.thread_level and widget.model!='res.partner'">
|
||||
<t t-if="widget.options.message.show_record_name and widget.record_name and (!widget.subject) and !widget.options.thread.thread_level and !widget.options.thread.display_on_flat and widget.model!='res.partner'">
|
||||
<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"/>
|
||||
|
@ -171,7 +249,7 @@
|
|||
</li>
|
||||
|
||||
<!-- expandable message layout -->
|
||||
<li t-name="mail.thread.expandable" t-attf-class="oe_mail oe_mail_thread_msg oe_mail_unread" t-attf-data-thread_id="{widget.id}">
|
||||
<li t-name="mail.thread.expandable" class="oe_mail oe_mail_thread_msg oe_mail_unread">
|
||||
<div t-attf-class="oe_mail_msg_#{widget.type} oe_semantic_html_override">
|
||||
<div class="oe_mail_msg_content oe_mail_msg_more_message">
|
||||
<a class="oe_mail_fetch_more">Load more messages <span t-if="widget.nb_messages>0">(<t t-raw="widget.nb_messages"/> messages not display)</span>...</a>
|
||||
|
@ -179,23 +257,6 @@
|
|||
</div>
|
||||
</li>
|
||||
|
||||
<!--
|
||||
mail.thread.message.attachments template
|
||||
Template used to display attachments in a mail.message
|
||||
-->
|
||||
<t t-name="mail.thread.message.attachments">
|
||||
<ul class="oe_mail_msg_attachments">
|
||||
<t t-foreach="record.attachment_ids" t-as="attachment">
|
||||
<li>
|
||||
<a t-att-href="attachment.url"><t t-raw="attachment.name || attachment.filename"/></a>
|
||||
<t t-if="record.show_attachment_delete">
|
||||
<a class="oe_right oe_mail_attachment_delete" title="Delete this attachmentt" t-attf-data-id="{attachment.id}">x</a>
|
||||
</t>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</t>
|
||||
|
||||
<!-- mail.thread.message.vote
|
||||
Template used to display Like/Unlike in a mail.message
|
||||
-->
|
||||
|
@ -215,7 +276,7 @@
|
|||
<button t-attf-class="oe_mail_msg_vote oe_tag">
|
||||
<span>
|
||||
<t t-if="!widget.has_voted">Agree</t>
|
||||
<t t-if="widget.has_voted">Unagree</t>
|
||||
<t t-if="widget.has_voted">Undo</t>
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
<span class="oe_unfollow">Unfollow</span>
|
||||
<span class="oe_following">Following</span>
|
||||
</button>
|
||||
<div class="oe_recthread_subtypes">
|
||||
<ul class="oe_subtypes"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_recthread_subtypes">
|
||||
<ul class="oe_subtypes"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_grey">
|
||||
|
|
|
@ -529,109 +529,6 @@ class test_mail(TestMailMockups):
|
|||
self.assertEqual(message2.subject, _subject, 'mail.message subject incorrect')
|
||||
self.assertEqual(message2.body, group_bird.description, 'mail.message body incorrect')
|
||||
|
||||
# FP Note: to be reviewed to be more generic, not depending on the algorythm of
|
||||
# message_read
|
||||
#def test_30_message_read(self):
|
||||
# """ Tests designed for message_read. """
|
||||
# # TDE NOTE: this test is not finished, as the message_read method is not fully specified.
|
||||
# # It will be updated as soon as we have fixed specs !
|
||||
# cr, uid = self.cr, self.uid
|
||||
# group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id)
|
||||
|
||||
# def _compare_structures(struct1, struct2, n=0):
|
||||
# # print '%scompare structure' % ('\t' * n)
|
||||
# # self.assertEqual(len(struct1), len(struct2), 'message_read structure number of childs incorrect')
|
||||
|
||||
# for x in range(len(struct1)):
|
||||
# if struct1[x].get('type') == 'expandable':
|
||||
# continue
|
||||
# # print '%s' % ('\t' * n), struct1[x]['id'], struct1[x]['child_nbr'], struct2[x]['id'], struct2[x].get('child_nbr', 'XX'), struct1[x].get('subject') or ''
|
||||
# self.assertEqual(struct1[x]['id'], struct2[x]['id'], 'message_read failure %s' % struct1[x].get('subject'))
|
||||
# _compare_structures(struct1[x]['child_ids'], struct2[x]['child_ids'], n + 1)
|
||||
# # print '%send compare' % ('\t' * n)
|
||||
|
||||
# # ----------------------------------------
|
||||
# # CASE1: Flattening test
|
||||
# # ----------------------------------------
|
||||
|
||||
# # Create dummy message structure
|
||||
# import copy
|
||||
# tree = [{'id': 2, 'child_nbr': 1, 'child_ids': [
|
||||
# {'id': 6, 'child_nbr': 1, 'child_ids': [
|
||||
# {'id': 8, 'child_nbr': 0, 'child_ids': []},
|
||||
# ]},
|
||||
# ]},
|
||||
# {'id': 1, 'child_nbr': 3, 'child_ids':[
|
||||
# {'id': 7, 'child_nbr': 1, 'child_ids': [
|
||||
# {'id': 9, 'child_nbr': 0, 'child_ids': []},
|
||||
# ]},
|
||||
# {'id': 4, 'child_nbr': 2, 'child_ids': [
|
||||
# {'id': 10, 'child_nbr': 0, 'child_ids': []},
|
||||
# {'id': 5, 'child_nbr': 0, 'child_ids': []},
|
||||
# ]},
|
||||
# {'id': 3, 'child_nbr': 0, 'child_ids': []},
|
||||
# ]},
|
||||
# ]
|
||||
# # Test: completely flat
|
||||
# new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 0, limit=15, add_expandable=False)
|
||||
# _compare_structures(new_tree, new_tree)
|
||||
# self.assertEqual(len(new_tree), 10, 'message_read_tree_flatten wrong in flat')
|
||||
# # Test: 1 thread level
|
||||
# tree_test = [{'id': 2, 'child_ids': [
|
||||
# {'id': 8, 'child_ids': []}, {'id': 6, 'child_ids': []},
|
||||
# ]},
|
||||
# {'id': 1, 'child_ids': [
|
||||
# {'id': 10, 'child_ids': []}, {'id': 9, 'child_ids': []},
|
||||
# {'id': 7, 'child_ids': []}, {'id': 5, 'child_ids': []},
|
||||
# {'id': 4, 'child_ids': []}, {'id': 3, 'child_ids': []},
|
||||
# ]},
|
||||
# ]
|
||||
# new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 1, limit=15, add_expandable=False)
|
||||
# _compare_structures(new_tree, tree_test)
|
||||
# # Test: 2 thread levels
|
||||
# new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 2, limit=15, add_expandable=False)
|
||||
# _compare_structures(new_tree, tree)
|
||||
|
||||
# # ----------------------------------------
|
||||
# # CASE2: message_read test
|
||||
# # ----------------------------------------
|
||||
|
||||
# # 1. Add a few messages to pigs group
|
||||
# msgid1 = group_pigs.message_post(body='1', subject='1', parent_id=False)
|
||||
# msgid2 = group_pigs.message_post(body='2', subject='1-1', parent_id=msgid1)
|
||||
# msgid3 = group_pigs.message_post(body='3', subject='1-2', parent_id=msgid1)
|
||||
# msgid4 = group_pigs.message_post(body='4', subject='2', parent_id=False)
|
||||
# msgid5 = group_pigs.message_post(body='5', subject='1-1-1', parent_id=msgid2)
|
||||
# msgid6 = group_pigs.message_post(body='6', subject='2-1', parent_id=msgid4)
|
||||
|
||||
# # Test: read all messages flat
|
||||
# tree_test = [{'id': msgid6, 'child_ids': []}, {'id': msgid5, 'child_ids': []},
|
||||
# {'id': msgid4, 'child_ids': []}, {'id': msgid3, 'child_ids': []},
|
||||
# {'id': msgid2, 'child_ids': []}, {'id': msgid1, 'child_ids': []}]
|
||||
# tree = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], level=0, limit=15)
|
||||
# _compare_structures(tree, tree_test)
|
||||
# # Test: read with 1 level of thread
|
||||
# tree_test = [{'id': msgid4, 'child_ids': [{'id': msgid6, 'child_ids': []}, ]},
|
||||
# {'id': msgid1, 'child_ids': [
|
||||
# {'id': msgid5, 'child_ids': []}, {'id': msgid3, 'child_ids': []},
|
||||
# {'id': msgid2, 'child_ids': []},
|
||||
# ]},
|
||||
# ]
|
||||
# tree = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], level=1, limit=15)
|
||||
# _compare_structures(tree, tree_test)
|
||||
# # Test: read with 2 levels of thread
|
||||
# tree_test = [{'id': msgid4, 'child_ids': [{'id': msgid6, 'child_ids': []}, ]},
|
||||
# {'id': msgid1, 'child_ids': [
|
||||
# {'id': msgid3, 'child_ids': []},
|
||||
# {'id': msgid2, 'child_ids': [{'id': msgid5, 'child_ids': []}, ]},
|
||||
# ]},
|
||||
# ]
|
||||
# tree = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], level=2, limit=15)
|
||||
# _compare_structures(tree, tree_test)
|
||||
|
||||
# # 2. Test expandables
|
||||
# # TDE FIXME: add those tests when expandables are specified and implemented
|
||||
|
||||
def test_40_needaction(self):
|
||||
""" Tests for mail.message needaction. """
|
||||
cr, uid = self.cr, self.uid
|
||||
|
|
|
@ -223,7 +223,6 @@ class mail_compose_message(osv.TransientModel):
|
|||
email(s), rendering any template patterns on the fly if needed. """
|
||||
if context is None:
|
||||
context = {}
|
||||
print '**', context
|
||||
active_ids = context.get('active_ids')
|
||||
|
||||
for wizard in self.browse(cr, uid, ids, context=context):
|
||||
|
|
|
@ -16,13 +16,11 @@
|
|||
<field name="partner_ids" widget="many2many_tags" placeholder="Add contacts to notify..."
|
||||
context="{'force_email':True}"
|
||||
on_change="onchange_partner_ids(partner_ids)"/>
|
||||
<field name="is_private" help="If this message is not private, this message will send to all your followers or all followers of the parented message."/>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Body">
|
||||
<field name="body_text" nolabel="1"
|
||||
attrs="{'invisible':[('content_subtype', '=', 'html')]}"/>
|
||||
<field name="body" nolabel="1"
|
||||
attrs="{'invisible':[('content_subtype', '=', 'plain')]}"/>
|
||||
<field name="body" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" nolabel="1"/>
|
||||
|
@ -32,10 +30,10 @@
|
|||
<button string="Send" name="send_mail" type="object" class="oe_highlight" />
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
<div class="oe_right">
|
||||
<!--div class="oe_right">
|
||||
<button string="" name="toggle_content_subtype" type="object" icon="/mail/static/src/img/formatting.png"
|
||||
help="Toggle advanced formatting mode"/>
|
||||
</div>
|
||||
</div-->
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -68,6 +66,7 @@
|
|||
context="{'force_email':True}"
|
||||
on_change="onchange_partner_ids(partner_ids)"
|
||||
class="oe_mail_compose_message_partner_ids"/>
|
||||
<!--field name="is_private" help="If this message is not private, this message will send to all your followers or all followers of the parented message."/-->
|
||||
<field name="attachment_ids" colspan="2" nolabel="1" widget="many2many_tags"
|
||||
placeholder="Add attachments..." invisible="1"
|
||||
class="oe_mail_compose_message_attachment_ids"/>
|
||||
|
|
Loading…
Reference in New Issue