From 3657e4bd821e60544880985a5d48a5bc4419d803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 31 Jan 2012 16:50:00 +0100 Subject: [PATCH 001/133] [ADD] Added empty files for mail_group and mail_group views. Added css file for kanban view. Modified init and openerp files accordingly. bzr revid: tde@openerp.com-20120131155000-cmzd88d0rkso8sl1 --- addons/mail/__init__.py | 1 + addons/mail/__openerp__.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/addons/mail/__init__.py b/addons/mail/__init__.py index 4787883ef9c..c7fffb3a338 100644 --- a/addons/mail/__init__.py +++ b/addons/mail/__init__.py @@ -21,6 +21,7 @@ import mail_message import mail_thread +import mail_group import res_partner import wizard diff --git a/addons/mail/__openerp__.py b/addons/mail/__openerp__.py index 8085d301364..5e52e103852 100644 --- a/addons/mail/__openerp__.py +++ b/addons/mail/__openerp__.py @@ -58,6 +58,7 @@ The main features are: 'data': [ "wizard/mail_compose_message_view.xml", "mail_message_view.xml", + "mail_group_view.xml", "mail_thread_view.xml", "res_partner_view.xml", 'security/ir.model.access.csv', @@ -67,5 +68,6 @@ The main features are: 'auto_install': False, 'certificate': '001056784984222247309', 'images': ['images/customer_history.jpeg','images/messages_form.jpeg','images/messages_list.jpeg'], + 'css': ['static/src/css/mail_group.css'], } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From a0a89fd37b24553776fa451466a922e727915571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 31 Jan 2012 16:52:57 +0100 Subject: [PATCH 002/133] [ADD] Really added files I was pretending to add in previous revision bzr revid: tde@openerp.com-20120131155257-skq6lu8g0mptm19h --- addons/mail/mail_group.py | 20 +++++++ addons/mail/mail_group_view.xml | 4 ++ addons/mail/static/src/css/mail_group.css | 68 +++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 addons/mail/mail_group.py create mode 100644 addons/mail/mail_group_view.xml create mode 100644 addons/mail/static/src/css/mail_group.css diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py new file mode 100644 index 00000000000..5dfeb073de6 --- /dev/null +++ b/addons/mail/mail_group.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010-2011 OpenERP SA () +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see +# +############################################################################## \ No newline at end of file diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml new file mode 100644 index 00000000000..b2839b2cc0a --- /dev/null +++ b/addons/mail/mail_group_view.xml @@ -0,0 +1,4 @@ + + + + diff --git a/addons/mail/static/src/css/mail_group.css b/addons/mail/static/src/css/mail_group.css new file mode 100644 index 00000000000..a65f766210e --- /dev/null +++ b/addons/mail/static/src/css/mail_group.css @@ -0,0 +1,68 @@ +.oe_group_vignette { + padding: 8px 0; + min-height: 100px; +} + +.oe_group_image, .oe_group_details { + display: inline-block; + vertical-align: top; +} + +.oe_group_image { + width: 100px; + height: 100px; + text-align: center; + overflow: hidden; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + -o-border-radius: 3px; + -ms-border-radius: 3px; + border-radius: 3px; + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); + -o-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); + -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); +} + +.oe_group_picture { + width: 100px; + height: auto; + clip: rect(10px, 100px, 110px, 0px); +} + +.oe_group_picture_wide { + height: 100px; + width: auto; + clip: rect(0px, 115px, 100px, 15px); +} + +.oe_group_details { + width: 220px; + font-size: 13px; + padding: 2px 5px; + color: #4c4c4c; + min-height: 120px; +} + +.oe_group_details h4 { + margin: 0; + font-size: 13px; +} + +.oe_group_details h4 a { + color: #4c4c4c; +} + +.oe_group_details h4 a:hover { + text-decoration: underline; +} + +.oe_group_details ul { + margin: 3px 0 5px; + padding: 0; + list-style: none; +} + +.oe_group_details li { + margin: 2px 0; +} From f4551851fd7a3905782b4e81b81878d867cb2ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 31 Jan 2012 16:54:12 +0100 Subject: [PATCH 003/133] [IMP] Added group and subscription models. Added subscription mechanism when searching for tweets. Added views. bzr revid: tde@openerp.com-20120131155412-r16jr1nhwd9k4srv --- addons/mail/mail_group.py | 132 +++++++++++++++++++++++- addons/mail/mail_group_view.xml | 176 +++++++++++++++++++++++++++++++- addons/mail/mail_message.py | 81 ++++++++++++++- 3 files changed, 384 insertions(+), 5 deletions(-) diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index 5dfeb073de6..996f9f174ae 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -17,4 +17,134 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see # -############################################################################## \ No newline at end of file +############################################################################## + +import tools +from osv import osv +from osv import fields +from tools.translate import _ + +class mail_group(osv.osv): + """ + A mail group is a collection of users sharing messages. Mail groups are different from user groups + because they don't have a specific field holding users. Group users are users that follow + the mail group, using the subscription/follow mechanism of Chatter. + """ + + _name = 'mail.group' + _inherits = {'res.groups': 'group_id'} + + def action_group_join(self, cr, uid, ids, context={}): + sub_obj = self.pool.get('mail.subscription') + menu_values = {'res_model': 'mail.group', 'user_id': uid} + for id in ids: + menu_values['res_id'] = id + sub_id = sub_obj.create(cr, uid, menu_values, context=context) + + for group in self.browse(cr, uid, ids, context): + self.write(cr, uid, group.id, { + 'users': [(4, uid)] + }) + + return True + + _columns = { + 'group_id': fields.many2one('res.groups', required=True, ondelete='cascade', + string='Group', + help='The group extended by this portal'), + #'name': fields.char('Name', size=64, required=True), + 'description': fields.text('Description'), + 'responsible_id': fields.many2one('res.users', string='Responsible', + ondelete='set null', required=True), + 'public': fields.boolean('Public', help='This group is visible by non members') + } + + _defaults = { + 'public': True, + } + + + def create(self, cr, uid, values, context=None): + """ extend create() to automatically create a menu for the group """ + if context is None: context = {} + # create group + group_id = super(mail_group, self).create(cr, uid, values, context) + # create menu + self._create_menu(cr, uid, [group_id], context) + return group_id + + def _create_menu(self, cr, uid, ids, context=None): + """ create a menu for the given groups """ + menu_obj = self.pool.get('ir.ui.menu') + ir_data = self.pool.get('ir.model.data') + act_win_obj = self.pool.get('ir.actions.act_window') + menu_root = self._get_res_xml_id(cr, uid, 'mail', 'mg_groups') + + for group in self.browse(cr, uid, ids, context): + # create an ir.action.act_window action + act_values = { + 'name': '%s' % group.name, + 'res_model': 'mail.message', + 'domain': '["&", ("res_model", "=", "mail.group"), ("res_id", "=", %s)]' % group.id, + } + act_id = act_win_obj.create(cr, uid, act_values, context) + # create a menuitem under 'mail.mg_groups' + menu_values = { + 'name': _('%s') % group.name, + 'parent_id': menu_root, + 'action': 'ir.actions.act_window,%s' % (act_id), + 'groups_id': [(6, 0, [group.group_id.id])], + } + menu_id = menu_obj.create(cr, uid, menu_values, context) + # create data + data_values = { + 'name': _('%s') % group.name, + 'model': 'ir.ui.menu', + 'module': 'portal', + 'res_id': menu_id, + 'noupdate': 'True'} + data_id = ir_data.create(cr, uid, data_values, context) + return True + + def _assign_menu(self, cr, uid, ids, context=None): + """ assign groups (ids) menu to the users joigning the groups""" + user_obj = self.pool.get('res.users') + for p in self.browse(cr, uid, ids, context): + # user menu action = portal menu action if set in portal + if p.menu_action_id: + user_ids = [u.id for u in p.users if u.id != 1] + user_values = {'menu_id': p.menu_action_id.id} + user_obj.write(cr, uid, user_ids, user_values, context) + + def _get_res_xml_id(self, cr, uid, module, xml_id): + """ return the resource id associated to the given xml_id """ + data_obj = self.pool.get('ir.model.data') + data_id = data_obj._get_id(cr, uid, module, xml_id) + return data_obj.browse(cr, uid, data_id).res_id + + +mail_group() + + +class mail_subscription(osv.osv): + """ + mail_subscription holds the data related to the follow mechanism inside OpenERP. + A subscription can be of following: + - res_model: model of the followed objects + - res_id: ID of resource OR + - res_domain: a domain filtering followed objects + """ + + _name = 'mail.subscription' + _rec_name = 'id' + _columns = { + 'res_model': fields.char('Related Document model', size=128, select=1), + 'res_id': fields.integer('Related Document ID', select=1), + 'res_domain': fields.char('res_domain', size=256), + 'user_id': fields.integer('Related User ID', select=1), + } + + _defaults = { + } + +mail_subscription() diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index b2839b2cc0a..3532eed5871 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -1,4 +1,178 @@ + - + + + mail.message.tree_tweet + mail.message + tree + 15 + + + + + + + + + + + + mail.message.form_tweet + mail.message + form + 15 + +
+ + + + + + + + + + + + +
+ + + + mail.message.search_tweet + mail.message + search + + + + + + + + + + mail.group.kanban + mail.group + kanban + + + + + +
+
+ + prout +
+
+

+
    +
  • +
  • Join
  • +
  • Joined
  • +
