[MERGE] Merged vote system in Chatter.
Adds a +1 / -1 on displayed messages in Chatter. Those links allow to vote or unvote for a given messages. Purpose: being able to build a Chatter, using a ranking based on votes instgead of date or ids. This will be used in a future vote-based FAQ. bzr revid: tde@openerp.com-20120918152401-z6m38b1vllz4ckgi
This commit is contained in:
commit
389a7fc364
|
@ -25,6 +25,7 @@ import mail_message
|
|||
import mail_mail
|
||||
import mail_thread
|
||||
import mail_group
|
||||
import mail_vote
|
||||
import res_partner
|
||||
import res_users
|
||||
import report
|
||||
|
|
|
@ -130,6 +130,8 @@ class mail_message(osv.Model):
|
|||
'unread': fields.function(_get_unread, fnct_search=_search_unread,
|
||||
type='boolean', string='Unread',
|
||||
help='Functional field to search for unread messages linked to uid'),
|
||||
'vote_user_ids': fields.many2many('res.users', 'mail_vote', 'message_id', 'user_id', string='Votes',
|
||||
help='Users that voted for this message'),
|
||||
}
|
||||
|
||||
def _needaction_domain_get(self, cr, uid, context=None):
|
||||
|
@ -147,12 +149,35 @@ class mail_message(osv.Model):
|
|||
'body': '',
|
||||
}
|
||||
|
||||
#------------------------------------------------------
|
||||
# Vote/Like
|
||||
#------------------------------------------------------
|
||||
|
||||
def vote_toggle(self, cr, uid, ids, user_ids=None, context=None):
|
||||
''' Toggles voting '''
|
||||
if not user_ids:
|
||||
user_ids = [uid]
|
||||
for message in self.read(cr, uid, ids, ['vote_user_ids'], context=context):
|
||||
for user_id in user_ids:
|
||||
has_voted = user_id in message.get('vote_user_ids')
|
||||
if not has_voted:
|
||||
self.write(cr, uid, message.get('id'), {'vote_user_ids': [(4, user_id)]}, context=context)
|
||||
else:
|
||||
self.write(cr, uid, message.get('id'), {'vote_user_ids': [(3, user_id)]}, context=context)
|
||||
return True
|
||||
|
||||
#------------------------------------------------------
|
||||
# Message loading for web interface
|
||||
#------------------------------------------------------
|
||||
|
||||
def _message_dict_get(self, cr, uid, msg, context=None):
|
||||
""" Return a dict representation of the message browse record. """
|
||||
has_voted = False
|
||||
vote_ids = self.pool.get('res.users').name_get(cr, uid, [user.id for user in msg.vote_user_ids], context=context)
|
||||
for vote in vote_ids:
|
||||
if vote[0] == uid:
|
||||
has_voted = True
|
||||
break
|
||||
attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context)]
|
||||
author_id = self.pool.get('res.partner').name_get(cr, uid, [msg.author_id.id], context=context)[0]
|
||||
author_user_id = self.pool.get('res.users').name_get(cr, uid, [msg.author_id.user_ids[0].id], context=context)[0]
|
||||
|
@ -171,6 +196,8 @@ class mail_message(osv.Model):
|
|||
'author_user_id': author_user_id,
|
||||
'partner_ids': partner_ids,
|
||||
'child_ids': [],
|
||||
'vote_user_ids': vote_ids,
|
||||
'has_voted': has_voted
|
||||
}
|
||||
|
||||
def message_read_tree_flatten(self, cr, uid, messages, current_level, level, context=None):
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2012-Today OpenERP SA (<http://www.openerp.com>).
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import osv, fields
|
||||
|
||||
|
||||
class mail_vote(osv.Model):
|
||||
''' Mail vote feature allow users to like and unlike messages attached
|
||||
to a document. This allows for example to build a ranking-based
|
||||
displaying of messages, for FAQ. '''
|
||||
|
||||
_name = 'mail.vote'
|
||||
_description = 'Mail Vote'
|
||||
_columns = {
|
||||
'message_id': fields.many2one('mail.message', 'Message', select=1,
|
||||
ondelete='cascade', required=True),
|
||||
'user_id': fields.many2one('res.users', 'User', select=1,
|
||||
ondelete='cascade', required=True),
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -10,3 +10,4 @@ access_mail_alias_user,mail.alias,model_mail_alias,base.group_user,1,1,1,0
|
|||
access_mail_alias_system,mail.alias,model_mail_alias,base.group_system,1,1,1,1
|
||||
access_mail_mail_user,mail.mail,model_mail_mail,base.group_user,1,1,1,0
|
||||
access_mail_mail_manager,mail.mail,model_mail_mail,group_mail_manager,1,1,1,1
|
||||
access_mail_vote_all,mail.vote.all,model_mail_vote,,1,1,1,1
|
||||
|
|
|
|
@ -260,6 +260,31 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* mail.vote
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
.openerp .oe_mail_msg_content button.oe_mail_msg_vote {
|
||||
height:21px;
|
||||
width: 30px;
|
||||
padding: 1px;
|
||||
background: #8A89BA;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content button.oe_mail_msg_vote_true {
|
||||
background:#DC5F59;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content button.oe_mail_msg_vote span {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.openerp .oe_mail_msg_content span.oe_mail_vote_count{
|
||||
color: #807FB4;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* mail.compose.message form view & OpenERP hacks
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -291,6 +291,7 @@ openerp.mail = function(session) {
|
|||
truncate_limit: options.truncate_limit || 250,
|
||||
}
|
||||
// datasets and internal vars
|
||||
this.records = {};
|
||||
this.ds_thread = new session.web.DataSetSearch(this, this.context.default_model);
|
||||
this.ds_notification = new session.web.DataSetSearch(this, 'mail.notification');
|
||||
this.ds_message = new session.web.DataSetSearch(this, 'mail.message');
|
||||
|
@ -355,6 +356,8 @@ openerp.mail = function(session) {
|
|||
'default_parent_id': parseInt(msg_id),
|
||||
'default_content_subtype': 'html'} );
|
||||
});
|
||||
// event: click on 'Vote' button
|
||||
this.$el.on('click', 'button.oe_mail_msg_vote', this.on_vote);
|
||||
},
|
||||
|
||||
on_message_delete: function (event) {
|
||||
|
@ -373,6 +376,16 @@ openerp.mail = function(session) {
|
|||
return this.ds_notification.call('set_message_read', [parseInt(msg_id)]);
|
||||
},
|
||||
|
||||
on_vote: function (event) {
|
||||
event.stopPropagation();
|
||||
var self = this;
|
||||
var message_id = $(event.srcElement).parent().data().msg_id;
|
||||
var vote_node = $(event.srcElement).parents('li').eq(0);
|
||||
if (! message_id) { return false; }
|
||||
return this.ds_message.call('vote_toggle', [[parseInt(message_id)]]).pipe(
|
||||
self.toggle_vote(message_id, vote_node));
|
||||
},
|
||||
|
||||
/**
|
||||
* Override-hack of do_action: automatically reload the chatter.
|
||||
* Normally it should be called only when clicking on 'Post/Send'
|
||||
|
@ -492,6 +505,8 @@ openerp.mail = function(session) {
|
|||
attach['url'] = mail.ChatterUtils.get_attachment_url(this.session, attach);
|
||||
}
|
||||
record.is_author = mail.ChatterUtils.is_author(this, record.author_user_id[0]);
|
||||
// add to internal storage
|
||||
this.records[record.id] = record;
|
||||
// render, add the expand feature
|
||||
var rendered = session.web.qweb.render('mail.thread.message', {'record': record, 'thread': this, 'options': this.options});
|
||||
$(rendered).appendTo(this.$el.children('div.oe_mail_thread_display:first'));
|
||||
|
@ -505,6 +520,23 @@ openerp.mail = function(session) {
|
|||
});
|
||||
},
|
||||
|
||||
// Render vote Display template.
|
||||
toggle_vote: function (message_id, vote_node) {
|
||||
var self = this;
|
||||
var record = this.records[message_id];
|
||||
if (record.has_voted) {
|
||||
var idx = _.map(record.vote_user_ids, function (x) { return x[0]; }).indexOf(message_id);
|
||||
record.vote_user_ids.splice(idx, 1);
|
||||
}
|
||||
else {
|
||||
record.vote_user_ids.push([this.session.uid, 'You']);
|
||||
}
|
||||
record.has_voted = ! record.has_voted;
|
||||
var vote_element = session.web.qweb.render('mail.thread.message.vote', {'record': record});
|
||||
vote_node.empty();
|
||||
vote_node.html(vote_element);
|
||||
},
|
||||
|
||||
/** Display 'show more' button */
|
||||
update_fetch_more: function (new_value) {
|
||||
if (new_value) {
|
||||
|
|
|
@ -142,11 +142,9 @@
|
|||
</li>
|
||||
<li><a t-attf-href="#model=res.partner&id=#{record.author_id[0]}"><t t-raw="record.author_id[1]"/></a></li>
|
||||
<li><span t-att-title="record.date"><t t-raw="record.timerelative"/></span></li>
|
||||
<t t-call="mail.thread.message.vote"/>
|
||||
<li t-if="options.show_reply"><a class="oe_mail_msg_reply">Reply</a></li>
|
||||
<li t-if="options.show_reply_by_email"><a class="oe_mail_msg_reply_by_email" t-attf-data-msg_id="{record.id}">Reply</a></li>
|
||||
<!-- uncomment when merging vote
|
||||
<li><a href="#">Like</a></li>
|
||||
-->
|
||||
<li t-if="record.attachment_ids.length > 0">
|
||||
<a class="oe_mail_msg_view_attachments">
|
||||
<t t-if="record.attachment_ids.length == 1">1 Attachment</t>
|
||||
|
@ -180,4 +178,17 @@
|
|||
</ul>
|
||||
</t>
|
||||
|
||||
<!-- mail.thread.message.vote
|
||||
Template used to display Like/Unlike in a mail.message
|
||||
-->
|
||||
<li t-name="mail.thread.message.vote">
|
||||
<t t-if='record.vote_user_ids.length > 0'>
|
||||
<span class="oe_left oe_mail_vote_count"><t t-esc="record.vote_user_ids.length"/> votes</span>
|
||||
</t>
|
||||
<button t-attf-class="oe_mail_msg_vote oe_mail_msg_vote_#{record.has_voted}" t-attf-data-msg_id="{record.id}">
|
||||
<t t-if="! record.has_voted"><span>+1</span></t>
|
||||
<t t-if="record.has_voted"><span>-1</span></t>
|
||||
</button>
|
||||
</li>
|
||||
|
||||
</template>
|
||||
|
|
|
@ -647,3 +647,33 @@ class test_mail(TestMailMockups):
|
|||
msg1.refresh()
|
||||
self.assertEqual(5, len(group_pigs.message_ids), 'group should contain 5 messages')
|
||||
self.assertEqual(2, len(msg1.child_ids), 'msg1 should have 2 children now')
|
||||
|
||||
def test_60_vote(self):
|
||||
""" Test designed for the vote/unvote feature. """
|
||||
cr, uid = self.cr, self.uid
|
||||
group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id)
|
||||
user_admin = self.res_users.browse(cr, uid, uid)
|
||||
msg1 = group_pigs.message_post(body='My Body', subject='1')
|
||||
msg1 = self.mail_message.browse(cr, uid, msg1)
|
||||
|
||||
# Create user Bert Tartopoils
|
||||
user_bert_id = self.res_users.create(cr, uid, {'name': 'Bert', 'login': 'bert'})
|
||||
user_bert = self.res_users.browse(cr, uid, user_bert_id)
|
||||
|
||||
# Test: msg1 and msg2 have void vote_user_ids
|
||||
self.assertFalse(msg1.vote_user_ids, 'newly created message msg1 has not void vote_user_ids')
|
||||
# Do: Admin vote for msg1
|
||||
self.mail_message.vote_toggle(cr, uid, [msg1.id])
|
||||
msg1.refresh()
|
||||
# Test: msg1 has Admin as voter
|
||||
self.assertEqual(set(msg1.vote_user_ids), set([user_admin]), 'after voting, Admin is not the voter')
|
||||
# Do: Bert vote for msg1
|
||||
self.mail_message.vote_toggle(cr, uid, [msg1.id], [user_bert_id])
|
||||
msg1.refresh()
|
||||
# Test: msg1 has Admin and Bert as voters
|
||||
self.assertEqual(set(msg1.vote_user_ids), set([user_admin, user_bert]), 'after voting, Admin and Bert are not the voters')
|
||||
# Do: Admin unvote for msg1
|
||||
self.mail_message.vote_toggle(cr, uid, [msg1.id])
|
||||
msg1.refresh()
|
||||
# Test: msg1 has Bert as voter
|
||||
self.assertEqual(set(msg1.vote_user_ids), set([user_bert]), 'after unvoting for Admin, Bert is not the voter')
|
||||
|
|
Loading…
Reference in New Issue