Merge pull request #771 from odoo-dev/master-forum-imp-tde
[IMP] forum: better management of karma-based actions, using calculated fields and view simplification
This commit is contained in:
commit
691fc394af
|
@ -12,7 +12,6 @@ from openerp.addons.web.controllers.main import login_redirect
|
|||
from openerp.addons.web.http import request
|
||||
from openerp.addons.website.controllers.main import Website as controllers
|
||||
from openerp.addons.website.models.website import slug
|
||||
from openerp.tools import html2plaintext
|
||||
|
||||
controllers = controllers()
|
||||
|
||||
|
@ -33,20 +32,12 @@ class WebsiteForum(http.Controller):
|
|||
return msg
|
||||
|
||||
def _prepare_forum_values(self, forum=None, **kwargs):
|
||||
Forum = request.registry['forum.forum']
|
||||
user = request.registry['res.users'].browse(request.cr, request.uid, request.uid, context=request.context)
|
||||
values = {'user': user,
|
||||
'is_public_user': user.id == request.website.user_id.id,
|
||||
'notifications': self._get_notifications(),
|
||||
'header': kwargs.get('header', dict()),
|
||||
'searches': kwargs.get('searches', dict()),
|
||||
'can_edit_own': True,
|
||||
'can_edit_all': user.karma > Forum._karma_modo_edit_all,
|
||||
'can_close_own': user.karma > Forum._karma_modo_close_own,
|
||||
'can_close_all': user.karma > Forum._karma_modo_close_all,
|
||||
'can_unlink_own': user.karma > Forum._karma_modo_unlink_own,
|
||||
'can_unlink_all': user.karma > Forum._karma_modo_unlink_all,
|
||||
'can_unlink_comment': user.karma > Forum._karma_modo_unlink_comment,
|
||||
}
|
||||
if forum:
|
||||
values['forum'] = forum
|
||||
|
@ -55,14 +46,6 @@ class WebsiteForum(http.Controller):
|
|||
values.update(kwargs)
|
||||
return values
|
||||
|
||||
def _has_enough_karma(self, karma_name, uid=None):
|
||||
Forum = request.registry['forum.forum']
|
||||
karma = hasattr(Forum, karma_name) and getattr(Forum, karma_name) or 0
|
||||
user = request.registry['res.users'].browse(request.cr, SUPERUSER_ID, uid or request.uid, context=request.context)
|
||||
if user.karma < karma:
|
||||
return False, {'error': 'not_enough_karma', 'karma': karma}
|
||||
return True, {}
|
||||
|
||||
# Forum
|
||||
# --------------------------------------------------
|
||||
|
||||
|
@ -244,10 +227,6 @@ class WebsiteForum(http.Controller):
|
|||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>/ask_for_close', type='http', auth="user", methods=['POST'], website=True)
|
||||
def question_ask_for_close(self, forum, question, **post):
|
||||
check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_close_own' or '_karma_modo_close_all')
|
||||
if not check_res[0]:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Reason = request.registry['forum.post.reason']
|
||||
reason_ids = Reason.search(cr, uid, [], context=context)
|
||||
|
@ -272,42 +251,21 @@ class WebsiteForum(http.Controller):
|
|||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>/close', type='http', auth="user", methods=['POST'], website=True)
|
||||
def question_close(self, forum, question, **post):
|
||||
check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_close_own' or '_karma_modo_close_all')
|
||||
if not check_res[0]:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
|
||||
request.registry['forum.post'].write(request.cr, request.uid, [question.id], {
|
||||
'state': 'close',
|
||||
'closed_uid': request.uid,
|
||||
'closed_date': datetime.today().strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
'closed_reason_id': int(post.get('reason_id', False)),
|
||||
}, context=request.context)
|
||||
request.registry['forum.post'].close(request.cr, request.uid, [question.id], reason_id=int(post.get('reason_id', False)), context=request.context)
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>/reopen', type='http', auth="user", methods=['POST'], website=True)
|
||||
def question_reopen(self, forum, question, **kwarg):
|
||||
check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_close_own' or '_karma_modo_close_all')
|
||||
if not check_res[0]:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
|
||||
request.registry['forum.post'].write(request.cr, request.uid, [question.id], {'state': 'active'}, context=request.context)
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>/delete', type='http', auth="user", methods=['POST'], website=True)
|
||||
def question_delete(self, forum, question, **kwarg):
|
||||
check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_unlink_own' or '_karma_modo_unlink_all')
|
||||
if not check_res[0]:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
|
||||
request.registry['forum.post'].write(request.cr, request.uid, [question.id], {'active': False}, context=request.context)
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>/undelete', type='http', auth="user", methods=['POST'], website=True)
|
||||
def question_undelete(self, forum, question, **kwarg):
|
||||
check_res = self._has_enough_karma(question.create_uid.id == request.uid and '_karma_modo_unlink_own' or '_karma_modo_unlink_all')
|
||||
if not check_res[0]:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
|
||||
request.registry['forum.post'].write(request.cr, request.uid, [question.id], {'active': True}, context=request.context)
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
|
||||
|
||||
|
@ -349,11 +307,6 @@ class WebsiteForum(http.Controller):
|
|||
return request.redirect('/')
|
||||
if not request.session.uid:
|
||||
return {'error': 'anonymous_user'}
|
||||
user = request.registry['res.users'].browse(request.cr, SUPERUSER_ID, request.uid, context=request.context)
|
||||
if post.parent_id.create_uid.id != uid and user.karma < request.registry['forum.forum']._karma_answer_accept_all:
|
||||
return {'error': 'not_enough_karma', 'karma': request.registry['forum.forum']._karma_answer_accept_all}
|
||||
if post.create_uid.id == user.id and user.karma < request.registry['forum.forum']._karma_answer_accept_own:
|
||||
return {'error': 'not_enough_karma', 'karma': request.registry['forum.forum']._karma_answer_accept_own}
|
||||
|
||||
# set all answers to False, only one can be accepted
|
||||
request.registry['forum.post'].write(cr, uid, [c.id for c in post.parent_id.child_ids], {'is_correct': False}, context=context)
|
||||
|
@ -362,10 +315,6 @@ class WebsiteForum(http.Controller):
|
|||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/delete', type='http', auth="user", methods=['POST'], website=True)
|
||||
def post_delete(self, forum, post, **kwargs):
|
||||
check_res = self._has_enough_karma(post.create_uid.id == request.uid and '_karma_modo_unlink_own' or '_karma_modo_unlink_all')
|
||||
if not check_res[0]:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
|
||||
question = post.parent_id
|
||||
request.registry['forum.post'].unlink(request.cr, request.uid, [post.id], context=request.context)
|
||||
if question:
|
||||
|
@ -374,10 +323,6 @@ class WebsiteForum(http.Controller):
|
|||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/edit', type='http', auth="user", website=True)
|
||||
def post_edit(self, forum, post, **kwargs):
|
||||
check_res = self._has_enough_karma(post.create_uid.id == request.uid and '_karma_modo_edit_own' or '_karma_modo_edit_all')
|
||||
if not check_res[0]:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
|
||||
tags = ""
|
||||
for tag_name in post.tag_ids:
|
||||
tags += tag_name.name + ","
|
||||
|
@ -419,9 +364,6 @@ class WebsiteForum(http.Controller):
|
|||
return {'error': 'anonymous_user'}
|
||||
if request.uid == post.create_uid.id:
|
||||
return {'error': 'own_post'}
|
||||
check_res = self._has_enough_karma('_karma_upvote')
|
||||
if not check_res[0]:
|
||||
return check_res[1]
|
||||
upvote = True if not post.user_vote > 0 else False
|
||||
return request.registry['forum.post'].vote(request.cr, request.uid, [post.id], upvote=upvote, context=request.context)
|
||||
|
||||
|
@ -431,9 +373,6 @@ class WebsiteForum(http.Controller):
|
|||
return {'error': 'anonymous_user'}
|
||||
if request.uid == post.create_uid.id:
|
||||
return {'error': 'own_post'}
|
||||
check_res = self._has_enough_karma('_karma_downvote')
|
||||
if not check_res[0]:
|
||||
return check_res[1]
|
||||
upvote = True if post.user_vote < 0 else False
|
||||
return request.registry['forum.post'].vote(request.cr, request.uid, [post.id], upvote=upvote, context=request.context)
|
||||
|
||||
|
@ -625,26 +564,25 @@ class WebsiteForum(http.Controller):
|
|||
# Messaging
|
||||
# --------------------------------------------------
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/comment/<model("mail.message"):comment>/convert_to_answer', type='http', auth="public", methods=['POST'], website=True)
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/comment/<model("mail.message"):comment>/convert_to_answer', type='http', auth="user", methods=['POST'], website=True)
|
||||
def convert_comment_to_answer(self, forum, post, comment, **kwarg):
|
||||
body = comment.body
|
||||
request.registry['mail.message'].unlink(request.cr, request.uid, [comment.id], context=request.context)
|
||||
new_post_id = request.registry['forum.post'].convert_comment_to_answer(request.cr, request.uid, comment.id, context=request.context)
|
||||
if not new_post_id:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
post = request.registry['forum.post'].browse(request.cr, request.uid, new_post_id, context=request.context)
|
||||
question = post.parent_id if post.parent_id else post
|
||||
for answer in question.child_ids:
|
||||
if answer.create_uid.id == request.uid:
|
||||
return self.post_comment(forum, answer, comment=html2plaintext(body))
|
||||
return self.post_new(forum, question, content=body)
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/convert_to_comment', type='http', auth="user", methods=['POST'], website=True)
|
||||
def convert_answer_to_comment(self, forum, post, **kwarg):
|
||||
values = {
|
||||
'comment': html2plaintext(post.content),
|
||||
}
|
||||
question = post.parent_id
|
||||
request.registry['forum.post'].unlink(request.cr, SUPERUSER_ID, [post.id], context=request.context)
|
||||
return self.post_comment(forum, question, **values)
|
||||
new_msg_id = request.registry['forum.post'].convert_answer_to_comment(request.cr, request.uid, post.id, context=request.context)
|
||||
if not new_msg_id:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/comment/<model("mail.message"):comment>/delete', type='json', auth="user", website=True)
|
||||
def delete_comment(self, forum, post, comment, **kwarg):
|
||||
request.registry['mail.message'].unlink(request.cr, SUPERUSER_ID, [comment.id], context=request.context)
|
||||
return True
|
||||
if not request.session.uid:
|
||||
return {'error': 'anonymous_user'}
|
||||
return request.registry['forum.post'].unlink(request.cr, request.uid, post.id, comment.id, context=request.context)
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<record id="mt_question_new" model="mail.message.subtype">
|
||||
<field name="name">New Question</field>
|
||||
<field name="res_model">forum.post</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="description">New Question</field>
|
||||
</record>
|
||||
<record id="mt_question_edit" model="mail.message.subtype">
|
||||
|
@ -57,7 +57,7 @@
|
|||
<record id="mt_forum_answer_new" model="mail.message.subtype">
|
||||
<field name="name">New Answer</field>
|
||||
<field name="res_model">forum.forum</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="hidden" eval="False"/>
|
||||
<field name="parent_id" eval="ref('mt_answer_new')"/>
|
||||
<field name="relation_field">forum_id</field>
|
||||
|
|
|
@ -1,50 +1,63 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import openerp
|
||||
from openerp import tools
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.addons.website.models.website import slug
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools import html2plaintext
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class KarmaError(ValueError):
|
||||
""" Karma-related error, used for forum and posts. """
|
||||
pass
|
||||
|
||||
|
||||
class Forum(osv.Model):
|
||||
"""TDE TODO: set karma values for actions dynamic for a given forum"""
|
||||
_name = 'forum.forum'
|
||||
_description = 'Forums'
|
||||
_inherit = ['mail.thread', 'website.seo.metadata']
|
||||
# karma values
|
||||
_karma_upvote = 5 # done
|
||||
_karma_downvote = 50 # done
|
||||
_karma_answer_accept_own = 20 # done
|
||||
_karma_answer_accept_own_now = 50
|
||||
_karma_answer_accept_all = 500
|
||||
_karma_editor_link_files = 30 # done
|
||||
_karma_editor_clickable_link = 50
|
||||
_karma_comment = 1
|
||||
_karma_modo_retag = 75
|
||||
_karma_modo_flag = 100
|
||||
_karma_modo_flag_see_all = 300
|
||||
_karma_modo_unlink_comment = 750
|
||||
_karma_modo_edit_own = 1 # done
|
||||
_karma_modo_edit_all = 300 # done
|
||||
_karma_modo_close_own = 100 # done
|
||||
_karma_modo_close_all = 900 # done
|
||||
_karma_modo_unlink_own = 500 # done
|
||||
_karma_modo_unlink_all = 1000 # done
|
||||
# karma generation
|
||||
_karma_gen_quest_new = 2 # done
|
||||
_karma_gen_upvote_quest = 5 # done
|
||||
_karma_gen_downvote_quest = -2 # done
|
||||
_karma_gen_upvote_ans = 10 # done
|
||||
_karma_gen_downvote_ans = -2 # done
|
||||
_karma_gen_ans_accept = 2 # done
|
||||
_karma_gen_ans_accepted = 15 # done
|
||||
_karma_gen_ans_flagged = -100
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True, translate=True),
|
||||
'faq': fields.html('Guidelines'),
|
||||
'description': fields.html('Description'),
|
||||
# karma generation
|
||||
'karma_gen_question_new': fields.integer('Karma earned for new questions'),
|
||||
'karma_gen_question_upvote': fields.integer('Karma earned for upvoting a question'),
|
||||
'karma_gen_question_downvote': fields.integer('Karma earned for downvoting a question'),
|
||||
'karma_gen_answer_upvote': fields.integer('Karma earned for upvoting an answer'),
|
||||
'karma_gen_answer_downvote': fields.integer('Karma earned for downvoting an answer'),
|
||||
'karma_gen_answer_accept': fields.integer('Karma earned for accepting an anwer'),
|
||||
'karma_gen_answer_accepted': fields.integer('Karma earned for having an answer accepted'),
|
||||
'karma_gen_answer_flagged': fields.integer('Karma earned for having an answer flagged'),
|
||||
# karma-based actions
|
||||
'karma_ask': fields.integer('Karma to ask a new question'),
|
||||
'karma_answer': fields.integer('Karma to answer a question'),
|
||||
'karma_edit_own': fields.integer('Karma to edit its own posts'),
|
||||
'karma_edit_all': fields.integer('Karma to edit all posts'),
|
||||
'karma_close_own': fields.integer('Karma to close its own posts'),
|
||||
'karma_close_all': fields.integer('Karma to close all posts'),
|
||||
'karma_unlink_own': fields.integer('Karma to delete its own posts'),
|
||||
'karma_unlink_all': fields.integer('Karma to delete all posts'),
|
||||
'karma_upvote': fields.integer('Karma to upvote'),
|
||||
'karma_downvote': fields.integer('Karma to downvote'),
|
||||
'karma_answer_accept_own': fields.integer('Karma to accept an answer on its own questions'),
|
||||
'karma_answer_accept_all': fields.integer('Karma to accept an answers to all questions'),
|
||||
'karma_editor_link_files': fields.integer('Karma for linking files (Editor)'),
|
||||
'karma_editor_clickable_link': fields.integer('Karma for clickable links (Editor)'),
|
||||
'karma_comment_own': fields.integer('Karma to comment its own posts'),
|
||||
'karma_comment_all': fields.integer('Karma to comment all posts'),
|
||||
'karma_comment_convert_own': fields.integer('Karma to convert its own answers to comments and vice versa'),
|
||||
'karma_comment_convert_all': fields.integer('Karma to convert all answers to answers and vice versa'),
|
||||
'karma_comment_unlink_own': fields.integer('Karma to unlink its own comments'),
|
||||
'karma_comment_unlink_all': fields.integer('Karma to unlinnk all comments'),
|
||||
'karma_retag': fields.integer('Karma to change question tags'),
|
||||
'karma_flag': fields.integer('Karma to flag a post as offensive'),
|
||||
}
|
||||
|
||||
def _get_default_faq(self, cr, uid, context=None):
|
||||
|
@ -56,6 +69,36 @@ class Forum(osv.Model):
|
|||
_defaults = {
|
||||
'description': 'This community is for professionals and enthusiasts of our products and services.',
|
||||
'faq': _get_default_faq,
|
||||
'karma_gen_question_new': 2,
|
||||
'karma_gen_question_upvote': 5,
|
||||
'karma_gen_question_downvote': -2,
|
||||
'karma_gen_answer_upvote': 10,
|
||||
'karma_gen_answer_downvote': -2,
|
||||
'karma_gen_answer_accept': 2,
|
||||
'karma_gen_answer_accepted': 15,
|
||||
'karma_gen_answer_flagged': -100,
|
||||
'karma_ask': 0,
|
||||
'karma_answer': 0,
|
||||
'karma_edit_own': 1,
|
||||
'karma_edit_all': 300,
|
||||
'karma_close_own': 100,
|
||||
'karma_close_all': 500,
|
||||
'karma_unlink_own': 500,
|
||||
'karma_unlink_all': 1000,
|
||||
'karma_upvote': 5,
|
||||
'karma_downvote': 50,
|
||||
'karma_answer_accept_own': 20,
|
||||
'karma_answer_accept_all': 500,
|
||||
'karma_editor_link_files': 20,
|
||||
'karma_editor_clickable_link': 20,
|
||||
'karma_comment_own': 1,
|
||||
'karma_comment_all': 1,
|
||||
'karma_comment_convert_own': 50,
|
||||
'karma_comment_convert_all': 500,
|
||||
'karma_comment_unlink_own': 50,
|
||||
'karma_comment_unlink_all': 500,
|
||||
'karma_retag': 75,
|
||||
'karma_flag': 500,
|
||||
}
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
|
@ -139,6 +182,36 @@ class Post(osv.Model):
|
|||
res[post.id] = post.parent_id and post.parent_id.create_uid == post.create_uid or False
|
||||
return res
|
||||
|
||||
def _get_post_karma_rights(self, cr, uid, ids, field_name, arg, context=None):
|
||||
user = self.pool['res.users'].browse(cr, uid, uid, context=context)
|
||||
res = dict.fromkeys(ids, False)
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
res[post.id] = {
|
||||
'karma_ask': post.forum_id.karma_ask,
|
||||
'karma_answer': post.forum_id.karma_answer,
|
||||
'karma_accept': post.parent_id and post.parent_id.create_uid.id == uid and post.forum_id.karma_answer_accept_own or post.forum_id.karma_answer_accept_all,
|
||||
'karma_edit': post.create_uid.id == uid and post.forum_id.karma_edit_own or post.forum_id.karma_edit_all,
|
||||
'karma_close': post.create_uid.id == uid and post.forum_id.karma_close_own or post.forum_id.karma_close_all,
|
||||
'karma_unlink': post.create_uid.id == uid and post.forum_id.karma_unlink_own or post.forum_id.karma_unlink_all,
|
||||
'karma_upvote': post.forum_id.karma_upvote,
|
||||
'karma_downvote': post.forum_id.karma_downvote,
|
||||
'karma_comment': post.create_uid.id == uid and post.forum_id.karma_comment_own or post.forum_id.karma_comment_all,
|
||||
'karma_comment_convert': post.create_uid.id == uid and post.forum_id.karma_comment_convert_own or post.forum_id.karma_comment_convert_all,
|
||||
}
|
||||
res[post.id].update({
|
||||
'can_ask': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_ask'],
|
||||
'can_answer': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_answer'],
|
||||
'can_accept': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_accept'],
|
||||
'can_edit': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_edit'],
|
||||
'can_close': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_close'],
|
||||
'can_unlink': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_unlink'],
|
||||
'can_upvote': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_upvote'],
|
||||
'can_downvote': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_downvote'],
|
||||
'can_comment': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_comment'],
|
||||
'can_comment_convert': uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_comment_convert'],
|
||||
})
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Title'),
|
||||
'forum_id': fields.many2one('forum.forum', 'Forum', required=True),
|
||||
|
@ -151,7 +224,7 @@ class Post(osv.Model):
|
|||
'website_message_ids': fields.one2many(
|
||||
'mail.message', 'res_id',
|
||||
domain=lambda self: [
|
||||
'&', ('model', '=', self._name), ('type', '=', 'comment')
|
||||
'&', ('model', '=', self._name), ('type', 'in', ['email', 'comment'])
|
||||
],
|
||||
string='Post Messages', help="Comments on forum post",
|
||||
),
|
||||
|
@ -203,6 +276,26 @@ class Post(osv.Model):
|
|||
'closed_reason_id': fields.many2one('forum.post.reason', 'Reason'),
|
||||
'closed_uid': fields.many2one('res.users', 'Closed by', select=1),
|
||||
'closed_date': fields.datetime('Closed on', readonly=True),
|
||||
# karma
|
||||
'karma_ask': fields.function(_get_post_karma_rights, string='Karma to ask', type='integer', multi='_get_post_karma_rights'),
|
||||
'karma_accept': fields.function(_get_post_karma_rights, string='Karma to accept this answer', type='integer', multi='_get_post_karma_rights'),
|
||||
'karma_edit': fields.function(_get_post_karma_rights, string='Karma to edit', type='integer', multi='_get_post_karma_rights'),
|
||||
'karma_close': fields.function(_get_post_karma_rights, string='Karma to close', type='integer', multi='_get_post_karma_rights'),
|
||||
'karma_unlink': fields.function(_get_post_karma_rights, string='Karma to unlink', type='integer', multi='_get_post_karma_rights'),
|
||||
'karma_upvote': fields.function(_get_post_karma_rights, string='Karma to upvote', type='integer', multi='_get_post_karma_rights'),
|
||||
'karma_downvote': fields.function(_get_post_karma_rights, string='Karma to downvote', type='integer', multi='_get_post_karma_rights'),
|
||||
'karma_comment': fields.function(_get_post_karma_rights, string='Karma to comment', type='integer', multi='_get_post_karma_rights'),
|
||||
'karma_comment_convert': fields.function(_get_post_karma_rights, string='karma to convert as a comment', type='integer', multi='_get_post_karma_rights'),
|
||||
# access rights
|
||||
'can_ask': fields.function(_get_post_karma_rights, string='Can Ask', type='boolean', multi='_get_post_karma_rights'),
|
||||
'can_accept': fields.function(_get_post_karma_rights, string='Can Accept', type='boolean', multi='_get_post_karma_rights'),
|
||||
'can_edit': fields.function(_get_post_karma_rights, string='Can Edit', type='boolean', multi='_get_post_karma_rights'),
|
||||
'can_close': fields.function(_get_post_karma_rights, string='Can Close', type='boolean', multi='_get_post_karma_rights'),
|
||||
'can_unlink': fields.function(_get_post_karma_rights, string='Can Unlink', type='boolean', multi='_get_post_karma_rights'),
|
||||
'can_upvote': fields.function(_get_post_karma_rights, string='Can Upvote', type='boolean', multi='_get_post_karma_rights'),
|
||||
'can_downvote': fields.function(_get_post_karma_rights, string='Can Downvote', type='boolean', multi='_get_post_karma_rights'),
|
||||
'can_comment': fields.function(_get_post_karma_rights, string='Can Comment', type='boolean', multi='_get_post_karma_rights'),
|
||||
'can_comment_convert': fields.function(_get_post_karma_rights, string='Can Convert to Comment', type='boolean', multi='_get_post_karma_rights'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
@ -219,41 +312,93 @@ class Post(osv.Model):
|
|||
context = {}
|
||||
create_context = dict(context, mail_create_nolog=True)
|
||||
post_id = super(Post, self).create(cr, uid, vals, context=create_context)
|
||||
# post message + subtype depending on parent_id
|
||||
if vals.get("parent_id"):
|
||||
parent = self.browse(cr, SUPERUSER_ID, vals['parent_id'], context=context)
|
||||
body = _('<p><a href="forum/%s/question/%s">New Answer Posted</a></p>' % (slug(parent.forum_id), slug(parent)))
|
||||
self.message_post(cr, uid, parent.id, subject=_('Re: %s') % parent.name, body=body, subtype='website_forum.mt_answer_new', context=context)
|
||||
post = self.browse(cr, SUPERUSER_ID, post_id, context=context) # SUPERUSER_ID to avoid read access rights issues when creating
|
||||
# karma-based access
|
||||
if post.parent_id and not post.can_ask:
|
||||
raise KarmaError('Not enough karma to create a new question')
|
||||
elif not post.parent_id and not post.can_answer:
|
||||
raise KarmaError('Not enough karma to answer to a question')
|
||||
# messaging and chatter
|
||||
base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
|
||||
if post.parent_id:
|
||||
body = _(
|
||||
'<p>A new answer for <i>%s</i> has been posted. <a href="%s/forum/%s/question/%s">Click here to access the post.</a></p>' %
|
||||
(post.parent_id.name, base_url, slug(post.parent_id.forum_id), slug(post.parent_id))
|
||||
)
|
||||
self.message_post(cr, uid, post.parent_id.id, subject=_('Re: %s') % post.parent_id.name, body=body, subtype='website_forum.mt_answer_new', context=context)
|
||||
else:
|
||||
self.message_post(cr, uid, post_id, subject=vals.get('name', ''), body=_('New Question Created'), subtype='website_forum.mt_question_new', context=context)
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [uid], self.pool['forum.forum']._karma_gen_quest_new, context=context)
|
||||
body = _(
|
||||
'<p>A new question <i>%s</i> has been asked on %s. <a href="%s/forum/%s/question/%s">Click here to access the question.</a></p>' %
|
||||
(post.name, post.forum_id.name, base_url, slug(post.forum_id), slug(post))
|
||||
)
|
||||
self.message_post(cr, uid, post_id, subject=post.name, body=body, subtype='website_forum.mt_question_new', context=context)
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [uid], post.forum_id.karma_gen_question_new, context=context)
|
||||
return post_id
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
Forum = self.pool['forum.forum']
|
||||
# update karma when accepting/rejecting answers
|
||||
posts = self.browse(cr, uid, ids, context=context)
|
||||
if 'state' in vals:
|
||||
if vals['state'] in ['active', 'close'] and any(not post.can_close for post in posts):
|
||||
raise KarmaError('Not enough karma to close or reopen a post.')
|
||||
if 'active' in vals:
|
||||
if any(not post.can_unlink for post in posts):
|
||||
raise KarmaError('Not enough karma to delete or reactivate a post')
|
||||
if 'is_correct' in vals:
|
||||
if any(not post.can_accept for post in posts):
|
||||
raise KarmaError('Not enough karma to accept or refuse an answer')
|
||||
# update karma except for self-acceptance
|
||||
mult = 1 if vals['is_correct'] else -1
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
if vals['is_correct'] != post.is_correct:
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [post.create_uid.id], Forum._karma_gen_ans_accepted * mult, context=context)
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [uid], Forum._karma_gen_ans_accept * mult, context=context)
|
||||
if vals['is_correct'] != post.is_correct and post.create_uid.id != uid:
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [post.create_uid.id], post.forum_id.karma_gen_answer_accepted * mult, context=context)
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [uid], post.forum_id.karma_gen_answer_accept * mult, context=context)
|
||||
if any(key not in ['state', 'active', 'is_correct', 'closed_uid', 'closed_date', 'closed_reason_id'] for key in vals.keys()) and any(not post.can_edit for post in posts):
|
||||
raise KarmaError('Not enough karma to edit a post.')
|
||||
|
||||
res = super(Post, self).write(cr, uid, ids, vals, context=context)
|
||||
# if post content modify, notify followers
|
||||
if 'content' in vals or 'name' in vals:
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
for post in posts:
|
||||
if post.parent_id:
|
||||
body, subtype = _('Answer Edited'), 'website_forum.mt_answer_edit'
|
||||
obj_id = post.parent_id.id
|
||||
else:
|
||||
body, subtype = _('Question Edited'), 'website_forum.mt_question_edit'
|
||||
obj_id = post.id
|
||||
self.message_post(cr, uid, obj_id, body=_(body), subtype=subtype, context=context)
|
||||
self.message_post(cr, uid, obj_id, body=body, subtype=subtype, context=context)
|
||||
return res
|
||||
|
||||
def close(self, cr, uid, ids, reason_id, context=None):
|
||||
if any(post.parent_id for post in self.browse(cr, uid, ids, context=context)):
|
||||
return False
|
||||
return self.pool['forum.post'].write(cr, uid, ids, {
|
||||
'state': 'close',
|
||||
'closed_uid': uid,
|
||||
'closed_date': datetime.today().strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
'closed_reason_id': reason_id,
|
||||
}, context=context)
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
posts = self.browse(cr, uid, ids, context=context)
|
||||
if any(not post.can_unlink for post in posts):
|
||||
raise KarmaError('Not enough karma to unlink a post')
|
||||
# if unlinking an answer with accepted answer: remove provided karma
|
||||
for post in posts:
|
||||
if post.is_correct:
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [post.create_uid.id], post.forum_id.karma_gen_answer_accepted * -1, context=context)
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [uid], post.forum_id.karma_gen_answer_accept * -1, context=context)
|
||||
return super(Post, self).unlink(cr, uid, ids, context=context)
|
||||
|
||||
def vote(self, cr, uid, ids, upvote=True, context=None):
|
||||
posts = self.browse(cr, uid, ids, context=context)
|
||||
|
||||
if upvote and any(not post.can_upvote for post in posts):
|
||||
raise KarmaError('Not enough karma to upvote.')
|
||||
elif not upvote and any(not post.can_downvote for post in posts):
|
||||
raise KarmaError('Not enough karma to downvote.')
|
||||
|
||||
Vote = self.pool['forum.post.vote']
|
||||
vote_ids = Vote.search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], context=context)
|
||||
vote_ids = Vote.search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], limit=1, context=context)
|
||||
if vote_ids:
|
||||
for vote in Vote.browse(cr, uid, vote_ids, context=context):
|
||||
if upvote:
|
||||
|
@ -267,6 +412,89 @@ class Post(osv.Model):
|
|||
Vote.create(cr, uid, {'post_id': post_id, 'vote': new_vote}, context=context)
|
||||
return {'vote_count': self._get_vote_count(cr, uid, ids, None, None, context=context)[ids[0]]}
|
||||
|
||||
def convert_answer_to_comment(self, cr, uid, id, context=None):
|
||||
""" Tools to convert an answer (forum.post) to a comment (mail.message).
|
||||
The original post is unlinked and a new comment is posted on the question
|
||||
using the post create_uid as the comment's author. """
|
||||
post = self.browse(cr, uid, id, context=context)
|
||||
if not post.parent_id:
|
||||
return False
|
||||
|
||||
# karma-based action check: use the post field that computed own/all value
|
||||
if not post.can_comment_convert:
|
||||
raise KarmaError('Not enough karma to convert an answer to a comment')
|
||||
|
||||
# post the message
|
||||
question = post.parent_id
|
||||
values = {
|
||||
'author_id': post.create_uid.partner_id.id,
|
||||
'body': html2plaintext(post.content),
|
||||
'type': 'comment',
|
||||
'subtype': 'mail.mt_comment',
|
||||
'date': post.create_date,
|
||||
}
|
||||
message_id = self.pool['forum.post'].message_post(
|
||||
cr, uid, question.id,
|
||||
context=dict(context, mail_create_nosubcribe=True),
|
||||
**values)
|
||||
|
||||
# unlink the original answer, using SUPERUSER_ID to avoid karma issues
|
||||
self.pool['forum.post'].unlink(cr, SUPERUSER_ID, [post.id], context=context)
|
||||
|
||||
return message_id
|
||||
|
||||
def convert_comment_to_answer(self, cr, uid, message_id, default=None, context=None):
|
||||
""" Tool to convert a comment (mail.message) into an answer (forum.post).
|
||||
The original comment is unlinked and a new answer from the comment's author
|
||||
is created. Nothing is done if the comment's author already answered the
|
||||
question. """
|
||||
comment = self.pool['mail.message'].browse(cr, SUPERUSER_ID, message_id, context=context)
|
||||
post = self.pool['forum.post'].browse(cr, uid, comment.res_id, context=context)
|
||||
user = self.pool['res.users'].browse(cr, uid, uid, context=context)
|
||||
if not comment.author_id or not comment.author_id.user_ids: # only comment posted by users can be converted
|
||||
return False
|
||||
|
||||
# karma-based action check: must check the message's author to know if own / all
|
||||
karma_convert = comment.author_id.id == user.partner_id.id and post.forum_id.karma_comment_convert_own or post.forum_id.karma_comment_convert_all
|
||||
can_convert = uid == SUPERUSER_ID or user.karma >= karma_convert
|
||||
if not can_convert:
|
||||
raise KarmaError('Not enough karma to convert a comment to an answer')
|
||||
|
||||
# check the message's author has not already an answer
|
||||
question = post.parent_id if post.parent_id else post
|
||||
post_create_uid = comment.author_id.user_ids[0]
|
||||
if any(answer.create_uid.id == post_create_uid.id for answer in question.child_ids):
|
||||
return False
|
||||
|
||||
# create the new post
|
||||
post_values = {
|
||||
'forum_id': question.forum_id.id,
|
||||
'content': comment.body,
|
||||
'parent_id': question.id,
|
||||
}
|
||||
# done with the author user to have create_uid correctly set
|
||||
new_post_id = self.pool['forum.post'].create(cr, post_create_uid.id, post_values, context=context)
|
||||
|
||||
# delete comment
|
||||
self.pool['mail.message'].unlink(cr, SUPERUSER_ID, [comment.id], context=context)
|
||||
|
||||
return new_post_id
|
||||
|
||||
def unlink_comment(self, cr, uid, id, message_id, context=None):
|
||||
comment = self.pool['mail.message'].browse(cr, SUPERUSER_ID, message_id, context=context)
|
||||
post = self.pool['forum.post'].browse(cr, uid, id, context=context)
|
||||
user = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
if not comment.model == 'forum.post' or not comment.res_id == id:
|
||||
return False
|
||||
|
||||
# karma-based action check: must check the message's author to know if own or all
|
||||
karma_unlink = comment.author_id.id == user.partner_id.id and post.forum_id.karma_comment_unlink_own or post.forum_id.karma_comment_unlink_all
|
||||
can_unlink = uid == SUPERUSER_ID or user.karma >= karma_unlink
|
||||
if not can_unlink:
|
||||
raise KarmaError('Not enough karma to unlink a comment')
|
||||
|
||||
return self.pool['mail.message'].unlink(cr, SUPERUSER_ID, [message_id], context=context)
|
||||
|
||||
def set_viewed(self, cr, uid, ids, context=None):
|
||||
cr.execute("""UPDATE forum_post SET views = views+1 WHERE id IN %s""", (tuple(ids),))
|
||||
return True
|
||||
|
@ -300,31 +528,31 @@ class Vote(osv.Model):
|
|||
'vote': lambda *args: '1',
|
||||
}
|
||||
|
||||
def _get_karma_value(self, old_vote, new_vote, up_karma, down_karma):
|
||||
_karma_upd = {
|
||||
'-1': {'-1': 0, '0': -1 * down_karma, '1': -1 * down_karma + up_karma},
|
||||
'0': {'-1': 1 * down_karma, '0': 0, '1': up_karma},
|
||||
'1': {'-1': -1 * up_karma + down_karma, '0': -1 * up_karma, '1': 0}
|
||||
}
|
||||
return _karma_upd[old_vote][new_vote]
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
vote_id = super(Vote, self).create(cr, uid, vals, context=context)
|
||||
if vals.get('vote', '1') == '1':
|
||||
karma = self.pool['forum.forum']._karma_upvote
|
||||
elif vals.get('vote', '1') == '-1':
|
||||
karma = self.pool['forum.forum']._karma_downvote
|
||||
post = self.pool['forum.post'].browse(cr, uid, vals['post_id'], context=context)
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [post.create_uid.id], karma, context=context)
|
||||
vote = self.browse(cr, uid, vote_id, context=context)
|
||||
if vote.post_id.parent_id:
|
||||
karma_value = self._get_karma_value('0', vote.vote, vote.post_id.forum_id.karma_gen_answer_upvote, vote.post_id.forum_id.karma_gen_answer_downvote)
|
||||
else:
|
||||
karma_value = self._get_karma_value('0', vote.vote, vote.post_id.forum_id.karma_gen_question_upvote, vote.post_id.forum_id.karma_gen_question_downvote)
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [vote.post_id.create_uid.id], karma_value, context=context)
|
||||
return vote_id
|
||||
|
||||
def write(self, cr, uid, ids, values, context=None):
|
||||
def _get_karma_value(old_vote, new_vote, up_karma, down_karma):
|
||||
_karma_upd = {
|
||||
'-1': {'-1': 0, '0': -1 * down_karma, '1': -1 * down_karma + up_karma},
|
||||
'0': {'-1': 1 * down_karma, '0': 0, '1': up_karma},
|
||||
'1': {'-1': -1 * up_karma + down_karma, '0': -1 * up_karma, '1': 0}
|
||||
}
|
||||
return _karma_upd[old_vote][new_vote]
|
||||
if 'vote' in values:
|
||||
Forum = self.pool['forum.forum']
|
||||
for vote in self.browse(cr, uid, ids, context=context):
|
||||
if vote.post_id.parent_id:
|
||||
karma_value = _get_karma_value(vote.vote, values['vote'], Forum._karma_gen_upvote_ans, Forum._karma_gen_downvote_ans)
|
||||
karma_value = self._get_karma_value(vote.vote, values['vote'], vote.post_id.forum_id.karma_gen_answer_upvote, vote.post_id.forum_id.karma_gen_answer_downvote)
|
||||
else:
|
||||
karma_value = _get_karma_value(vote.vote, values['vote'], Forum._karma_gen_upvote_quest, Forum._karma_gen_downvote_quest)
|
||||
karma_value = self._get_karma_value(vote.vote, values['vote'], vote.post_id.forum_id.karma_gen_question_upvote, vote.post_id.forum_id.karma_gen_question_downvote)
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [vote.post_id.create_uid.id], karma_value, context=context)
|
||||
res = super(Vote, self).write(cr, uid, ids, values, context=context)
|
||||
return res
|
||||
|
|
|
@ -104,6 +104,14 @@ a.no-decoration {
|
|||
height: 1.2em !important;
|
||||
}
|
||||
|
||||
.oe_forum_alert {
|
||||
position: absolute;
|
||||
margin-top: -30px;
|
||||
margin-left: 90px;
|
||||
width: 300px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
button.btn-link.text-muted {
|
||||
color: #999999;
|
||||
}
|
||||
|
|
|
@ -84,5 +84,12 @@ a.no-decoration
|
|||
font: 1.2em "Helvetica Neue", Helvetica, Arial, sans-serif !important
|
||||
height: 1.2em !important
|
||||
|
||||
.oe_forum_alert
|
||||
position: absolute
|
||||
margin-top: -30px
|
||||
margin-left: 90px
|
||||
width: 300px
|
||||
z-index: 9999
|
||||
|
||||
button.btn-link.text-muted
|
||||
color: #999
|
||||
|
|
|
@ -1,28 +1,37 @@
|
|||
$(document).ready(function () {
|
||||
|
||||
$('.vote_up ,.vote_down').on('click', function (ev) {
|
||||
$('.karma_required').on('click', function (ev) {
|
||||
var karma = $(ev.currentTarget).data('karma');
|
||||
if (karma) {
|
||||
ev.preventDefault();
|
||||
var $warning = $('<div class="alert alert-danger alert-dismissable oe_forum_alert" id="karma_alert">'+
|
||||
'<button type="button" class="close notification_close" data-dismiss="alert" aria-hidden="true">×</button>'+
|
||||
karma + ' karma is required to perform this action. You can earn karma by answering questions or having '+
|
||||
'your answers upvoted by the community.</div>');
|
||||
var vote_alert = $(ev.currentTarget).parent().find("#vote_alert");
|
||||
if (vote_alert.length == 0) {
|
||||
$(ev.currentTarget).parent().append($warning);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('.vote_up,.vote_down').not('.karma_required').on('click', function (ev) {
|
||||
ev.preventDefault();
|
||||
var $link = $(ev.currentTarget);
|
||||
openerp.jsonRpc($link.data('href'), 'call', {})
|
||||
.then(function (data) {
|
||||
if (data['error']){
|
||||
if (data['error'] == 'own_post'){
|
||||
var $warning = $('<div class="alert alert-danger alert-dismissable" id="vote_alert" style="position:absolute; margin-top: -30px; margin-left: 90px;">'+
|
||||
var $warning = $('<div class="alert alert-danger alert-dismissable oe_forum_alert" id="vote_alert">'+
|
||||
'<button type="button" class="close notification_close" data-dismiss="alert" aria-hidden="true">×</button>'+
|
||||
'Sorry, you cannot vote for your own posts'+
|
||||
'</div>');
|
||||
} else if (data['error'] == 'anonymous_user'){
|
||||
var $warning = $('<div class="alert alert-danger alert-dismissable" id="vote_alert" style="position:absolute; margin-top: -30px; margin-left: 90px;">'+
|
||||
var $warning = $('<div class="alert alert-danger alert-dismissable oe_forum_alert" id="vote_alert">'+
|
||||
'<button type="button" class="close notification_close" data-dismiss="alert" aria-hidden="true">×</button>'+
|
||||
'Sorry you must be logged to vote'+
|
||||
'</div>');
|
||||
}
|
||||
else if (data['error'] == 'not_enough_karma') {
|
||||
var $warning = $('<div class="alert alert-danger alert-dismissable" id="vote_alert" style="max-width: 500px; position:absolute; margin-top: -30px; margin-left: 90px;">'+
|
||||
'<button type="button" class="close notification_close" data-dismiss="alert" aria-hidden="true">×</button>'+
|
||||
'Sorry, at least ' + data['karma'] + ' karma is required to vote. You can gain karma by answering questions and receiving votes.'+
|
||||
'</div>');
|
||||
}
|
||||
vote_alert = $link.parent().find("#vote_alert");
|
||||
if (vote_alert.length == 0) {
|
||||
$link.parent().append($warning);
|
||||
|
@ -44,21 +53,16 @@ $(document).ready(function () {
|
|||
return true;
|
||||
});
|
||||
|
||||
$('.accept_answer').on('click', function (ev) {
|
||||
$('.accept_answer').not('.karma_required').on('click', function (ev) {
|
||||
ev.preventDefault();
|
||||
var $link = $(ev.currentTarget);
|
||||
openerp.jsonRpc($link.data('href'), 'call', {}).then(function (data) {
|
||||
if (data['error']) {
|
||||
if (data['error'] == 'anonymous_user'){
|
||||
if (data['error'] == 'anonymous_user') {
|
||||
var $warning = $('<div class="alert alert-danger alert-dismissable" id="correct_answer_alert" style="position:absolute; margin-top: -30px; margin-left: 90px;">'+
|
||||
'<button type="button" class="close notification_close" data-dismiss="alert" aria-hidden="true">×</button>'+
|
||||
'Sorry, anonymous users cannot choose correct answer.'+
|
||||
'</div>');
|
||||
} else if (data['error'] == 'not_enough_karma') {
|
||||
var $warning = $('<div class="alert alert-danger alert-dismissable" id="vote_alert" style="max-width: 500px; position:absolute; margin-top: -30px; margin-left: 90px;">'+
|
||||
'<button type="button" class="close notification_close" data-dismiss="alert" aria-hidden="true">×</button>'+
|
||||
'Sorry, at least ' + data['karma'] + ' karma is required to accept this answer. You can gain karma by answering questions and receiving votes.'+
|
||||
'</div>');
|
||||
}
|
||||
correct_answer_alert = $link.parent().find("#correct_answer_alert");
|
||||
if (correct_answer_alert.length == 0) {
|
||||
|
|
|
@ -24,6 +24,27 @@
|
|||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="karma_ask"/>
|
||||
<field name="karma_edit_own"/>
|
||||
<field name="karma_edit_all"/>
|
||||
<field name="karma_close_own"/>
|
||||
<field name="karma_close_all"/>
|
||||
<field name="karma_unlink_own"/>
|
||||
<field name="karma_unlink_all"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="karma_upvote"/>
|
||||
<field name="karma_downvote"/>
|
||||
<field name="karma_answer_accept_own"/>
|
||||
<field name="karma_answer_accept_all"/>
|
||||
<field name="karma_editor_link_files"/>
|
||||
<field name="karma_editor_clickable_link"/>
|
||||
<field name="karma_comment_own"/>
|
||||
<field name="karma_comment_all"/>
|
||||
<field name="karma_comment_convert_own"/>
|
||||
<field name="karma_comment_convert_all"/>
|
||||
<field name="karma_comment_unlink_own"/>
|
||||
<field name="karma_comment_unlink_all"/>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<!-- helper -->
|
||||
<template id="link_button">
|
||||
<form method="POST" t-att-action="url">
|
||||
<button t-attf-class="fa btn-link #{classes}">
|
||||
<button t-attf-class="fa btn-link #{classes} #{karma and 'karma_required text-muted' or ''}" t-attf-data-karma="#{karma}">
|
||||
<t t-esc="label"/></button>
|
||||
</form>
|
||||
</template>
|
||||
|
@ -163,7 +163,7 @@
|
|||
<div t-if="question.child_count<=1" class="subtitle">Answer</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<div class="col-md-10 clearfix">
|
||||
<div class="question-name">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/question/#{ slug(question) }" t-field="question.name"/>
|
||||
<span t-if="not question.active"><b> [Deleted]</b></span>
|
||||
|
@ -419,10 +419,12 @@
|
|||
|
||||
<template id="vote">
|
||||
<div t-attf-class="box oe_grey">
|
||||
<a t-attf-class="vote_up fa fa-thumbs-up no-decoration #{post.user_vote == 1 and 'text-success' or ''}"
|
||||
<a t-attf-class="vote_up fa fa-thumbs-up no-decoration #{post.user_vote == 1 and 'text-success' or ''} #{((post.user_vote == 1 and not post.can_downvote) or not post.can_upvote) and 'karma_required' or ''}"
|
||||
t-attf-data-karma="#{post.user_vote == 1 and post.karma_downvote or post.karma_upvote}"
|
||||
t-attf-data-href="/forum/#{slug(post.forum_id)}/post/#{slug(post)}/upvote"/>
|
||||
<span id="vote_count" t-esc="post.vote_count"/>
|
||||
<a t-attf-class="vote_down fa fa-thumbs-down no-decoration #{post.user_vote == -1 and 'text-warning' or ''}"
|
||||
<a t-attf-class="vote_down fa fa-thumbs-down no-decoration #{post.user_vote == -1 and 'text-warning' or ''} #{((post.user_vote == -1 and not post.can_upvote) or not post.can_downvote) and 'karma_required' or ''}"
|
||||
t-attf-data-karma="#{post.user_vote == -1 and post.karma_uovote or post.karma_downvote}"
|
||||
t-attf-data-href="/forum/#{slug(post.forum_id)}/post/#{slug(post)}/downvote"/>
|
||||
<div t-if="vote_count > 1" class="subtitle">
|
||||
votes
|
||||
|
@ -449,7 +451,7 @@
|
|||
t-attf-class="favourite_question no-decoration fa fa-2x fa-star #{question.user_favourite and 'forum_favourite_question' or ''}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="col-md-10">
|
||||
<div class="col-md-10">
|
||||
<h1 class="mt0">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/question/#{ slug(question) }" t-field="question.name"/>
|
||||
<span t-if="not question.active"><b> [Deleted]</b></span>
|
||||
|
@ -466,11 +468,12 @@
|
|||
style="display: inline-block;"/></b>
|
||||
</t>
|
||||
<b>on <span t-field="question.closed_date"/></b>
|
||||
<div t-if="question.state == 'close' and user.karma>=500" class="mt16 mb24 text-center">
|
||||
<div class="mt16 mb24 text-center">
|
||||
<t t-call="website_forum.link_button">
|
||||
<t t-set="url" t-value="'/forum/' + slug(forum) + '/question/' + slug(question) + '/reopen'"/>
|
||||
<t t-set="label" t-value="'Reopen'"/>
|
||||
<t t-set="classes" t-value="'fa-arrow-right'"/>
|
||||
<t t-set="karma" t-value="not question.can_close and question.karma_close or 0"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -483,45 +486,52 @@
|
|||
</t>
|
||||
</div>
|
||||
<ul class="list-inline" id="options">
|
||||
<li t-if="user.id == question.create_uid.id or user.karma>=50">
|
||||
<a style="cursor: pointer" data-toggle="collapse" class="text-muted fa fa-comment-o"
|
||||
t-attf-data-target="#comment#{ question._name.replace('.','') + '-' + str(question.id) }">
|
||||
<li>
|
||||
<a style="cursor: pointer" data-toggle="collapse"
|
||||
t-attf-class="fa fa-comment-o #{not question.can_comment and 'karma_required text-muted' or ''}"
|
||||
t-attf-data-karma="#{not question.can_comment and question.karma_comment or 0}"
|
||||
t-attf-data-target="#comment#{ question._name.replace('.','') + '-' + str(question.id) }">
|
||||
Comment
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="question.state != 'close' and ((user.id == question.create_uid.id and can_close_own) or can_close_all)">
|
||||
<li t-if="question.state != 'close'">
|
||||
<t t-call="website_forum.link_button">
|
||||
<t t-set="url" t-value="'/forum/' + slug(forum) +'/question/' + slug(question) + '/ask_for_close'"/>
|
||||
<t t-set="label" t-value="'Close'"/>
|
||||
<t t-set="classes" t-vaoue="'text-muted fa-times'"/>
|
||||
<t t-set="classes" t-value="'fa-times'"/>
|
||||
<t t-set="karma" t-value="not question.can_close and question.karma_close or 0"/>
|
||||
</t>
|
||||
</li>
|
||||
<li t-if="question.state == 'close' and ((user.id == question.create_uid.id and can_close_own) or can_close_all)">
|
||||
<li t-if="question.state == 'close'">
|
||||
<t t-call="website_forum.link_button">
|
||||
<t t-set="url" t-value="'/forum/' + slug(forum) +'/question/' + slug(question) + '/reopen'"/>
|
||||
<t t-set="label" t-value="'Reopen'"/>
|
||||
<t t-set="classes" t-value="'text-muted fa-undo'"/>
|
||||
<t t-set="classes" t-value="'fa-undo'"/>
|
||||
<t t-set="karma" t-value="not question.can_close and question.karma_close or 0"/>
|
||||
</t>
|
||||
</li>
|
||||
<li t-if="(user.id == question.create_uid.id and can_edit_own) or can_edit_all">
|
||||
<li>
|
||||
<t t-call="website_forum.link_button">
|
||||
<t t-set="url" t-value="'/forum/' + slug(forum) +'/post/' + slug(question) + '/edit'"/>
|
||||
<t t-set="label" t-value="'Edit'"/>
|
||||
<t t-set="classes" t-value="'text-muted fa-edit'"/>
|
||||
<t t-set="classes" t-value="'fa-edit'"/>
|
||||
<t t-set="karma" t-value="not question.can_edit and question.karma_edit or 0"/>
|
||||
</t>
|
||||
</li>
|
||||
<li t-if="question.active and ((user.id == question.create_uid.id and can_unlink_own) or can_unlink_all)">
|
||||
<li t-if="question.active">
|
||||
<t t-call="website_forum.link_button">
|
||||
<t t-set="url" t-value="'/forum/' + slug(forum) +'/question/' + slug(question) + '/delete'"/>
|
||||
<t t-set="label" t-value="'Delete'"/>
|
||||
<t t-set="classes" t-value="'text-muted fa-trash-o'"/>
|
||||
<t t-set="classes" t-value="'fa-trash-o'"/>
|
||||
<t t-set="karma" t-value="not question.can_unlink and question.karma_unlink or 0"/>
|
||||
</t>
|
||||
</li>
|
||||
<li t-if="not question.active and ((user.id == question.create_uid.id and can_unlink_own) or can_unlink_all)">
|
||||
<li t-if="not question.active">
|
||||
<t t-call="website_forum.link_button">
|
||||
<t t-set="url" t-value="'/forum/' + slug(forum) +'/question/' + slug(question) + '/undelete'"/>
|
||||
<t t-set="label" t-value="'Undelete'"/>
|
||||
<t t-set="classes" t-value="'text-muted fa-trash-o'"/>
|
||||
<t t-set="classes" t-value="'fa-trash-o'"/>
|
||||
<t t-set="karma" t-value="not question.can_unlink and question.karma_unlink or 0"/>
|
||||
</t>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -565,7 +575,8 @@
|
|||
<t t-set="post" t-value="answer"/>
|
||||
</t>
|
||||
<div class="text-muted mt8">
|
||||
<a t-attf-class="accept_answer fa fa-2x fa-check-circle no-decoration #{answer.is_correct and 'oe_answer_true' or 'oe_answer_false'}"
|
||||
<a t-attf-class="accept_answer fa fa-2x fa-check-circle no-decoration #{answer.is_correct and 'oe_answer_true' or 'oe_answer_false'} #{not answer.can_accept and 'karma_required' or ''}"
|
||||
t-attf-data-karma="#{answer.karma_accept}"
|
||||
t-attf-data-href="/forum/#{slug(question.forum_id)}/post/#{slug(answer)}/toggle_correct"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -573,26 +584,32 @@
|
|||
<t t-raw="answer.content"/>
|
||||
<div class="mt16">
|
||||
<ul class="list-inline pull-right">
|
||||
<li t-if="user.id == answer.create_uid.id or user.karma>=50">
|
||||
<a style="cursor: pointer" data-toggle="collapse" class="text-muted fa fa-comment-o"
|
||||
t-attf-data-target="#comment#{ answer._name.replace('.','') + '-' + str(answer.id) }"> Comment
|
||||
<li>
|
||||
<a t-attf-class="fa fa-comment-o #{not answer.can_comment and 'karma_required text-muted' or ''}"
|
||||
t-attf-data-karma="#{not answer.can_comment and answer.karma_comment or 0}"
|
||||
style="cursor: pointer" data-toggle="collapse"
|
||||
t-attf-data-target="#comment#{ answer._name.replace('.','') + '-' + str(answer.id) }"> Comment
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="(user.id == answer.create_uid.id and can_edit_own) or can_edit_all">
|
||||
<a class="text-muted fa fa-edit" t-attf-href="/forum/#{slug(forum)}/post/#{slug(answer)}/edit"> Edit</a>
|
||||
<li>
|
||||
<a t-attf-class="fa fa-edit #{not answer.can_edit and 'karma_required text-muted' or ''}"
|
||||
t-attf-data-karma="#{not answer.can_edit and answer.karma_edit or 0}"
|
||||
t-attf-href="/forum/#{slug(forum)}/post/#{slug(answer)}/edit"> Edit</a>
|
||||
</li>
|
||||
<li t-if="(user.id == answer.create_uid.id and can_unlink_own) or can_unlink_all">
|
||||
<li>
|
||||
<t t-call="website_forum.link_button">
|
||||
<t t-set="url" t-value="'/forum/' + slug(forum) + '/post/' + slug(answer) + '/delete'"/>
|
||||
<t t-set="label" t-value="'Delete'"/>
|
||||
<t t-set="classes" t-value="'text-muted fa-trash-o'"/>
|
||||
<t t-set="classes" t-value="'fa-trash-o'"/>
|
||||
<t t-set="karma" t-value="not answer.can_unlink and answer.karma_unlink or 0"/>
|
||||
</t>
|
||||
</li>
|
||||
<li t-if="user.id == answer.create_uid.id">
|
||||
<li>
|
||||
<t t-call="website_forum.link_button">
|
||||
<t t-set="url" t-value="'/forum/' + slug(forum) + '/post/' + slug(answer) + '/convert_to_comment'"/>
|
||||
<t t-set="label" t-value="'Convert as a comment'"/>
|
||||
<t t-set="classes" t-value="'text-muted fa-magic'"/>
|
||||
<t t-set="classes" t-value="'fa-magic'"/>
|
||||
<t t-set="karma" t-value="not answer.can_comment_convert and answer.karma_comment_convert or 0"/>
|
||||
</t>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -610,7 +627,8 @@
|
|||
<t t-set="post" t-value="answer"/>
|
||||
</t>
|
||||
<div class="text-muted mt8">
|
||||
<a t-attf-class="accept_answer fa fa-2x fa-check-circle no-decoration #{answer.is_correct and 'oe_answer_true' or 'oe_answer_false'}"
|
||||
<a t-attf-class="accept_answer fa fa-2x fa-check-circle no-decoration #{answer.is_correct and 'oe_answer_true' or 'oe_answer_false'} #{not answer.can_accept and 'karma_required' or ''}"
|
||||
t-attf-data-karma="#{answer.karma_accept}"
|
||||
t-attf-data-href="/forum/#{slug(question.forum_id)}/post/#{slug(answer)}/toggle_correct"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -641,10 +659,12 @@
|
|||
t-attf-data-href="/forum/#{slug(forum)}/post/#{slug(object)}/comment/#{slug(message)}/delete"
|
||||
class="close comment_delete">&times;</button>
|
||||
<span t-field="message.body"/>
|
||||
<t t-set="required_karma" t-value="message.author_id.id == user.partner_id.id and object.forum_id.karma_comment_convert_own or object.forum_id.karma_comment_convert_all"/>
|
||||
<t t-call="website_forum.link_button">
|
||||
<t t-set="url" t-value="'/forum/' + slug(forum) + '/post/' + slug(object) + '/comment/' + slug(message) + '/convert_to_answer'"/>
|
||||
<t t-set="label" t-value="'Convert as an answer'"/>
|
||||
<t t-set="classes" t-value="'text-muted fa-magic pull-right'"/>
|
||||
<t t-set="karma" t-value="user.karma<required_karma and required_karma or 0"/>
|
||||
<t t-set="classes" t-value="'fa-magic pull-right'"/>
|
||||
</t>
|
||||
<a t-attf-href="/forum/#{slug(forum)}/partner/#{message.author_id.id}"
|
||||
t-field="message.author_id" t-field-options='{"widget": "contact", "country_image": true, "fields": ["name", "country_id"]}'
|
||||
|
|
Loading…
Reference in New Issue