+
+ +
+
+
+
+
+
+ + + + mail.group.form + mail.group + form + + +
+ + + + + + + + + + + + + +
+ + + + Groups + mail.group + form + kanban,tree,form + + + + Messages + mail.message + form + tree,form + {'filter_search': True, 'tree_view_ref': 'mail.view_tweet_tree', 'form_view_ref': 'mail.view_tweet_form'} + + + + + Messages + mail.message + form + tree,form + {'filter_search': True, 'tree_view_ref': 'mail.view_tweet_tree', 'form_view_ref': 'mail.view_tweet_form'} + + [('user_id', '=', uid)] + + + + Subscriptions + mail.subscription + form + tree,form + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 1693397f6fa..825e3f3c7c6 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -71,8 +71,8 @@ class mail_message_common(osv.osv_memory): _rec_name = 'subject' _columns = { 'subject': fields.char('Subject', size=512, required=True), - 'model': fields.char('Related Document model', size=128, select=1, readonly=1), - 'res_id': fields.integer('Related Document ID', select=1, readonly=1), + 'model': fields.char('Related Document model', size=128, select=1), # was rfeadonly + 'res_id': fields.integer('Related Document ID', select=1), # was rfeadonly 'date': fields.datetime('Date'), 'email_from': fields.char('From', size=128, help='Message sender, taken from user preferences. If empty, this is not a mail but a message.'), 'email_to': fields.char('To', size=256, help='Message recipients'), @@ -163,7 +163,7 @@ class mail_message(osv.osv): _columns = { 'partner_id': fields.many2one('res.partner', 'Related partner'), - 'user_id': fields.many2one('res.users', 'Related user', readonly=1), + #'user_id': fields.many2one('res.users', 'Related user', readonly=1), 'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id', 'Attachments'), 'display_text': fields.function(_get_display_text, method=True, type='text', size="512", string='Display Text'), 'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing mail server', readonly=1), @@ -176,12 +176,87 @@ class mail_message(osv.osv): ], 'State', readonly=True), 'auto_delete': fields.boolean('Auto Delete', help="Permanently delete this email after sending it, to save space"), 'original': fields.binary('Original', help="Original version of the message, as it was sent on the network", readonly=1), + # tde add/modif + 'user_id': fields.many2one('res.users', 'Related user', readonly=1), + 'type': fields.selection([ + ('tweet', 'Tweet'), + ('status', 'Status'), + ], 'Type'), + 'need_action': fields.boolean('Need action'), } _defaults = { 'state': 'received', } + # thib add + def create(self, cr, uid, vals, context=None): + print vals + return super(mail_message, self).create(cr, uid, vals, context) + + def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): + if not context or not context.has_key('filter_search'): + return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) + + # get subscriptions + sub_obj = self.pool.get('mail.subscription') + sub_ids = sub_obj.search(cr, uid, [('user_id', '=', uid)]) + subs = sub_obj.browse(cr, uid, sub_ids) + + # stock tweets to find + res_model_ids_dict = {} + res_model_all_list = [] + + # check all subscriptions + for sub in subs: + if sub.res_model and sub.res_id == 0 and sub.res_domain == False: + print "s-1" + if sub.res_model not in res_model_all_list: + res_model_all_list.append(sub.res_model) + elif sub.res_model and sub.res_id: + print "s-2" + if res_model_ids_dict.has_key(sub.res_model): + res_model_ids_dict[sub.res_model].append(sub.res_id) + else: + res_model_ids_dict[sub.res_model] = [sub.res_id] + elif sub.res_model and sub.res_domain: + print "s-3" + res_obj = self.pool.get(sub.res_model) + print sub.res_domain + #res_ids = res_obj.search(cr, uid, [('id', 'in', [1,2])]) + res_ids = res_obj.search(cr, uid, eval(sub.res_domain)) + if res_model_ids_dict.has_key(sub.res_model): + res_model_ids_dict[sub.res_model] += res_ids + else: + res_model_ids_dict[sub.res_model] = res_ids + print 'cacaprout' + else: + print 'erreur !!!' + print sub + + # add fully-followed domains + args.append('|') + args.append(['model', 'in', res_model_all_list]) + + # add partially-followed domains + for x in range(0, len(res_model_ids_dict.keys())-1): + args.append('|') + + for res_model in res_model_ids_dict.keys(): + if res_model not in res_model_all_list: + args.append('&') + args.append(['model', '=', res_model]) + args.append(['res_id', 'in', res_model_ids_dict[res_model]]) + + if context and context.has_key('filter_search'): + pass + else: + args = [] + print args + return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit,order=order, context=context, count=count) + + # end thib add + def init(self, cr): cr.execute("""SELECT indexname FROM pg_indexes WHERE indexname = 'mail_message_model_res_id_idx'""") if not cr.fetchone(): From b15ec8334bc641877e96957a064ca3b435248429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 31 Jan 2012 16:57:48 +0100 Subject: [PATCH 004/133] [FIX] Fixed missing fields for search. bzr revid: tde@openerp.com-20120131155748-1ossao3j32wd8bal --- addons/mail/mail_group_view.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 3532eed5871..755583cc136 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -13,6 +13,8 @@ + + From 2107ef2017ffa97b2029b2fb682895be4ff9d08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 1 Feb 2012 12:02:34 +0100 Subject: [PATCH 005/133] [FIX] Wrong field name in message tree view bzr revid: tde@openerp.com-20120201110234-a3vkrrtp70bc7wob --- addons/mail/mail_group_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 755583cc136..d6b852a2cbe 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -13,7 +13,7 @@ - + From 991d9b784399ab0efa602dfba5f6e5beee445356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 1 Feb 2012 16:42:13 +0100 Subject: [PATCH 006/133] [FIX] spelling error bzr revid: tde@openerp.com-20120201154213-utvgy12zt49c7jcq --- addons/mail/mail_group_view.xml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index d6b852a2cbe..ee92758d5f9 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -116,7 +116,7 @@ - + Groups mail.group form @@ -150,22 +150,24 @@ - + - + - + + + - - + - + + + - + - - - + - + + + + + \ No newline at end of file diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 23c131ec66b..c1e8f7aa098 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -82,7 +82,7 @@ class mail_thread(osv.osv): }) return super(mail_thread, self).copy(cr, uid, id, default, context=context) - def message_append(self, cr, uid, threads, subject, body_text=None, email_to=False, + def message_append(self, cr, uid, threads, subject, body_text=None, type='email', email_to=False, email_from=False, email_cc=None, email_bcc=None, reply_to=None, email_date=None, message_id=False, references=None, attachments=None, body_html=None, subtype=None, headers=None, @@ -166,7 +166,8 @@ class mail_thread(osv.osv): 'message_id': message_id, 'body_text': body_text or (hasattr(thread, 'description') and thread.description or False), 'attachment_ids': [(6, 0, to_attach)], - 'state' : 'received', + 'state': 'received', + 'type': type, } if email_from: @@ -215,9 +216,12 @@ class mail_thread(osv.osv): to determine the model of the thread to update (instead of the current model). """ + # 6.2 Social feature: add default email type for old API + if not 'type' in msg_dict: msg_dict['type'] = 'email' return self.message_append(cr, uid, ids, subject = msg_dict.get('subject'), body_text = msg_dict.get('body_text'), + type = msg_dict.get('type'), email_to = msg_dict.get('to'), email_from = msg_dict.get('from'), email_cc = msg_dict.get('cc'), @@ -235,8 +239,15 @@ class mail_thread(osv.osv): context = context) # Message loading - def message_load(self): - pass + def message_load(self, cr, uid, ids, context=None): + """ Social feature added this method + loading message: search in mail.messages where res_id = ids, (res_)model = current model """ + msg_obj = self.pool.get('mail.message') + msg_ids = [] + for id in ids: + msg_ids += msg_obj.search(cr, uid, ['&', ('res_id', '=', id), ('model', '=', self._name)], context=context) + msgs = msg_obj.browse(cr, uid, ids) + return msgs #------------------------------------------------------ # Email specific @@ -484,8 +495,8 @@ class mail_thread(osv.osv): #------------------------------------------------------ # Note specific #------------------------------------------------------ - def message_append_note(self, context, type='notification'): - pass + def message_append_note(self, cr, uid, ids, subject, body, type='notification', context=None): + return self.message_append(cr, uid, ids, subject, body_text=body, type=type, context=context) #------------------------------------------------------ # Subscription mechanism From a83847d6f74f832fa9c49a70cf9560f51c281007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 2 Feb 2012 11:35:01 +0100 Subject: [PATCH 012/133] [ADD] Implementation of subscription mechanism methods bzr revid: tde@openerp.com-20120202103501-0tt9epmzkfcuf8xz --- addons/mail/mail_thread.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index c1e8f7aa098..8d5a05fb2bb 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -501,16 +501,27 @@ class mail_thread(osv.osv): #------------------------------------------------------ # Subscription mechanism #------------------------------------------------------ - def message_get_subscribers(self): - pass - - def message_subscribe(self): - pass - - def message_unsubscribe(self): - pass - + def message_get_subscribers(self, cr, uid, ids, context=None): + subscription_obj = self.pool.get('mail.subscription') + for id in ids: + sub_ids = subscription_obj.search(cr, uid, ['res_model': self._name, 'res_id': id], context=context) + subs = subscription_obj.browse(cr, uid, sub_ids, context=context) + return subs + def message_subscribe(self, cr, uid, ids, context=None): + subscription_obj = self.pool.get('mail.subscription') + subscriber_id = uid # TODO + for id in ids: + subscription_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': subscriber_id}, context=context) + return True + def message_unsubscribe(self, cr, uid, ids, context=None): + subscription_obj = self.pool.get('mail.subscription') + subscriber_id = uid # TODO + sub_ids = [] + for id in ids: + sub_ids += subscription_obj.search(cr, uid, ['res_model': self._name, 'res_id': id, 'user_id': subscriber_id], context=context) + subscription_obj.unlink(cr, uid, ids, context=context) + return True # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 109647a109de0f0c45329570ff1b5e863359717e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 2 Feb 2012 12:26:57 +0100 Subject: [PATCH 013/133] [IMP] Added push of messages when creating one. Fixed bugs in mail_thread subscription mechanism. Added list views for subscriptions and notifications. Subscription is now unread by default. bzr revid: tde@openerp.com-20120202112657-zj406ck98n06imo9 --- addons/mail/mail_message.py | 20 +++++++++++--- addons/mail/mail_subscription.py | 5 ++-- addons/mail/mail_subscription_view.xml | 36 ++++++++++++++++++++++++++ addons/mail/mail_thread.py | 4 +-- 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 877ffd972b6..dfd2fe00b92 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -71,8 +71,8 @@ class mail_message_common(osv.osv_memory): _rec_name = 'subject' _columns = { 'subject': fields.char('Subject', size=512, required=True), - 'model': fields.char('Related Document model', size=128, select=1), # was rfeadonly - 'res_id': fields.integer('Related Document ID', select=1), # was rfeadonly + 'model': fields.char('Related Document model', size=128, select=1), # was readonly + 'res_id': fields.integer('Related Document ID', select=1), # was readonly 'date': fields.datetime('Date'), 'email_from': fields.char('From', size=128, help='Message sender, taken from user preferences. If empty, this is not a mail but a message.'), 'email_to': fields.char('To', size=256, help='Message recipients'), @@ -191,11 +191,23 @@ class mail_message(osv.osv): } #------------------------------------------------------ - # Note specific api + # Generic api #------------------------------------------------------ def create(self, cr, uid, vals, context=None): - return super(mail_message, self).create(cr, uid, vals, context) + msg_id = super(mail_message, self).create(cr, uid, vals, context) + # push the message to suscribed users + subscription_obj = self.pool.get('mail.subscription') + notification_obj = self.pool.get('mail.notification') + sub_ids = subscription_obj.search(cr, uid, ['&', ('res_model', '=', vals['model']), ('user_id', '=', uid)], context=context) + subs = subscription_obj.browse(cr, uid, sub_ids, context=context) + for sub in subs: + notification_obj.create(cr, uid, {'user_id': sub.user_id, 'message_id': msg_id}, context=context) + return msg_id + + #------------------------------------------------------ + # Note specific api + #------------------------------------------------------ def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): if not context or not context.has_key('filter_search'): diff --git a/addons/mail/mail_subscription.py b/addons/mail/mail_subscription.py index f250ddc42e6..89750c47f5f 100644 --- a/addons/mail/mail_subscription.py +++ b/addons/mail/mail_subscription.py @@ -30,7 +30,7 @@ class mail_subscription(osv.osv): A subscription can be of following: - res_model: model of the followed objects - res_id: ID of resource OR - - res_domain: a domain filtering followed objects + - res_domain: a domain filtering followed objects - currently removed """ _name = 'mail.subscription' @@ -38,7 +38,7 @@ class mail_subscription(osv.osv): _columns = { 'res_model': fields.char('Related Document model', size=128, select=1), 'res_id': fields.integer('Related Document ID', select=1), - 'res_domain': fields.char('res_domain', size=256), + #'res_domain': fields.char('res_domain', size=256), 'user_id': fields.integer('Related User ID', select=1), } @@ -63,6 +63,7 @@ class mail_notification(osv.osv): } _defaults = { + 'read': False, } mail_notification() diff --git a/addons/mail/mail_subscription_view.xml b/addons/mail/mail_subscription_view.xml index 75f0408f341..2850cd206a1 100644 --- a/addons/mail/mail_subscription_view.xml +++ b/addons/mail/mail_subscription_view.xml @@ -2,6 +2,42 @@ + + + + mail.subscription.tree + mail.subscription + tree + 10 + + + + + + + + + + + + + mail.notification.tree + mail.notification + tree + 10 + + + + + + + + + Subscriptions mail.subscription diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 8d5a05fb2bb..e9df98ee955 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -504,7 +504,7 @@ class mail_thread(osv.osv): def message_get_subscribers(self, cr, uid, ids, context=None): subscription_obj = self.pool.get('mail.subscription') for id in ids: - sub_ids = subscription_obj.search(cr, uid, ['res_model': self._name, 'res_id': id], context=context) + sub_ids = subscription_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', '=', id)], context=context) subs = subscription_obj.browse(cr, uid, sub_ids, context=context) return subs @@ -520,7 +520,7 @@ class mail_thread(osv.osv): subscriber_id = uid # TODO sub_ids = [] for id in ids: - sub_ids += subscription_obj.search(cr, uid, ['res_model': self._name, 'res_id': id, 'user_id': subscriber_id], context=context) + sub_ids += subscription_obj.search(cr, uid, ['&', '&', ('res_model', '=', self._name), ('res_id', '=', id), ('user_id', '=', subscriber_id)], context=context) subscription_obj.unlink(cr, uid, ids, context=context) return True From 1b9b26693ccc932c820df7cc1ccbe56dfc490fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 2 Feb 2012 15:18:43 +0100 Subject: [PATCH 014/133] [ADD] Added first not-working draft for widget. Cleaned message search function. bzr revid: tde@openerp.com-20120202141843-4jq49mbd7a6ecq4b --- addons/mail/__openerp__.py | 16 +++- addons/mail/mail_message.py | 117 +++++++++++++++------------- addons/mail/static/src/js/mail.js | 53 +++++++------ addons/mail/static/src/xml/mail.xml | 17 ++++ 4 files changed, 126 insertions(+), 77 deletions(-) create mode 100644 addons/mail/static/src/xml/mail.xml diff --git a/addons/mail/__openerp__.py b/addons/mail/__openerp__.py index ed28c5be365..ec079463230 100644 --- a/addons/mail/__openerp__.py +++ b/addons/mail/__openerp__.py @@ -68,7 +68,19 @@ The main features are: 'installable': True, 'auto_install': False, 'certificate': '001056784984222247309', - 'images': ['images/customer_history.jpeg','images/messages_form.jpeg','images/messages_list.jpeg'], - 'css': ['static/src/css/mail_group.css'], + 'images': [ + 'images/customer_history.jpeg', + 'images/messages_form.jpeg', + 'images/messages_list.jpeg', + ], + 'css': [ + 'static/src/css/mail_group.css', + ], + 'js': [ + 'static/src/js/mail.js', + ], + 'qweb': [ + 'static/src/xml/mail.xml', + ], } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index dfd2fe00b92..b13d9a3d389 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -205,70 +205,81 @@ class mail_message(osv.osv): notification_obj.create(cr, uid, {'user_id': sub.user_id, 'message_id': msg_id}, context=context) return msg_id + def get_pushed_messages(self, cr, uid, context=None): + """Wall: get messages to display""" + notification_obj = self.pool.get('mail.notification') + notification_ids = notification_obj.search(cr, uid, [('user_id', '=', uid)], context=context) + notifications = notification_obj.browse(cr, uid, notification_ids, context=context) + + # TODO / REMARK: classify based on res_model / res_id to have a 1_level hierarchy ? + + return notifications + + #------------------------------------------------------ # Note specific api #------------------------------------------------------ - def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): - if not context or not context.has_key('filter_search'): - return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) + #def tmp_backup(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): + #if not context or not context.has_key('filter_search'): + #return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) - # get subscriptions - sub_obj = self.pool.get('mail.subscription') - sub_ids = sub_obj.search(cr, uid, [('user_id', '=', uid)]) - subs = sub_obj.browse(cr, uid, sub_ids) + ## get subscriptions + #sub_obj = self.pool.get('mail.subscription') + #sub_ids = sub_obj.search(cr, uid, [('user_id', '=', uid)]) + #subs = sub_obj.browse(cr, uid, sub_ids) - # stock tweets to find - res_model_ids_dict = {} - res_model_all_list = [] + ## stock tweets to find + #res_model_ids_dict = {} + #res_model_all_list = [] - # check all subscriptions - for sub in subs: - if sub.res_model and sub.res_id == 0 and sub.res_domain == False: - print "s-1" - if sub.res_model not in res_model_all_list: - res_model_all_list.append(sub.res_model) - elif sub.res_model and sub.res_id: - print "s-2" - if res_model_ids_dict.has_key(sub.res_model): - res_model_ids_dict[sub.res_model].append(sub.res_id) - else: - res_model_ids_dict[sub.res_model] = [sub.res_id] - elif sub.res_model and sub.res_domain: - print "s-3" - res_obj = self.pool.get(sub.res_model) - print sub.res_domain - #res_ids = res_obj.search(cr, uid, [('id', 'in', [1,2])]) - res_ids = res_obj.search(cr, uid, eval(sub.res_domain)) - if res_model_ids_dict.has_key(sub.res_model): - res_model_ids_dict[sub.res_model] += res_ids - else: - res_model_ids_dict[sub.res_model] = res_ids - print 'cacaprout' - else: - print 'erreur !!!' - print sub + ## check all subscriptions + #for sub in subs: + #if sub.res_model and sub.res_id == 0 and sub.res_domain == False: + #print "s-1" + #if sub.res_model not in res_model_all_list: + #res_model_all_list.append(sub.res_model) + #elif sub.res_model and sub.res_id: + #print "s-2" + #if res_model_ids_dict.has_key(sub.res_model): + #res_model_ids_dict[sub.res_model].append(sub.res_id) + #else: + #res_model_ids_dict[sub.res_model] = [sub.res_id] + #elif sub.res_model and sub.res_domain: + #print "s-3" + #res_obj = self.pool.get(sub.res_model) + #print sub.res_domain + ##res_ids = res_obj.search(cr, uid, [('id', 'in', [1,2])]) + #res_ids = res_obj.search(cr, uid, eval(sub.res_domain)) + #if res_model_ids_dict.has_key(sub.res_model): + #res_model_ids_dict[sub.res_model] += res_ids + #else: + #res_model_ids_dict[sub.res_model] = res_ids + #print 'cacaprout' + #else: + #print 'erreur !!!' + #print sub - # add fully-followed domains - args.append('|') - args.append(['model', 'in', res_model_all_list]) + ## add fully-followed domains + #args.append('|') + #args.append(['model', 'in', res_model_all_list]) - # add partially-followed domains - for x in range(0, len(res_model_ids_dict.keys())-1): - args.append('|') + ## add partially-followed domains + #for x in range(0, len(res_model_ids_dict.keys())-1): + #args.append('|') - for res_model in res_model_ids_dict.keys(): - if res_model not in res_model_all_list: - args.append('&') - args.append(['model', '=', res_model]) - args.append(['res_id', 'in', res_model_ids_dict[res_model]]) + #for res_model in res_model_ids_dict.keys(): + #if res_model not in res_model_all_list: + #args.append('&') + #args.append(['model', '=', res_model]) + #args.append(['res_id', 'in', res_model_ids_dict[res_model]]) - if context and context.has_key('filter_search'): - pass - else: - args = [] - print args - return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit,order=order, context=context, count=count) + #if context and context.has_key('filter_search'): + #pass + #else: + #args = [] + #print args + #return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit,order=order, context=context, count=count) #------------------------------------------------------ # E-Mail api diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 2e81741f62a..6e23d813702 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -1,25 +1,34 @@ openerp.mail = function(session) { - -var mail = session.mail = {}; - -mail.Wall = session.web.Widget.extend({ - init: function(parent) { - }, - start: function() { - this.$element - }, -}); - -session.ThreadView - -session.MessgageInput - - - -var w = new session.mail.ThreadView(this); - -w.appendTo($("div.wall")); - - + + var mail = session.mail = {}; + + mail.Wall = session.web.Widget.extend({ + init: function(parent) { + }, + start: function() { +// this.$element + }, + }); + + mail.ThreadView = session.web.Widget.extend({ + template: 'MailTest', + + init: function(parent) { + }, + + start: function() { +// this.$element + }, + }); + + mail.MessgageInput = session.web.Widget.extend({ + }); + + + var tv = new mail.ThreadView(this); +// tv.appendTo($("div.wall")); +// tv.appendTo($("body")); + }; + // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml new file mode 100644 index 00000000000..005b4b23a79 --- /dev/null +++ b/addons/mail/static/src/xml/mail.xml @@ -0,0 +1,17 @@ + + \ No newline at end of file From babb03a00fcf01534c3b8bde56710c3799c6af2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 3 Feb 2012 09:48:25 +0100 Subject: [PATCH 015/133] First draft of javascript work for threadview bzr revid: tde@openerp.com-20120203084825-nyskuc8kxlljox0z --- addons/crm/crm_lead_view.xml | 43 +++++++++++++++++-------------- addons/mail/mail_thread.py | 1 + addons/mail/mail_thread_view.xml | 1 + addons/mail/static/src/js/mail.js | 5 ++-- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 44d83f47634..6218d00f044 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -547,27 +547,30 @@ - + - - - - - -
- +
@@ -25,12 +25,14 @@
-
+
Image
-
-
-
- +
+

+
+
+ +

From b6739df2973dd7743a38165ce6e69c217b50d9ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 7 Feb 2012 11:16:57 +0100 Subject: [PATCH 025/133] Tmp action button add for res_log testing purpose bzr revid: tde@openerp.com-20120207101657-phoxiwpa5q4g35sk --- addons/mail/mail_group.py | 11 +++++++---- addons/mail/mail_group_view.xml | 3 +++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index ff634e58d70..50141bf27a0 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -49,11 +49,14 @@ class mail_group(osv.osv): return True - def action_follow(self, cr, uid, ids, context={}): - return self.message_subscribe(cr, uid, ids, context=context) + def action_test(self, cr, uid, ids, context={}): + for o in self.browse(cr, uid, ids): + message = _('You are doing things with the group %s, wooooh !') % (o.name,) + self.log(cr, uid, o.id, message) + return True - def action_unfollow(self, cr, uid, ids, context={}): - return self.message_unsubscribe(cr, uid, ids, context=context) + def action_null(self, cr, uid, ids, context={}): + return True _columns = { #'group_id': fields.many2one('res.groups', required=True, ondelete='cascade', diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index ff489b09734..7ec4e26b25b 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -103,6 +103,9 @@
-
-

- 00000000 - 11111111 - 00000000 - 11111111 - 00000000 - 11111111 - 00000000 - 11111111 -

-
+ + zmeofizepofinzepfoiznepfoizpfozeinfpzoeinfpoznf zfe zef zef ze fz efz efz ef zef ze fz efznf zfe zef zef ze fz efz efz ef zef ze fz efznf zfe zef zef ze fz efz efz ef zef ze fz ef +
Image

-
-
- + zmeofizepofinzepfoiznepfoizpfozeinfpzoeinfpoznf zfe zef zef ze fz efz efz ef zef ze fz efznf zfe zef zef ze fz efz efz ef zef ze fz efznf zfe zef zef ze fz efz efz ef zef ze fz ef + + + +

From cff98a3aeb4b2308d00dc4b91b283ab79e322c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 8 Feb 2012 16:25:21 +0100 Subject: [PATCH 027/133] [IMP] Improved ThreadView widget display; cleaned ThreadView widget js code; added basic access rules; added message_mark_done method to clean a mail.thread of its need_action_user_id; added auto-push of notifications if user requested to perform an action is not following the object; added first draft of messaging mechanism in hr_holidays bzr revid: tde@openerp.com-20120208152521-68i4nekjj8mnuyc8 --- addons/hr_holidays/hr_holidays.py | 21 ++++++++++- addons/hr_holidays/hr_holidays_view.xml | 1 + addons/mail/mail_group.py | 6 --- addons/mail/mail_group_view.xml | 12 ------ addons/mail/mail_message.py | 10 ++++- addons/mail/mail_thread.py | 17 ++++++--- addons/mail/mail_thread_view.xml | 10 +++++ addons/mail/security/ir.model.access.csv | 2 + addons/mail/static/src/css/mail.css | 47 ++++++++++++++++-------- addons/mail/static/src/js/mail.js | 38 +++++++------------ addons/mail/static/src/xml/mail.xml | 44 ++++++++++++---------- 11 files changed, 123 insertions(+), 85 deletions(-) diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py index 3bb7a8e4982..2ddb6e87a3a 100644 --- a/addons/hr_holidays/hr_holidays.py +++ b/addons/hr_holidays/hr_holidays.py @@ -93,6 +93,7 @@ class hr_holidays(osv.osv): _name = "hr.holidays" _description = "Leave" _order = "type desc, date_from asc" + _inherit = ['mail.thread'] def _employee_get(self, cr, uid, context=None): ids = self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)], context=context) @@ -250,8 +251,16 @@ class hr_holidays(osv.osv): obj_emp = self.pool.get('hr.employee') ids2 = obj_emp.search(cr, uid, [('user_id', '=', uid)]) manager = ids2 and ids2[0] or False + self.holidays_validate_notificate(cr, uid, ids, context=context) return self.write(cr, uid, ids, {'state':'validate1', 'manager_id': manager}) + def holidays_validate_notificate(self, cr, uid, ids, context=None): + for obj in self.browse(cr, uid, ids): + self.message_mark_done(cr, uid, [obj.id], context=context) + self.message_append_note(cr, uid, [obj.id], 'System notification', _("The %s request '%s' has been validated.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) + if obj.holiday_status_id.double_validation: + self.message_append_note(cr, uid, [obj.id], 'System notification', _("The %s request '%s' is waiting for second validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) + def holidays_validate2(self, cr, uid, ids, context=None): self.check_holidays(cr, uid, ids, context=context) obj_emp = self.pool.get('hr.employee') @@ -301,13 +310,23 @@ class hr_holidays(osv.osv): wf_service.trg_validate(uid, 'hr.holidays', leave_id, 'validate', cr) wf_service.trg_validate(uid, 'hr.holidays', leave_id, 'second_validate', cr) if holiday_ids: + self.holidays_valid2_notificate(self, cr, uid, [holiday_ids], context=context) self.write(cr, uid, holiday_ids, {'manager_id2': manager}) return True + + def holidays_valid2_notificate(self, cr, uid, ids, context=None): + for obj in self.browse(cr, uid, ids): + self.message_append_note(cr, uid, [obj.id], 'System notification', _("The %s request '%s' has been double validated.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) def holidays_confirm(self, cr, uid, ids, context=None): self.check_holidays(cr, uid, ids, context=context) + self.holidays_confirm_notificate(cr, uid, ids, context=context) return self.write(cr, uid, ids, {'state':'confirm'}) - + + def holidays_confirm_notificate(self, cr, uid, ids, context=None): + for obj in self.browse(cr, uid, ids): + self.message_append_note(cr, uid, [obj.id], 'System notification', _("The %s request '%s' has been confirmed and is waiting for validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', need_action_user_id=obj.employee_id.parent_id.user_id.id) + def holidays_refuse(self, cr, uid, ids, approval, context=None): obj_emp = self.pool.get('hr.employee') ids2 = obj_emp.search(cr, uid, [('user_id', '=', uid)]) diff --git a/addons/hr_holidays/hr_holidays_view.xml b/addons/hr_holidays/hr_holidays_view.xml index 22d4d6e567d..2096ae2bc61 100644 --- a/addons/hr_holidays/hr_holidays_view.xml +++ b/addons/hr_holidays/hr_holidays_view.xml @@ -95,6 +95,7 @@ +
+
+
\ No newline at end of file From 9efc4714f26757a127861119e549f7718af3e136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 9 Feb 2012 11:04:47 +0100 Subject: [PATCH 030/133] [IMP] Wall: added parameters passing (filtering, message number to display, ..). Added My Wall (all feeds versus my feeds). bzr revid: tde@openerp.com-20120209100447-p8csuqq85jsexrdn --- addons/hr_holidays/hr_holidays.py | 8 ++++---- addons/mail/mail_message.py | 2 +- addons/mail/mail_message_view.xml | 7 +++++++ addons/mail/mail_thread_view.xml | 19 ++++++++++++++----- addons/mail/static/src/js/mail.js | 9 ++++++--- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py index 2ddb6e87a3a..8fd91c30581 100644 --- a/addons/hr_holidays/hr_holidays.py +++ b/addons/hr_holidays/hr_holidays.py @@ -257,9 +257,9 @@ class hr_holidays(osv.osv): def holidays_validate_notificate(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids): self.message_mark_done(cr, uid, [obj.id], context=context) - self.message_append_note(cr, uid, [obj.id], 'System notification', _("The %s request '%s' has been validated.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) + self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' has been validated.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) if obj.holiday_status_id.double_validation: - self.message_append_note(cr, uid, [obj.id], 'System notification', _("The %s request '%s' is waiting for second validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) + self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' is waiting for second validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) def holidays_validate2(self, cr, uid, ids, context=None): self.check_holidays(cr, uid, ids, context=context) @@ -316,7 +316,7 @@ class hr_holidays(osv.osv): def holidays_valid2_notificate(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids): - self.message_append_note(cr, uid, [obj.id], 'System notification', _("The %s request '%s' has been double validated.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) + self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' has been double validated.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) def holidays_confirm(self, cr, uid, ids, context=None): self.check_holidays(cr, uid, ids, context=context) @@ -325,7 +325,7 @@ class hr_holidays(osv.osv): def holidays_confirm_notificate(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids): - self.message_append_note(cr, uid, [obj.id], 'System notification', _("The %s request '%s' has been confirmed and is waiting for validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', need_action_user_id=obj.employee_id.parent_id.user_id.id) + self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' has been confirmed and is waiting for validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', need_action_user_id=obj.employee_id.parent_id.user_id.id) def holidays_refuse(self, cr, uid, ids, approval, context=None): obj_emp = self.pool.get('hr.employee') diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 2ecdad5ceca..28e02401244 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -216,7 +216,7 @@ class mail_message(osv.osv): notification_obj.create(cr, uid, {'user_id': vals['need_action_user_id'], 'message_id': msg_id}, context=context) return msg_id - def get_pushed_messages(self, cr, uid, context=None): + def get_pushed_messages(self, cr, uid, ids, filter_search=False, context=None): """Wall: get messages to display""" notification_obj = self.pool.get('mail.notification') notification_ids = notification_obj.search(cr, uid, [('user_id', '=', uid)], context=context) diff --git a/addons/mail/mail_message_view.xml b/addons/mail/mail_message_view.xml index 4ccf7d44323..0036897d411 100644 --- a/addons/mail/mail_message_view.xml +++ b/addons/mail/mail_message_view.xml @@ -230,6 +230,13 @@ (w)All Feeds mail.all_feeds + + + + + My Feeds + mail.all_feeds +
diff --git a/addons/mail/mail_thread_view.xml b/addons/mail/mail_thread_view.xml index 7bd503b0546..d2e557d06d8 100644 --- a/addons/mail/mail_thread_view.xml +++ b/addons/mail/mail_thread_view.xml @@ -51,26 +51,35 @@
- + + Feeds + + + + - - - + + My Feeds + + + + (w)All Feeds - + + diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index bd82399b88e..747276121fa 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -95,8 +95,9 @@ openerp.mail = function(session) { // QWeb template to use when rendering the object template: 'WallView', - init: function() { - this._super.apply(this, arguments); + init: function (parent, params) { + this._super(parent); + this.filter_search = params['filter_search']; /* DataSets */ this.ds_msg = new session.web.DataSet(this, 'mail.message'); }, @@ -104,8 +105,9 @@ openerp.mail = function(session) { start: function() { var self = this; this._super.apply(this, arguments); + console.log(this); self.$element.find('button.oe_mail_action_comment').bind('click', function () { self.do_comment(); }); - this.ds_msg.call('get_pushed_messages', []).then( + this.ds_msg.call('get_pushed_messages', [[], self.filter_search]).then( this.proxy('display_records')); }, @@ -114,6 +116,7 @@ openerp.mail = function(session) { }, fetch_messages: function () { + console.log('debug--fetch_messages'); return this.ds_msg.call('get_pushed_messages', []).then( this.proxy('display_records')); }, From 1d09919c1810c575d3c2bd74ef76b54ceca44d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Feb 2012 10:53:48 +0100 Subject: [PATCH 031/133] [FIX] Fixed bug with message dict not necessarily containing a 'type' entry bzr revid: tde@openerp.com-20120210095348-z8m7gqpse6hw9byr --- addons/mail/mail_message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 28e02401244..58e5833fa49 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -198,7 +198,7 @@ class mail_message(osv.osv): def create(self, cr, uid, vals, context=None): # OpenSocial: notifications do not come from any user but from system - if vals['type'] == 'notification': vals['user_id'] = False + if vals.get('type') == 'notification': vals['user_id'] = False need_action_pushed = False msg_id = super(mail_message, self).create(cr, uid, vals, context) # push the message to suscribed users From 62a33c175a16471db9e9b2ad5555beaca27ddd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Feb 2012 11:25:37 +0100 Subject: [PATCH 032/133] [FIX] Fixed crash when assigning need_action_user_id to unexistent manager_id for holidays validation bzr revid: tde@openerp.com-20120210102537-rrvk58ttasnfmoqq --- addons/hr_holidays/hr_holidays.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py index 8fd91c30581..a2acea4792d 100644 --- a/addons/hr_holidays/hr_holidays.py +++ b/addons/hr_holidays/hr_holidays.py @@ -325,7 +325,7 @@ class hr_holidays(osv.osv): def holidays_confirm_notificate(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids): - self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' has been confirmed and is waiting for validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', need_action_user_id=obj.employee_id.parent_id.user_id.id) + self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' has been confirmed and is waiting for validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', need_action_user_id = obj.employee_id.parent_id.user_id.id if obj.employee_id.parent_id else False) def holidays_refuse(self, cr, uid, ids, approval, context=None): obj_emp = self.pool.get('hr.employee') From 5042ba24658d48ffbd500484b6e01c0712f0ada5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Feb 2012 11:52:23 +0100 Subject: [PATCH 033/133] [IMP] Cleaned xml, css and js for ThreadView. bzr revid: tde@openerp.com-20120210105223-fv24nic79ycldc2i --- addons/mail/static/src/css/mail.css | 75 ++++++++++++++++++++++------- addons/mail/static/src/js/mail.js | 26 +++++----- addons/mail/static/src/xml/mail.xml | 33 ++++++++----- 3 files changed, 93 insertions(+), 41 deletions(-) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 906bdbff6cf..baf7a98d71f 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -1,43 +1,74 @@ /** ThreadView widget **/ .oe_mail_main { + overflow: auto; + padding: 5px 5px 5px 5px; } +/* 2 columns view */ +.oe_mail_main_left { + float: left; + width: 65%; +} + +.oe_mail_main_right { + float: right; + width: 34%; +} + +/* Left-side CSS */ .oe_mail_actions { - padding-bottom: 10px; + margin-bottom: 10px; } .oe_mail_post_comment { - width: 65%; - padding-bottom: 10px; + margin-bottom: 10px; } -.oe_mail_comments { - width: 65%; +.oe_mail_button_follow, .oe_mail_button_unfollow, .oe_mail_button_getfollowers, .oe_mail_button_hidefollowers { + width: 100px; +} + +.oe_mail_button_comment { + width: 150px; +} + +.oe_mail_action_textarea { + width: 60%; + height: 50px; + padding: 5px; +} + +.oe_mail_action_comment { } .oe_mail_msg { - width: 65%; -/* border: 1px solid #998877; */ - padding: 10px 0px 10px 0px; } -.oe_mail_msg:after { +/*.oe_mail_msg:after { content: ""; display: block; clear: both; +}*/ + +.oe_mail_comment { + white-space: normal; + margin-bottom: 5px; } .oe_mail_msg_image { float: left; - width: 9%; + width: 14%; +} + +.oe_mail_msg_image img { + width: 80%; + margin-left: 10%; } .oe_mail_msg_content { - width: 89%; - margin-left: 10%; -/* border: 1px solid #557722; */ - overflow: hidden; + width: 85%; + margin-left: 15%; } .oe_mail_msg_p { @@ -48,14 +79,24 @@ .oe_mail_msg_body { } -.oe_mail_msg_author { +.oe_mail_msg_author, .oe_mail_msg_author a { color: #4E43E7; } -.oe_mail_msg_need_action { +.oe_mail_msg_need_action, .oe_mail_msg_need_action a { color: #C03000; } -.oe_mail_msg_date { +.oe_mail_msg_date, .oe_mail_msg_date a { color: #4E43E7; } + +/* Right-side CSS */ +.oe_mail_followers_vignette { + float: left; + width: 20%%; +} + +.oe_mail_followers_vignette img { + width: 80%; +} diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 747276121fa..93a333335a8 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -27,15 +27,15 @@ openerp.mail = function(session) { var self = this; this._super.apply(this, arguments); /* bind follow and unfollow buttons */ - self.$element.find('button.oe_mail_action_follow').bind('click', function () { self.do_follow(); }); - self.$element.find('button.oe_mail_action_follow').hide(); - self.$element.find('button.oe_mail_action_unfollow').bind('click', function () { self.do_unfollow(); }); - self.$element.find('button.oe_mail_action_unfollow').hide(); - self.$element.find('button.oe_mail_action_comment').bind('click', function () { self.do_comment(); }); + self.$element.find('button.oe_mail_button_follow').bind('click', function () { self.do_follow(); }); + self.$element.find('button.oe_mail_button_follow').hide(); + self.$element.find('button.oe_mail_button_unfollow').bind('click', function () { self.do_unfollow(); }); + self.$element.find('button.oe_mail_button_unfollow').hide(); + self.$element.find('button.oe_mail_button_comment').bind('click', function () { self.do_comment(); }); /* find wich (un)follow buttons to show */ var call_res = this.ds.call('message_is_subscriber', [[this.session.uid]]).then(function (records) { - if (records == true) { self.follow_state = 1; self.$element.find('button.oe_mail_action_unfollow').show(); } - else { self.follow_state = 0; self.$element.find('button.oe_mail_action_follow').show(); } + if (records == true) { self.follow_state = 1; self.$element.find('button.oe_mail_button_unfollow').show(); } + else { self.follow_state = 0; self.$element.find('button.oe_mail_button_follow').show(); } }); }, @@ -56,27 +56,27 @@ openerp.mail = function(session) { }, display_records: function (records) { - this.$element.find('div.oe_mail_comments').empty(); + this.$element.find('div.oe_mail_msg').empty(); var self = this; _(records).each(function (record) { var template = 'ThreadMsgView'; var render_res = session.web.qweb.render(template, { 'record': record, }); - $('
').html(render_res).appendTo(self.$element.find('div.oe_mail_comments')); + $('
').html(render_res).appendTo(self.$element.find('div.oe_mail_msg')); }); // this.timeout = setTimeout(this.proxy('fetch_messages'), 5000); }, do_follow: function () { - this.$element.find('button.oe_mail_action_unfollow').show(); - this.$element.find('button.oe_mail_action_follow').hide(); + this.$element.find('button.oe_mail_button_unfollow').show(); + this.$element.find('button.oe_mail_button_follow').hide(); return this.ds_sub.create({'res_model': this.view.model, 'user_id': this.session.uid, 'res_id': this.view.datarecord.id}).then(); }, do_unfollow: function () { - this.$element.find('button.oe_mail_action_follow').show(); - this.$element.find('button.oe_mail_action_unfollow').hide(); + this.$element.find('button.oe_mail_button_follow').show(); + this.$element.find('button.oe_mail_button_unfollow').hide(); return this.ds.call('message_unsubscribe', [[this.view.datarecord.id]]).then(); }, diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 58e242829b6..72fbf8d0f88 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -3,17 +3,28 @@
OpenSocial
-
- - +
+
+ + +
+
+
+ +
+
+
+
+
-
-
- -
-
+
+ + +
+
+
Image
@@ -23,15 +34,15 @@ OpenERP System Notification
- + - - Need action + - Need action by

- +

From 628989451d3f4ceab62dfdfce110d126b8f0b96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Feb 2012 13:42:53 +0100 Subject: [PATCH 034/133] [IMP] Changed mail.subscription.user_id field from integer to many2one bzr revid: tde@openerp.com-20120210124253-mx7vgxhmzpfant62 --- addons/mail/mail_subscription.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/mail/mail_subscription.py b/addons/mail/mail_subscription.py index c5b5407190b..eaf53bc1c17 100644 --- a/addons/mail/mail_subscription.py +++ b/addons/mail/mail_subscription.py @@ -39,7 +39,8 @@ class mail_subscription(osv.osv): select=1, required=True), 'res_id': fields.integer('Related Document ID', select=1), #'res_domain': fields.char('res_domain', size=256), - 'user_id': fields.integer('Related User ID', select=1, required=True), + 'user_id': fields.many2one('res.users', string='Related User ID', + ondelete='cascade', required=True, select=1), } _defaults = { } From a123480d2c123f011265eff253d787cca27fb57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 10 Feb 2012 13:43:48 +0100 Subject: [PATCH 035/133] [IMP] Added a 'get followers' button on ThreadWidget. Basic displaying of results added. bzr revid: tde@openerp.com-20120210124348-8s73xmswnfypqhx6 --- addons/mail/mail_thread.py | 7 +++++++ addons/mail/static/src/css/mail.css | 2 +- addons/mail/static/src/js/mail.js | 28 +++++++++++++++++++++++----- addons/mail/static/src/xml/mail.xml | 10 +++++----- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index f582bc50062..68bf4429d18 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -543,6 +543,13 @@ class mail_thread(osv.osv): subs = subscription_obj.browse(cr, uid, sub_ids, context=context) return subs + def message_get_subscribers_web(self, cr, uid, ids, context=None): + subscription_obj = self.pool.get('mail.subscription') + for id in ids: + sub_ids = subscription_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', '=', id)], context=context) + subs = subscription_obj.read(cr, uid, sub_ids, context=context) + return subs + def message_is_subscriber(self, cr, uid, ids, context=None): for subscription in self.message_get_subscribers(cr, uid, ids, context=context): if subscription.user_id == uid: return True diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index baf7a98d71f..0d153ce0c06 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -25,7 +25,7 @@ margin-bottom: 10px; } -.oe_mail_button_follow, .oe_mail_button_unfollow, .oe_mail_button_getfollowers, .oe_mail_button_hidefollowers { +.oe_mail_button_follow, .oe_mail_button_unfollow, .oe_mail_button_followers { width: 100px; } diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 93a333335a8..fa7037bcacb 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -32,6 +32,7 @@ openerp.mail = function(session) { self.$element.find('button.oe_mail_button_unfollow').bind('click', function () { self.do_unfollow(); }); self.$element.find('button.oe_mail_button_unfollow').hide(); self.$element.find('button.oe_mail_button_comment').bind('click', function () { self.do_comment(); }); + self.$element.find('button.oe_mail_button_followers').bind('click', function () { self.do_toggle_followers(); }); /* find wich (un)follow buttons to show */ var call_res = this.ds.call('message_is_subscriber', [[this.session.uid]]).then(function (records) { if (records == true) { self.follow_state = 1; self.$element.find('button.oe_mail_button_unfollow').show(); } @@ -47,15 +48,18 @@ openerp.mail = function(session) { set_value: function() { this._super.apply(this, arguments); if (! this.view.datarecord.id) { return; } - return this.fetch_messages(); + return this.fetch_data(); }, - fetch_messages: function () { - return this.ds.call('message_load', [[this.view.datarecord.id]]).then( - this.proxy('display_records')); + fetch_data: function () { + var load_res = this.ds.call('message_load', [[this.view.datarecord.id]]).then( + this.proxy('display_comments')); + var follow_res = this.ds.call('message_get_subscribers_web', [[this.view.datarecord.id]]).then( + this.proxy('display_followers')); + return follow_res; }, - display_records: function (records) { + display_comments: function (records) { this.$element.find('div.oe_mail_msg').empty(); var self = this; _(records).each(function (record) { @@ -68,6 +72,16 @@ openerp.mail = function(session) { // this.timeout = setTimeout(this.proxy('fetch_messages'), 5000); }, + display_followers: function (records) { + this.$element.find('div.oe_mail_followers').empty(); + var self = this; + _(records).each(function (record) { + console.log(record); +//
+ $('
').text(record.user_id[1]).appendTo(self.$element.find('div.oe_mail_followers')); + }); + }, + do_follow: function () { this.$element.find('button.oe_mail_button_unfollow').show(); this.$element.find('button.oe_mail_button_follow').hide(); @@ -85,6 +99,10 @@ openerp.mail = function(session) { return this.ds.call('message_append_note', [[this.view.datarecord.id], 'Reply comment', body_text, type='comment']).then( this.proxy('fetch_messages')); }, + + do_toggle_followers: function () { + this.$element.find('div.oe_mail_followers').toggle(); + }, }); /* Add WallView widget to registry */ diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 72fbf8d0f88..ff8386f32b9 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -18,13 +18,13 @@
- - -
-
+
+ +
+
+
-
Image
From fcbd3d26dca82b0c265abd45504b083e54f9ad9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 16 Feb 2012 14:34:44 +0100 Subject: [PATCH 036/133] [IMP] hr: added parent_id in demo data for employees, allowing to test the need_action_user_id feature with hr.holidays with demo data bzr revid: tde@openerp.com-20120216133444-byv4m8vkh8g68uoe --- addons/hr/hr_demo.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/addons/hr/hr_demo.xml b/addons/hr/hr_demo.xml index b6a11f0b111..00b2ab325e4 100644 --- a/addons/hr/hr_demo.xml +++ b/addons/hr/hr_demo.xml @@ -165,6 +165,7 @@ Fabien Pinckaers + Grand-Rosière @@ -177,6 +178,7 @@ Antony Lesuisse + Grand-Rosière @@ -189,6 +191,7 @@ Minh Tran + Grand-Rosière @@ -202,6 +205,7 @@ Nicolas Vanhoren + Grand-Rosière @@ -214,6 +218,7 @@ Stéphane Wirtel + Grand-Rosière @@ -226,6 +231,7 @@ Christophe Simonis + Grand-Rosière @@ -238,6 +244,7 @@ Quentin De Paoli + Grand-Rosière @@ -249,6 +256,7 @@ Fabien Meghazi + Grand-Rosière @@ -260,6 +268,7 @@ Francois Pietquin + Grand-Rosière @@ -272,6 +281,7 @@ Julien Thewys + Grand-Rosière @@ -296,6 +306,7 @@ Valérie Descamps + Grand-Rosière From 8e14b6a70661dc367e20357afb3550bf12798465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 16 Feb 2012 14:43:19 +0100 Subject: [PATCH 037/133] [FIX] hr: updated demo data for employee_fp referencing itself as manager bzr revid: tde@openerp.com-20120216134319-8r8ty5h3wbnrkd35 --- addons/hr/hr_demo.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/hr/hr_demo.xml b/addons/hr/hr_demo.xml index 00b2ab325e4..f82e2dac39e 100644 --- a/addons/hr/hr_demo.xml +++ b/addons/hr/hr_demo.xml @@ -165,7 +165,6 @@ Fabien Pinckaers - Grand-Rosière @@ -174,6 +173,10 @@ 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 + + + + Antony Lesuisse From 67bb1396605c4e145cfd8b0c397a4232e5626de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 16 Feb 2012 17:03:02 +0100 Subject: [PATCH 038/133] [REF] mail.thread: fixed an error in is_subscriber, cleaned code; mail.js: threadview widget: cleaned code bzr revid: tde@openerp.com-20120216160302-g5knaca3vie1ekot --- addons/mail/mail_thread.py | 53 ++++++++++-------------- addons/mail/static/src/js/mail.js | 62 +++++++++++++++++------------ addons/mail/static/src/xml/mail.xml | 2 +- 3 files changed, 59 insertions(+), 58 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 68bf4429d18..f63ebde836c 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -241,23 +241,19 @@ class mail_thread(osv.osv): # Message loading def message_load_ids(self, cr, uid, ids, context=None): - """ OpenSocial feature added this method - get ids of thread messages + """ OpenSocial feature: return thread messages ids (for web compatibility) + loading messages: search in mail.messages where res_id = ids, (res_)model = current model """ msg_obj = self.pool.get('mail.message') - msg_ids = [msg_obj.search(cr, uid, ['&', ('res_id', '=', id), ('model', '=', self._name)], context=context) for id in ids] - return msg_ids[0] + msg_ids = msg_obj.search(cr, uid, ['&', ('res_id', 'in', ids), ('model', '=', self._name)], context=context) + return msg_ids def message_load(self, cr, uid, ids, context=None): - """ OpenSocial feature added this method - loading message: search in mail.messages where res_id = ids, (res_)model = current model + """ OpenSocial feature: return thread messages + loading messages: search in mail.messages where res_id = ids, (res_)model = current model """ - msg_ids = [] - msg_obj = self.pool.get('mail.message') - for id in ids: - msg_ids += msg_obj.search(cr, uid, ['&', ('res_id', '=', id), ('model', '=', self._name)], context=context) - msgs = msg_obj.read(cr, uid, msg_ids, context=context) - return msgs + msg_ids = self.message_load_ids(cr, uid, ids, context=context) + return self.pool.get('mail.message').read(cr, uid, msg_ids, context=context) #------------------------------------------------------ # Email specific @@ -528,9 +524,10 @@ class mail_thread(osv.osv): Find by: res_id (thread id), model (self._name), need_action_user_id != false """ msg_obj = self.pool.get('mail.message') - for id in ids: - msg_ids = msg_obj.search(cr, uid, ['&', ('res_id', '=', id), ('model', '=', self._name)], context=context) - msg_obj.write(cr, uid, msg_ids, {'need_action_user_id': False}, context=context) + msg_ids = msg_obj.search(cr, uid, + ['&', '&', ('res_id', 'in', ids), ('model', '=', self._name), ('need_action_user_id', '!=', False)], context=context) + msg_obj.write(cr, uid, msg_ids, {'need_action_user_id': False}, context=context) + return True #------------------------------------------------------ # Subscription mechanism @@ -538,22 +535,17 @@ class mail_thread(osv.osv): def message_get_subscribers(self, cr, uid, ids, context=None): subscription_obj = self.pool.get('mail.subscription') - for id in ids: - sub_ids = subscription_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', '=', id)], context=context) - subs = subscription_obj.browse(cr, uid, sub_ids, context=context) - return subs - - def message_get_subscribers_web(self, cr, uid, ids, context=None): - subscription_obj = self.pool.get('mail.subscription') - for id in ids: - sub_ids = subscription_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', '=', id)], context=context) - subs = subscription_obj.read(cr, uid, sub_ids, context=context) + sub_ids = subscription_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', 'in', ids)], context=context) + subs = subscription_obj.read(cr, uid, sub_ids, context=context) return subs def message_is_subscriber(self, cr, uid, ids, context=None): - for subscription in self.message_get_subscribers(cr, uid, ids, context=context): - if subscription.user_id == uid: return True - return False + subscription_obj = self.pool.get('mail.subscription') + sub_ids = subscription_obj.search(cr, uid, + ['&', '&', ('res_model', '=', self._name), ('res_id', 'in', ids), ('user_id', '=', uid)], context=context) + if len(sub_ids) > 1: + print 'cacaprout error !' + return True if sub_ids else False def message_subscribe(self, cr, uid, ids, context=None): subscription_obj = self.pool.get('mail.subscription') @@ -565,9 +557,8 @@ class mail_thread(osv.osv): def message_unsubscribe(self, cr, uid, ids, context=None): subscription_obj = self.pool.get('mail.subscription') subscriber_id = uid # TODO - sub_ids = [] - for id in ids: - sub_ids += subscription_obj.search(cr, uid, ['&', '&', ('res_model', '=', self._name), ('res_id', '=', id), ('user_id', '=', subscriber_id)], context=context) + sub_ids = subscription_obj.search(cr, uid, + ['&', '&', ('res_model', '=', self._name), ('res_id', 'in', ids), ('user_id', '=', subscriber_id)], context=context) subscription_obj.unlink(cr, uid, sub_ids, context=context) return True diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index fa7037bcacb..aa1ed33fb6d 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -14,47 +14,55 @@ openerp.mail = function(session) { template: 'ThreadView', init: function() { -// this.timeout; this.follow_state = 0; this._super.apply(this, arguments); /* DataSets */ this.ds = new session.web.DataSet(this, this.view.model); - this.ds_sub = new session.web.DataSet(this, 'mail.subscription'); -// this.ds_msg = new session.web.DataSet(this, 'mail.message'); }, start: function() { var self = this; this._super.apply(this, arguments); - /* bind follow and unfollow buttons */ - self.$element.find('button.oe_mail_button_follow').bind('click', function () { self.do_follow(); }); - self.$element.find('button.oe_mail_button_follow').hide(); - self.$element.find('button.oe_mail_button_unfollow').bind('click', function () { self.do_unfollow(); }); - self.$element.find('button.oe_mail_button_unfollow').hide(); + /* bind buttons */ self.$element.find('button.oe_mail_button_comment').bind('click', function () { self.do_comment(); }); self.$element.find('button.oe_mail_button_followers').bind('click', function () { self.do_toggle_followers(); }); - /* find wich (un)follow buttons to show */ - var call_res = this.ds.call('message_is_subscriber', [[this.session.uid]]).then(function (records) { - if (records == true) { self.follow_state = 1; self.$element.find('button.oe_mail_button_unfollow').show(); } - else { self.follow_state = 0; self.$element.find('button.oe_mail_button_follow').show(); } - }); + self.$element.find('button.oe_mail_button_follow').bind('click', function () { self.do_follow(); }); + self.$element.find('button.oe_mail_button_unfollow').bind('click', function () { self.do_unfollow(); }); + /* hide follow/unfollow buttons */ + self.$element.find('button.oe_mail_button_follow').hide(); + self.$element.find('button.oe_mail_button_unfollow').hide(); }, stop: function () { -// clearTimeout(this.timeout); - this._super(); + console.log('stop'); + this._super.apply(this, arguments); }, set_value: function() { + var self = this; this._super.apply(this, arguments); + /* hide follow/unfollow buttons */ + self.$element.find('button.oe_mail_button_follow').hide(); + self.$element.find('button.oe_mail_button_unfollow').hide(); if (! this.view.datarecord.id) { return; } - return this.fetch_data(); + /* find wich (un)follow buttons to show */ + var call_res = this.ds.call('message_is_subscriber', [[this.view.datarecord.id]]).then(function (records) { + if (records == true) { self.follow_state = 1; self.$element.find('button.oe_mail_button_unfollow').show(); } + else { self.follow_state = 0; self.$element.find('button.oe_mail_button_follow').show(); } + }); + /* fetch comments and subscribers */ + this.fetch_subscribers(); + return this.fetch_comments(); }, - fetch_data: function () { + fetch_comments: function () { var load_res = this.ds.call('message_load', [[this.view.datarecord.id]]).then( this.proxy('display_comments')); - var follow_res = this.ds.call('message_get_subscribers_web', [[this.view.datarecord.id]]).then( + return load_res; + }, + + fetch_subscribers: function () { + var follow_res = this.ds.call('message_get_subscribers', [[this.view.datarecord.id]]).then( this.proxy('display_followers')); return follow_res; }, @@ -69,35 +77,37 @@ openerp.mail = function(session) { }); $('
').html(render_res).appendTo(self.$element.find('div.oe_mail_msg')); }); -// this.timeout = setTimeout(this.proxy('fetch_messages'), 5000); }, display_followers: function (records) { this.$element.find('div.oe_mail_followers').empty(); var self = this; _(records).each(function (record) { - console.log(record); //
$('
').text(record.user_id[1]).appendTo(self.$element.find('div.oe_mail_followers')); }); }, do_follow: function () { - this.$element.find('button.oe_mail_button_unfollow').show(); - this.$element.find('button.oe_mail_button_follow').hide(); - return this.ds_sub.create({'res_model': this.view.model, 'user_id': this.session.uid, 'res_id': this.view.datarecord.id}).then(); + this.do_toggle_follow(); + return this.ds.call('message_subscribe', [[this.view.datarecord.id]]).then(); }, do_unfollow: function () { - this.$element.find('button.oe_mail_button_follow').show(); - this.$element.find('button.oe_mail_button_unfollow').hide(); + this.do_toggle_follow(); return this.ds.call('message_unsubscribe', [[this.view.datarecord.id]]).then(); }, do_comment: function () { var body_text = this.$element.find('textarea').val(); return this.ds.call('message_append_note', [[this.view.datarecord.id], 'Reply comment', body_text, type='comment']).then( - this.proxy('fetch_messages')); + this.proxy('fetch_comments')); + }, + + do_toggle_follow: function () { + this.follow_state = 1 - this.follow_state; + this.$element.find('button.oe_mail_button_unfollow').toggle(); + this.$element.find('button.oe_mail_button_follow').toggle(); }, do_toggle_followers: function () { diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index ff8386f32b9..50e73f10326 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -56,4 +56,4 @@
- \ No newline at end of file + From 64164155d23453a7087dd0740da1783e6332300b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 16 Feb 2012 17:48:37 +0100 Subject: [PATCH 039/133] [FIX] mail_message: fixed notification creation, propagating a subscription model modification (from int to many2one); fixed unprotected accesses to 'need_action_user_id' key in vals dictionnary bzr revid: tde@openerp.com-20120216164837-jscxxu52sybvy7db --- addons/mail/mail_message.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 58e5833fa49..9ada617a177 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -209,10 +209,10 @@ class mail_message(osv.osv): ('res_id', '=', vals['res_id'])], context=context) subs = subscription_obj.browse(cr, uid, sub_ids, context=context) for sub in subs: - notification_obj.create(cr, uid, {'user_id': sub.user_id, 'message_id': msg_id}, context=context) - if vals['need_action_user_id'] == sub.user_id: need_action_pushed = True + notification_obj.create(cr, uid, {'user_id': sub.user_id.id, 'message_id': msg_id}, context=context) + if vals.get('need_action_user_id', False) == sub.user_id: need_action_pushed = True # push to need_action_user_id if user does not follow the object - if vals['need_action_user_id'] != False and not need_action_pushed: + if vals.get('need_action_user_id', False) and not need_action_pushed: notification_obj.create(cr, uid, {'user_id': vals['need_action_user_id'], 'message_id': msg_id}, context=context) return msg_id From 12514823e69781fdf6509c7e07dda2f9d6d67311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 16 Feb 2012 18:04:46 +0100 Subject: [PATCH 040/133] [FIX] Cleaned create method for mail_message; added protection against unknown keys in vals parameter bzr revid: tde@openerp.com-20120216170446-h4u8t3znp7p4lerb --- addons/mail/mail_message.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 9ada617a177..03eb57bfd0f 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -204,15 +204,19 @@ class mail_message(osv.osv): # push the message to suscribed users subscription_obj = self.pool.get('mail.subscription') notification_obj = self.pool.get('mail.notification') + # not pure-email: check for subscriptions + if not 'need_action_user_id' in vals: vals['need_action_user_id'] = False + if not 'model' in vals: vals['model'] = False + if not 'res_id' in vals: vals['res_id'] = 0 sub_ids = subscription_obj.search(cr, uid, ['&', ('res_model', '=', vals['model']), ('res_id', '=', vals['res_id'])], context=context) subs = subscription_obj.browse(cr, uid, sub_ids, context=context) for sub in subs: notification_obj.create(cr, uid, {'user_id': sub.user_id.id, 'message_id': msg_id}, context=context) - if vals.get('need_action_user_id', False) == sub.user_id: need_action_pushed = True + if vals['need_action_user_id'] == sub.user_id: need_action_pushed = True # push to need_action_user_id if user does not follow the object - if vals.get('need_action_user_id', False) and not need_action_pushed: + if vals['need_action_user_id'] and not need_action_pushed: notification_obj.create(cr, uid, {'user_id': vals['need_action_user_id'], 'message_id': msg_id}, context=context) return msg_id From b23dd504c4d572fad8478f040a36b3571066f2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 20 Feb 2012 10:22:39 +0100 Subject: [PATCH 041/133] [FIX] Fixed template var name to match rev 2225 of web client bzr revid: tde@openerp.com-20120220092239-l1e35sv2l7qfzegx --- addons/mail/static/src/js/mail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index aa1ed33fb6d..ae98891eda9 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -11,7 +11,7 @@ openerp.mail = function(session) { /* ThreadView widget: thread of comments */ mail.ThreadView = session.web.form.Field.extend({ // QWeb template to use when rendering the object - template: 'ThreadView', + form_template: 'ThreadView', init: function() { this.follow_state = 0; From b8612374d7f4b202a1f5c092bc7bd695864848a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 20 Feb 2012 12:17:05 +0100 Subject: [PATCH 042/133] [IMP] crm_case: removed generic notification when changing state. Messages are now delegated to upper modules, that will have to write consistent and useful notifications. bzr revid: tde@openerp.com-20120220111705-4q7x3ukgvnz3vhe1 --- addons/crm/crm.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 4ebb0b4796d..7775e442df7 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -393,7 +393,6 @@ class crm_case(crm_base): def case_open(self, cr, uid, ids, *args): """Opens Case""" cases = self.browse(cr, uid, ids) - self.message_append(cr, uid, cases, _('Open')) for case in cases: data = {'state': 'open', 'active': True } if not case.user_id: @@ -406,7 +405,6 @@ class crm_case(crm_base): """Closes Case""" cases = self.browse(cr, uid, ids) cases[0].state # to fill the browse record cache - self.message_append(cr, uid, cases, _('Close')) self.write(cr, uid, ids, {'state': 'done', 'date_closed': time.strftime('%Y-%m-%d %H:%M:%S'), }) @@ -430,7 +428,6 @@ class crm_case(crm_base): raise osv.except_osv(_('Error !'), _('You can not escalate, you are already at the top level regarding your sales-team category.')) self.write(cr, uid, [case.id], data) cases = self.browse(cr, uid, ids) - self.message_append(cr, uid, cases, _('Escalate')) self._action(cr, uid, cases, 'escalate') return True @@ -438,7 +435,6 @@ class crm_case(crm_base): """Cancels Case""" cases = self.browse(cr, uid, ids) cases[0].state # to fill the browse record cache - self.message_append(cr, uid, cases, _('Cancel')) self.write(cr, uid, ids, {'state': 'cancel', 'active': True}) self._action(cr, uid, cases, 'cancel') @@ -451,7 +447,6 @@ class crm_case(crm_base): """Marks case as pending""" cases = self.browse(cr, uid, ids) cases[0].state # to fill the browse record cache - self.message_append(cr, uid, cases, _('Pending')) self.write(cr, uid, ids, {'state': 'pending', 'active': True}) self._action(cr, uid, cases, 'pending') return True @@ -463,7 +458,6 @@ class crm_case(crm_base): state = 'open' cases = self.browse(cr, uid, ids) cases[0].state # to fill the browse record cache - self.message_append(cr, uid, cases, _('Draft')) self.write(cr, uid, ids, {'state': state, 'active': True}) self._action(cr, uid, cases, state) return True From 674680484179c93d424461011ce4e1503747b369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 20 Feb 2012 17:11:57 +0100 Subject: [PATCH 043/133] [REF] mail_thread: deleted unused mail_thread views, now unecessary since content is not managed by a message_ids o2m field anymore bzr revid: tde@openerp.com-20120220161157-b9m23nq1czt4uoy3 --- addons/mail/mail_thread_view.xml | 60 -------------------------------- 1 file changed, 60 deletions(-) diff --git a/addons/mail/mail_thread_view.xml b/addons/mail/mail_thread_view.xml index d2e557d06d8..a71ae040328 100644 --- a/addons/mail/mail_thread_view.xml +++ b/addons/mail/mail_thread_view.xml @@ -1,62 +1,12 @@ - - mail.thread.form - mail.thread - form - -
- - - - - - - - - -
- - - mail.thread.tree - mail.thread - tree - - - - - - - - - - Email Threads - mail.thread - tree,form - form - - - - - tree - - - - - - form - - - Feeds - - @@ -83,16 +33,6 @@ - -
From 1469deff854c9bf0369ece9c7f639d2fe0257b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 20 Feb 2012 18:21:06 +0100 Subject: [PATCH 044/133] [IMP] mail_thread API: message_get_subscribers now returns res.users read results instead of mail.subscription results. message_subscribe has now an optional parameter user_ids to subscribe ids in user_ids instead of uid. bzr revid: tde@openerp.com-20120220172106-fpjafkkvea0m1k93 --- addons/mail/mail_thread.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index f63ebde836c..e0a42f3cfe7 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -533,11 +533,16 @@ class mail_thread(osv.osv): # Subscription mechanism #------------------------------------------------------ - def message_get_subscribers(self, cr, uid, ids, context=None): + def message_get_subscribers_ids(self, cr, uid, ids, context=None): subscription_obj = self.pool.get('mail.subscription') sub_ids = subscription_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', 'in', ids)], context=context) subs = subscription_obj.read(cr, uid, sub_ids, context=context) - return subs + return [sub['user_id'] for sub in subs] + + def message_get_subscribers(self, cr, uid, ids, context=None): + user_ids = self.message_get_subscribers_ids(cr, uid, ids, context=context) + users = self.pool.get('res.users').read(cr, uid, user_ids, context=context) + return users def message_is_subscriber(self, cr, uid, ids, context=None): subscription_obj = self.pool.get('mail.subscription') @@ -547,12 +552,13 @@ class mail_thread(osv.osv): print 'cacaprout error !' return True if sub_ids else False - def message_subscribe(self, cr, uid, ids, context=None): + def message_subscribe(self, cr, uid, ids, user_ids = None, context=None): subscription_obj = self.pool.get('mail.subscription') - subscriber_id = uid # TODO + sub_user_ids = [uid] if user_ids is None else user_ids for id in ids: - subscription_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': subscriber_id}, context=context) - return True + create_ids = [subscription_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': user_id}, context=context) + for user_id in sub_user_ids] + return create_ids def message_unsubscribe(self, cr, uid, ids, context=None): subscription_obj = self.pool.get('mail.subscription') From 3a53f777dfc5e3ce640f78d36acf94524e002d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 20 Feb 2012 18:22:30 +0100 Subject: [PATCH 045/133] [FIX] Propagated API modification: message_get_subscribers result are now read records from res.users bzr revid: tde@openerp.com-20120220172230-mj7vx5akh0xrmzs6 --- addons/mail/static/src/js/mail.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index ae98891eda9..b9404885b6a 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -84,7 +84,8 @@ openerp.mail = function(session) { var self = this; _(records).each(function (record) { //
- $('
').text(record.user_id[1]).appendTo(self.$element.find('div.oe_mail_followers')); + //$('
').text(record.user_id[1]).appendTo(self.$element.find('div.oe_mail_followers')); + $('
').text(record.name).appendTo(self.$element.find('div.oe_mail_followers')); }); }, From a2ef45aaebe2d75a7fb00c23276170bffbac3d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 20 Feb 2012 18:23:23 +0100 Subject: [PATCH 046/133] [IMP] hr_holidays: improved notifications, added notifications when creating or refusing a leave requet/allocation. bzr revid: tde@openerp.com-20120220172323-4kqkhxntcgx6g178 --- addons/hr_holidays/hr_holidays.py | 80 ++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py index a2acea4792d..a8573b9bf7c 100644 --- a/addons/hr_holidays/hr_holidays.py +++ b/addons/hr_holidays/hr_holidays.py @@ -151,7 +151,12 @@ class hr_holidays(osv.osv): ('date_check2', "CHECK ( (type='add') OR (date_from <= date_to))", "The start date must be before the end date !"), ('date_check', "CHECK ( number_of_days_temp >= 0 )", "The number of days must be greater than 0 !"), ] - + + def create(self, cr, uid, vals, context=None): + obj_id = super(hr_holidays, self).create(cr, uid, vals, context=context) + self.create_notificate(cr, uid, [obj_id], context=context) + return obj_id + def _create_resource_leave(self, cr, uid, leaves, context=None): '''This method will create entry in resource calendar leave object at the time of holidays validated ''' obj_res_leave = self.pool.get('resource.calendar.leaves') @@ -253,13 +258,6 @@ class hr_holidays(osv.osv): manager = ids2 and ids2[0] or False self.holidays_validate_notificate(cr, uid, ids, context=context) return self.write(cr, uid, ids, {'state':'validate1', 'manager_id': manager}) - - def holidays_validate_notificate(self, cr, uid, ids, context=None): - for obj in self.browse(cr, uid, ids): - self.message_mark_done(cr, uid, [obj.id], context=context) - self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' has been validated.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) - if obj.holiday_status_id.double_validation: - self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' is waiting for second validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) def holidays_validate2(self, cr, uid, ids, context=None): self.check_holidays(cr, uid, ids, context=context) @@ -313,20 +311,12 @@ class hr_holidays(osv.osv): self.holidays_valid2_notificate(self, cr, uid, [holiday_ids], context=context) self.write(cr, uid, holiday_ids, {'manager_id2': manager}) return True - - def holidays_valid2_notificate(self, cr, uid, ids, context=None): - for obj in self.browse(cr, uid, ids): - self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' has been double validated.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) def holidays_confirm(self, cr, uid, ids, context=None): self.check_holidays(cr, uid, ids, context=context) self.holidays_confirm_notificate(cr, uid, ids, context=context) return self.write(cr, uid, ids, {'state':'confirm'}) - def holidays_confirm_notificate(self, cr, uid, ids, context=None): - for obj in self.browse(cr, uid, ids): - self.message_append_note(cr, uid, [obj.id], _('System notification'), _("The %s request '%s' has been confirmed and is waiting for validation.") % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', need_action_user_id = obj.employee_id.parent_id.user_id.id if obj.employee_id.parent_id else False) - def holidays_refuse(self, cr, uid, ids, approval, context=None): obj_emp = self.pool.get('hr.employee') ids2 = obj_emp.search(cr, uid, [('user_id', '=', uid)]) @@ -335,6 +325,7 @@ class hr_holidays(osv.osv): self.write(cr, uid, ids, {'state': 'refuse', 'manager_id': manager}) else: self.write(cr, uid, ids, {'state': 'refuse', 'manager_id2': manager}) + self.holidays_refuse_notificate(cr, uid, ids, approval, context=context) self.holidays_cancel(cr, uid, ids, context=context) return True @@ -362,6 +353,63 @@ class hr_holidays(osv.osv): if leaves_rest < record.number_of_days_temp: raise osv.except_osv(_('Warning!'),_('You cannot validate leaves for employee %s: too few remaining days (%s).') % (record.employee_id.name, leaves_rest)) return True + + # ----------------------------- + # OpenChatter and notifications + # ----------------------------- + + def create_notificate(self, cr, uid, ids, context=None): + obj = self.browse(cr, uid, ids, context=context)[0] + self.message_append_note(cr, uid, ids, _('System notification'), + _("""The %s request '%s' has been created and is in draft mode. In this mode, it can be modified freely. + Click on Confirm to confirm your request and ask for its validation by the managers.""") + % ('leave' if obj.type == 'remove' else 'allocation', obj.name), type='notification', context=context) + return True + + def message_get_subscribers(self, cr, uid, ids, context=None): + """OpenChatter: override message_get_subscribers to add : + - employee related user + - employee manager user, if it exists""" + users = super(hr_holidays, self).message_get_subscribers(cr, uid, ids, context=context) + user_ids = [] + for holidays in self.browse(cr, uid, ids, context=context): + user_ids.append(holidays.user_id.id) + if holidays.employee_id.parent_id: + user_ids.append(holidays.employee_id.parent_id.user_id.id) + users += self.pool.get('res.users').read(cr, uid, user_ids, context=context) + return users + + def holidays_confirm_notificate(self, cr, uid, ids, context=None): + for obj in self.browse(cr, uid, ids): + self.message_append_note(cr, uid, [obj.id], _('System notification'), + _("The %s request '%s' has been confirmed. It is now waiting for validation by the manager.") + % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', + need_action_user_id = obj.employee_id.parent_id.user_id.id if obj.employee_id.parent_id else False) + + def holidays_validate_notificate(self, cr, uid, ids, context=None): + for obj in self.browse(cr, uid, ids): + self.message_mark_done(cr, uid, [obj.id], context=context) + if obj.holiday_status_id.double_validation: + self.message_append_note(cr, uid, [obj.id], _('System notification'), + _("The %s request '%s' has been validated. A second validation of your request is necessary and is now pending.") + % ('leave' if obj.type == 'remove' else 'allocation', obj.name), type='notification', context=context) + else: + self.message_append_note(cr, uid, [obj.id], _('System notification'), + _("The %s request '%s' has been validated. The validation process is now over.") + % ('leave' if obj.type == 'remove' else 'allocation', obj.name), type='notification', context=context) + + def holidays_valid2_notificate(self, cr, uid, ids, context=None): + for obj in self.browse(cr, uid, ids): + self.message_append_note(cr, uid, [obj.id], _('System notification'), + _("The %s request '%s' has been double validated. The validation process is now over.") + % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) + + def holidays_refuse_notificate(self, cr, uid, ids, approval, context=None): + for obj in self.browse(cr, uid, ids): + self.message_append_note(cr, uid, [obj.id], _('System notification'), + _("The %s request '%s' has been refused. The validation process is now over.") + % ('leave' if obj.type == 'remove' else 'allocation', obj.name,), type='notification', context=context) + hr_holidays() class resource_calendar_leaves(osv.osv): From 1805d55959be90579e07e264a23965172b39d230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 21 Feb 2012 14:12:28 +0100 Subject: [PATCH 047/133] [ADD] hr.employee: added a photo_mini field holding a resized version of photo field; modified inheritance of res.users to be able to use employee photo instead of user photo; added hr_photo_prior option to res.user form view bzr revid: tde@openerp.com-20120221131228-q0w6pyk6phlnmnrd --- addons/hr/hr.py | 54 +++++++++++++++++++++++++++++++++++++++++++ addons/hr/hr_view.xml | 13 +++++++++++ 2 files changed, 67 insertions(+) diff --git a/addons/hr/hr.py b/addons/hr/hr.py index 76f9295a829..6cc2b520f0f 100644 --- a/addons/hr/hr.py +++ b/addons/hr/hr.py @@ -23,6 +23,9 @@ from osv import fields, osv import logging import addons +import io, StringIO +from PIL import Image + class hr_employee_category(osv.osv): def name_get(self, cr, uid, ids, context=None): @@ -145,6 +148,23 @@ class hr_employee(osv.osv): _name = "hr.employee" _description = "Employee" _inherits = {'resource.resource': "resource_id"} + + def _get_photo_mini(self, cr, uid, ids, name, args, context=None): + result = {} + for obj in self.browse(cr, uid, ids, context=context): + print obj + if not obj.photo: + result[obj.id] = False + continue + + image_stream = io.BytesIO(obj.photo.decode('base64')) + img = Image.open(image_stream) + img.thumbnail((120, 100), Image.ANTIALIAS) + img_stream = StringIO.StringIO() + img.save(img_stream, "JPEG") + result[obj.id] = img_stream.getvalue().encode('base64') + return result + _columns = { 'country_id': fields.many2one('res.country', 'Nationality'), 'birthday': fields.date("Date of Birth"), @@ -171,6 +191,10 @@ class hr_employee(osv.osv): 'coach_id': fields.many2one('hr.employee', 'Coach'), 'job_id': fields.many2one('hr.job', 'Job'), 'photo': fields.binary('Photo'), + 'photo_mini': fields.function(_get_photo_mini, string='Photo Mini', type="binary", + store = { + 'hr.epployee': (lambda self, cr, uid, ids, c={}: ids, ['photo'], 10), + }), 'passport_id':fields.char('Passport No', size=64), 'color': fields.integer('Color Index'), 'city': fields.related('address_id', 'city', type='char', string='City'), @@ -274,6 +298,36 @@ class res_users(osv.osv): return user_id + def _get_photo_calc(self, cr, uid, ids, name, args, context=None): + result = {} + empl_obj = self.pool.get('hr.employee') + for user in self.browse(cr, uid, ids, context=context): + result[user.id] = user.photo + if user.hr_photo_prior: + empl_ids = empl_obj.search(cr, uid, [('user_id', '=', user.id)], context=context) + if empl_ids: + empl = empl_obj.browse(cr, uid, empl_ids, context=context)[0] + result[user.id] = empl.photo + return result + + def _get_photo_calc_mini(self, cr, uid, ids, name, args, context=None): + result = {} + empl_obj = self.pool.get('hr.employee') + for user in self.browse(cr, uid, ids, context=context): + result[user.id] = user.photo_mini + if user.hr_photo_prior: + empl_ids = empl_obj.search(cr, uid, [('user_id', '=', user.id)], context=context) + if empl_ids: + empl = empl_obj.browse(cr, uid, empl_ids, context=context)[0] + result[user.id] = empl.photo_mini + return result + + _columns = { + 'hr_photo_prior': fields.boolean('Use employee photo'), + 'photo_calc': fields.function(_get_photo_calc, string='Photo', type="binary", readonly=True), + 'photo_calc_mini': fields.function(_get_photo_calc_mini, string='Photo Mini', type="binary", readonly=True), + } + res_users() diff --git a/addons/hr/hr_view.xml b/addons/hr/hr_view.xml index 29066be2208..39da28b7025 100644 --- a/addons/hr/hr_view.xml +++ b/addons/hr/hr_view.xml @@ -219,6 +219,19 @@ + + + res.users.form_hr_photo + res.users + form + + + + + + + + - - res.users.form_hr_photo - res.users - form - - - - - - - - - - - - + + mail.group.tree + mail.group + tree + + + + + + + + + + + + mail.group.search + mail.group + search + + + + + + + + + Groups mail.group form kanban,tree,form + + + + - \ No newline at end of file + diff --git a/addons/mail/mail_thread_view.xml b/addons/mail/mail_thread_view.xml index a71ae040328..db180baa2cb 100644 --- a/addons/mail/mail_thread_view.xml +++ b/addons/mail/mail_thread_view.xml @@ -22,9 +22,6 @@ - - - From 3b71800294ef102edc1f646ac5f722eec6618485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 7 Mar 2012 16:13:43 +0100 Subject: [PATCH 118/133] hr: removed a lonely 'print' statement bzr revid: tde@openerp.com-20120307151343-81o7p0fgx6mocxyr --- addons/hr/hr.py | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/hr/hr.py b/addons/hr/hr.py index 07b04998018..30ca6a69239 100644 --- a/addons/hr/hr.py +++ b/addons/hr/hr.py @@ -152,7 +152,6 @@ class hr_employee(osv.osv): def _get_photo_mini(self, cr, uid, ids, name, args, context=None): result = {} for obj in self.browse(cr, uid, ids, context=context): - print obj if not obj.photo: result[obj.id] = False continue From 4e60bfccc552eaa9247efb0e7be607e7a56be9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 7 Mar 2012 16:34:45 +0100 Subject: [PATCH 119/133] [ADD] mail.group: added photo and photo_mini bzr revid: tde@openerp.com-20120307153445-2nrgdod40fuikldw --- addons/mail/mail_group.py | 30 +++++++++++++++++++++++++++--- addons/mail/mail_group_view.xml | 18 +++++++++++------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index 7be931d7e34..217b145e451 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -24,6 +24,9 @@ from osv import osv from osv import fields from tools.translate import _ +import io, StringIO +from PIL import Image + class mail_group(osv.osv): """ A mail_group is a collection of users sharing messages in a discussion group. @@ -48,15 +51,36 @@ class mail_group(osv.osv): return True - def action_null(self, cr, uid, ids, context={}): + def _get_photo_mini(self, cr, uid, ids, name, args, context=None): + result = {} + for obj in self.browse(cr, uid, ids, context=context): + if not obj.photo: + result[obj.id] = False + continue + + image_stream = io.BytesIO(obj.photo.decode('base64')) + img = Image.open(image_stream) + img.thumbnail((120, 100), Image.ANTIALIAS) + img_stream = StringIO.StringIO() + img.save(img_stream, "JPEG") + result[obj.id] = img_stream.getvalue().encode('base64') + return result + + def _set_photo_mini(self, cr, uid, id, name, value, args, context=None): + self.write(cr, uid, [id], {'photo': value}, context=context) return True _columns = { 'name': fields.char('Name', size=64, required=True), 'description': fields.text('Description'), 'responsible_id': fields.many2one('res.users', string='Responsible', - ondelete='set null', required=True), - 'public': fields.boolean('Public', help='This group is visible by non members') + ondelete='set null', required=True, select=1), + 'public': fields.boolean('Public', help='This group is visible by non members'), + 'photo': fields.binary('Photo'), + 'photo_mini': fields.function(_get_photo_mini, fnct_inv=_set_photo_mini, string='Photo Mini', type="binary", + store = { + 'mail.group': (lambda self, cr, uid, ids, c={}: ids, ['photo'], 10), + }), } _defaults = { diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 741d25c5932..f48ae653bfb 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -38,18 +38,22 @@
- - - - - + + + + + + + + + + + - -
diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 09fafd48a7e..47992889c90 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -326,6 +326,21 @@ class mail_thread(osv.osv): msgs = message_obj.read(cr, uid, msg_ids, context=context) return msgs + # Message tools + def message_get_discussions_nbr(self, cr, uid, ids, context=None): + count = 0 + message_obj = self.pool.get('mail.message') + for obj in self.browse(cr, uid, ids, context=context): + count += message_obj.search(cr, uid, [('model', '=', self._name), ('res_id', '=', obj.id)], count=True) # TODO: add parent_id when merging branch + return count + + def message_get_messages_nbr(self, cr, uid, ids, context=None): + count = 0 + message_obj = self.pool.get('mail.message') + for obj in self.browse(cr, uid, ids, context=context): + count += message_obj.search(cr, uid, [('model', '=', self._name), ('res_id', '=', obj.id)], count=True) + return count + #------------------------------------------------------ # Email specific #------------------------------------------------------ From b73b0918585bdea449afe5c6ed083ff631e84411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 8 Mar 2012 10:45:03 +0100 Subject: [PATCH 122/133] [ADD] project: task kanban view: user avatar is now used instead of gravatar. It now takes all height in the right-side of the context box, instead of only the right-side of title box. Added a css file for new style definitions. bzr revid: tde@openerp.com-20120308094503-cv1xt4as5lymxe95 --- addons/hr/hr_view.xml | 1 - addons/project/__openerp__.py | 3 + addons/project/project_view.xml | 76 ++++++++++--------- .../project/static/src/css/project_task.css | 21 +++++ 4 files changed, 63 insertions(+), 38 deletions(-) create mode 100644 addons/project/static/src/css/project_task.css diff --git a/addons/hr/hr_view.xml b/addons/hr/hr_view.xml index 045bdd90f99..81f1c655d33 100644 --- a/addons/hr/hr_view.xml +++ b/addons/hr/hr_view.xml @@ -130,7 +130,6 @@ hr.employee kanban - diff --git a/addons/project/__openerp__.py b/addons/project/__openerp__.py index 96a7dc4f28f..fc196890f78 100644 --- a/addons/project/__openerp__.py +++ b/addons/project/__openerp__.py @@ -67,6 +67,9 @@ Dashboard for project members that includes: 'test/project_process.yml', 'test/task_process.yml', ], + 'css': [ + 'static/src/css/project_task.css', + ], 'installable': True, 'auto_install': False, 'application': True, diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 26abe86fe99..9f791f81053 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -344,44 +344,46 @@ oe_kanban_color_green
- - - - - - -
- - - - - - -
-
-
- - - , - - - - - - - ! - +
+ +
+
+ + + + + +
+ + + + +
+
+
+ + + , + + + + + + + ! + +
+
-
diff --git a/addons/project/static/src/css/project_task.css b/addons/project/static/src/css/project_task.css new file mode 100644 index 00000000000..c029df7b2ba --- /dev/null +++ b/addons/project/static/src/css/project_task.css @@ -0,0 +1,21 @@ +.openerp .oe_proj_task_content_box { + margin-right: 41px; +} + +.openerp .oe_proj_task_avatar_box { + float: right; + width: 40px; +} + +.openerp .oe_kanban_avatar { + display: block; + width: 40px; + height: auto; + clip: rect(5px, 40px, 45px, 0px); +} + +.openerp .oe_kanban_avatar_wide { + height: 40px; + width: auto; + clip: rect(0px, 45px, 40px, 05px); +} From 6ce4a48ce9aade35c6574da9383f52414fb4ea6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 8 Mar 2012 11:40:55 +0100 Subject: [PATCH 123/133] [CLEAN] Cleaned a bit of unecessary xml/css bzr revid: tde@openerp.com-20120308104055-knvdgvj4a2z0k5fd --- addons/mail/static/src/css/mail.css | 5 +---- addons/mail/static/src/js/mail.js | 2 +- addons/mail/static/src/xml/mail.xml | 2 -- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 91fda693193..dd79e82a2a1 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -23,10 +23,7 @@ width: 34%; } -.oe_mail_wall_thread_content { -} - -.oe_mail_wall_thread_content div.oe_mail_thread_act .oe_mail_action_textarea { +.oe_mail_wall_thread div.oe_mail_thread_act .oe_mail_action_textarea { width: 100%; height: 20px; padding: 2px; diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 8bad0287bc2..2f4b24ce087 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -577,7 +577,7 @@ openerp.mail = function(session) { 'res_model': model_name, 'res_id': records[0]['res_id'], 'uid': self.session.uid, 'records': records, 'parent_id': false, 'thread_level': self.params.thread_level} ); - thread.appendTo(self.$element.find('div.oe_mail_wall_thread_content:last')); + thread.appendTo(self.$element.find('div.oe_mail_wall_thread:last')); }); }); }, diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index a51921dfc46..5b4812129e5 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -23,8 +23,6 @@
-
-
From 63a16e70748d3bb960199dd82029c625c18147a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 8 Mar 2012 12:24:45 +0100 Subject: [PATCH 124/133] [ADD] mail.thread: added automatic forward of message when @login is present in body. Also fixed a bug when posting a comment from the wall. bzr revid: tde@openerp.com-20120308112445-ndv0b1x82kv2uanp --- addons/mail/mail_thread.py | 13 +++++++++---- addons/mail/static/src/css/mail.css | 7 ++++++- addons/mail/static/src/js/mail.js | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index fcbb009615e..5949ef6bbee 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -25,6 +25,7 @@ import base64 import email from email.utils import parsedate +import re import logging import xmlrpclib from osv import osv, fields @@ -119,15 +120,19 @@ class mail_thread(osv.osv): notification_obj.create(cr, uid, {'user_id': vals['need_action_user_id'], 'message_id': msg_id}, context=context) # parse message to get requested users - user_ids = self.message_parse_users(cr, uid, [msg_id], 'body_text', context=context) + user_ids = self.message_parse_users(cr, uid, [msg_id], vals['body_text'], context=context) for user_id in user_ids: + print 'pushed to %d' % (user_id) notification_obj.create(cr, uid, {'user_id': user_id, 'message_id': msg_id}, context=context) return msg_id - def message_parse_users(self, cr, uid, ids, field_name='body_text', context=None): - '''Parse message content; if find @login: returns the related id''' - user_ids = [] + def message_parse_users(self, cr, uid, ids, string, context=None): + '''Parse message content; if find @login -(^|\s)@(\w*)-: returns the related ids''' + regex = re.compile('(^|\s)@(\w*)') + login_lst = [item[1] for item in regex.findall(string)] + if not login_lst: return [] + user_ids = self.pool.get('res.users').search(cr, uid, [('login', 'in', login_lst)], context=context) return user_ids def message_capable_models(self, cr, uid, context=None): diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index dd79e82a2a1..1a0f433cbd0 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -82,7 +82,12 @@ .oe_mail_thread { } -.oe_mail_thread_display, .oe_mail_thread_act { +.oe_mail_thread_act { + white-space: normal; + margin-bottom: 5px; +} + +.oe_mail_thread_display { white-space: normal; margin-bottom: 5px; border-bottom: 1px solid #D2D9E7; diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 2f4b24ce087..8adf116b964 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -667,7 +667,7 @@ openerp.mail = function(session) { */ do_comment: function () { var body_text = this.$element.find('textarea.oe_mail_wall_action_textarea').val(); - return this.ds_users.call('message_append_note', [[this.session.uid], 'Tweet', body_text, type='comment']).then(this.init_comments()); + return this.ds_users.call('message_append_note', [[this.session.uid], 'Tweet', body_text, false, 'comment']).then(this.init_comments()); }, /** From 0f18e4cf20d9f3e4d212022f70139b55aa952a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 8 Mar 2012 17:41:38 +0100 Subject: [PATCH 125/133] [REF] Thread and Wall widgets: html/css refactoring, based on MIT first design. bzr revid: tde@openerp.com-20120308164138-lar56562dibp8q4s --- addons/mail/static/src/css/mail.css | 156 ++++++++++++++++++---------- addons/mail/static/src/js/mail.js | 23 ++-- addons/mail/static/src/xml/mail.xml | 35 +++---- 3 files changed, 128 insertions(+), 86 deletions(-) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 1a0f433cbd0..526ee7ceb42 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -4,8 +4,7 @@ .oe_mail_wall { overflow: auto; - padding: 5px 5px 5px 5px; - color: #4C4C4C; + padding: 5px; } .oe_mail_wall_search { @@ -24,11 +23,14 @@ } .oe_mail_wall_thread div.oe_mail_thread_act .oe_mail_action_textarea { - width: 100%; height: 20px; padding: 2px; } +.oe_mail_wall_more { + text-align: center; +} + /* ------------------------------ */ /* RecordThread */ /* ------------------------------ */ @@ -58,64 +60,71 @@ .oe_mail_recthread_right { float: right; - width: 35%; + width: 25%; + margin-right: 5%; } -.oe_mail_button_follow, .oe_mail_button_unfollow, .oe_mail_button_followers { +.oe_mail_button_follow, .oe_mail_button_unfollow { width: 120px; } -/* Subscribers */ -.oe_mail_followers_vignette { - float: left; - width: 20%%; +.oe_mail_button_followers { + display: inline; + width: 120px; } -.oe_mail_followers_vignette img { - width: 80%; +.oe_mail_followers h4 { + margin: 0 0 8px; } /* ------------------------------ */ /* ThreadDisplay */ /* ------------------------------ */ -.oe_mail_thread { -} - -.oe_mail_thread_act { +div.oe_mail_thread_act { white-space: normal; margin-bottom: 5px; } -.oe_mail_thread_display { +div.oe_mail_thread_display { white-space: normal; margin-bottom: 5px; - border-bottom: 1px solid #D2D9E7; } -.oe_mail_thread_subthread { +div.oe_mail_thread_subthread { + margin-top: 8px; padding-left: 5%; } -.oe_mail_thread_more { - margin-left: 20%; - margin-right: 40%; - border: 1px solid #D2D9E7; - text-align: center; +div.oe_mail_thread_more { + border-bottom: 1px solid #D2D9E7; } -.notification { +div.oe_mail_thread_msg { + padding: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; + border-radius: 4px; +} + +div.notification { background: #E0E0E0; } -.email { +div.email { background: #E0E0E0; } -.oe_mail_thread_msg:after, .oe_mail_thread_act:after { - content: ""; - display: block; - clear: both; +div.oe_mail_thread_msg:after, div.oe_mail_thread_act:after { + content: ""; + display: block; + clear: both; +} + +.oe_mail_msg_content { + margin-left: 60px; } .oe_mail_button_comment { @@ -128,30 +137,21 @@ } .oe_mail_msg_image { - float: left; + margin-right: 8px; width: 45px; - height: 40px; + height: 45px; text-align: center; overflow: hidden; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - border-radius: 3px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; + border-radius: 4px; -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); -o-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); -} - -.oe_mail_msg_image img { - width: 40px; - height: auto; - clip: rect(10px, 100px, 110px, 0px); -} - -.oe_mail_msg_content { - margin-left: 50px; + clip: rect(5px, 40px, 45px, 0px); } .oe_mail_msg_p { @@ -167,18 +167,64 @@ color: #4E43E7; } -.oe_mail_msg_author { - color: #747474; +/* ------------------------------ */ +/* Styling (should be openerp) */ +/* ------------------------------ */ + +input.oe_mail, textarea.oe_mail { + width: 100%; + padding: 4px; + font-size: 12px; + border: 1px solid #cccccc; + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -ms-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; } -.oe_mail_msg_author a { - color: #4E43E7; +input.oe_mail:focus, textarea.oe_mail:focus { + outline: 0; + border-color: rgba(82, 168, 236, 0.8); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + -box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); } -.oe_mail_msg_need_action, .oe_mail_msg_need_action a { +p.oe_mail_msg { + padding: 0; + margin: 0; +} + +.oe_mail_oe_right { + float: right; + margin-right: 8px; +} + +.oe_mail_oe_left { + float: left; + margin-right: 8px; +} + +.oe_mail_oe_fade { + font-size: 12px; + color: #888888; +} + +.oe_mail_oe_bold { + font-weight: bold; +} + +a.oe_mail_oe_intlink { + color: #8786b7; +} + +.oe_mail_oe_warning, .oe_mail_oe_warning a { color: #C03000; } - -.oe_mail_msg_date { - color: #747474; -} diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 8adf116b964..d9f6c3472c4 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -221,8 +221,7 @@ openerp.mail = function(session) { }, display_current_user: function () { - return this.$element.find('div.oe_mail_msg_image').empty().html( - ''); + return this.$element.find('img.oe_mail_msg_image').attr('src', this.thread_get_avatar_mini('res.users', 'avatar_mini', this.params.uid)); }, do_comment: function () { @@ -281,7 +280,7 @@ openerp.mail = function(session) { var regex_res = regex_login.exec(string); while (regex_res != null) { var login = regex_res[2]; - string = string.replace(regex_res[0], '@' + login + ''); + string = string.replace(regex_res[0], '@' + login + ''); regex_res = regex_login.exec(string); } return string; @@ -345,7 +344,7 @@ openerp.mail = function(session) { init: function() { this.is_sub = 0; - this.see_sub = 0; + this.see_sub = 1; this._super.apply(this, arguments); this.thread = null; /* DataSets */ @@ -370,10 +369,9 @@ openerp.mail = function(session) { console.log('set_value'); var self = this; this._super.apply(this, arguments); - this.see_sub = 0; + this.see_sub = 1; /* hide follow/unfollow/see followers buttons */ - this.$element.find('button.oe_mail_button_followers').html('Display followers') - this.$element.find('div.oe_mail_followers_display').hide(); + this.$element.find('button.oe_mail_button_followers').html('Hide followers') this.$element.find('button.oe_mail_button_follow').hide(); this.$element.find('button.oe_mail_button_unfollow').hide(); if (! this.view.datarecord.id) { return; } @@ -397,12 +395,13 @@ openerp.mail = function(session) { }, display_subscribers: function (records) { - this.$element.find('div.oe_mail_followers_display').empty(); var self = this; + var sub_node = this.$element.find('div.oe_mail_followers') + sub_node.empty(); + $('

').html('Followers (' + records.length + ')').appendTo(sub_node); _(records).each(function (record) { - $('
').html( - '' + record.name + '' - ).appendTo(self.$element.find('div.oe_mail_followers_display')); + var mini_url = self.thread_get_avatar_mini('res.users', 'avatar_mini', record.id); + $('' + record.name + '').appendTo(sub_node); }); }, @@ -426,7 +425,7 @@ openerp.mail = function(session) { this.see_sub = 1 - this.see_sub; if (this.see_sub == 1) { this.$element.find('button.oe_mail_button_followers').html('Hide followers'); } else { this.$element.find('button.oe_mail_button_followers').html('Display followers'); } - this.$element.find('div.oe_mail_followers_display').toggle(); + this.$element.find('div.oe_mail_followers').toggle(); }, thread_get_avatar_mini: function(model, field, id) { diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 5b4812129e5..295d46b96ba 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -7,7 +7,7 @@
-
+
+