[ADD] New module: website_forum, a clone of askbot / stackoverflow.
This module models a forum: questions, answers, voting and comment system, karma management. There is a link with gamification, allowing to use badges and reward users for their participation to the forum. Badges are temporarily commented out to ease the module beta-testing without having to wait for some gamification improvements. This merge also contains some fixes in access rights for gamification. bzr revid: tde@openerp.com-20140411183646-fmkeng9fzixjrqy5
This commit is contained in:
commit
9640e839d8
|
@ -23,7 +23,6 @@
|
|||
<field name="active" eval="False" />
|
||||
</record>
|
||||
|
||||
|
||||
<record id="badge_idea" model="gamification.badge">
|
||||
<field name="name">Brilliant</field>
|
||||
<field name="description">With your brilliant ideas, you are an inspiration to others.</field>
|
||||
|
@ -32,6 +31,16 @@
|
|||
<field name="rule_max_number">2</field>
|
||||
<field name="image" type="base64" file="gamification/static/img/badge_idea-image.png"/>
|
||||
</record>
|
||||
|
||||
<!-- subtype for badge allocation -->
|
||||
<record id="mt_badge_granted" model="mail.message.subtype">
|
||||
<field name="name">Badge Granted</field>
|
||||
<field name="res_model">res.users</field>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="hidden" eval="True"/>
|
||||
<field name="description">Badge Granted</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ class gamification_badge_user(osv.Model):
|
|||
_name = 'gamification.badge.user'
|
||||
_description = 'Gamification user badge'
|
||||
_order = "create_date desc"
|
||||
_rec_name = "badge_name"
|
||||
|
||||
_columns = {
|
||||
'user_id': fields.many2one('res.users', string="User", required=True),
|
||||
|
@ -62,7 +63,12 @@ class gamification_badge_user(osv.Model):
|
|||
template_id = self.pool['ir.model.data'].get_object(cr, uid, 'gamification', 'email_template_badge_received', context)
|
||||
for badge_user in self.browse(cr, uid, ids, context=context):
|
||||
body_html = temp_obj.render_template(cr, uid, template_id.body_html, 'gamification.badge.user', badge_user.id, context=context)
|
||||
res = user_obj.message_post(cr, uid, badge_user.user_id.id, body=body_html, context=context)
|
||||
res = user_obj.message_post(
|
||||
cr, uid, badge_user.user_id.id,
|
||||
body=body_html,
|
||||
subtype='gamification.mt_badge_granted',
|
||||
partner_ids=[badge_user.user_id.partner_id.id],
|
||||
context=context)
|
||||
return res
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
|
|
|
@ -4,4 +4,6 @@ goal_definition_portal,"Goal Definition Portal",gamification.model_gamification_
|
|||
challenge_portal,"Goal Challenge Portal",gamification.model_gamification_challenge,base.group_portal,1,0,0,0
|
||||
challenge_line_portal,"Challenge Line Portal",gamification.model_gamification_challenge_line,base.group_portal,1,0,0,0
|
||||
badge_portal,"Badge Portal",gamification.model_gamification_badge,base.group_portal,1,0,0,0
|
||||
badge_public,"Badge Public",gamification.model_gamification_badge,base.group_public,1,0,0,0
|
||||
badge_user_portal,"Badge-user Portal",gamification.model_gamification_badge_user,base.group_portal,1,1,1,0
|
||||
badge_user_public,"Badge-user Public",gamification.model_gamification_badge_user,base.group_public,1,0,0,0
|
||||
|
|
|
|
@ -0,0 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import controllers
|
||||
import models
|
|
@ -0,0 +1,58 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2014-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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Forum',
|
||||
'category': 'Website',
|
||||
'summary': 'Forum, FAQ, Q&A',
|
||||
'version': '1.0',
|
||||
'description': """
|
||||
Ask questions, get answers, no distractions
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'depends': [
|
||||
'auth_signup',
|
||||
'gamification',
|
||||
'website_mail',
|
||||
'website_partner'
|
||||
],
|
||||
'data': [
|
||||
'data/forum_data.xml',
|
||||
'views/forum.xml',
|
||||
'views/res_users.xml',
|
||||
'views/website_forum.xml',
|
||||
'views/ir_qweb.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'data/badges_question.xml',
|
||||
'data/badges_answer.xml',
|
||||
'data/badges_participation.xml',
|
||||
'data/badges_moderation.xml',
|
||||
],
|
||||
'qweb': [
|
||||
'static/src/xml/*.xml'
|
||||
],
|
||||
'demo': [
|
||||
'data/forum_demo.xml',
|
||||
],
|
||||
'css': ['static/src/css/website_forum.css'],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import main
|
|
@ -0,0 +1,550 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime
|
||||
import werkzeug.urls
|
||||
import simplejson
|
||||
|
||||
from openerp import tools
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.addons.web import http
|
||||
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()
|
||||
|
||||
|
||||
class WebsiteForum(http.Controller):
|
||||
_post_per_page = 10
|
||||
_user_per_page = 30
|
||||
|
||||
def _get_notifications(self):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Message = request.registry['mail.message']
|
||||
badge_st_id = request.registry['ir.model.data'].xmlid_to_res_id(cr, uid, 'gamification.mt_badge_granted')
|
||||
if badge_st_id:
|
||||
msg_ids = Message.search(cr, uid, [('subtype_id', '=', badge_st_id), ('to_read', '=', True)], context=context)
|
||||
msg = Message.browse(cr, uid, msg_ids, context=context)
|
||||
else:
|
||||
msg = list()
|
||||
return msg
|
||||
|
||||
def _prepare_forum_values(self, forum=None, **kwargs):
|
||||
user = request.registry['res.users'].browse(request.cr, request.uid, request.uid, context=request.context)
|
||||
public_uid = request.registry['website'].get_public_user(request.cr, request.uid, request.context)
|
||||
values = {'user': user, 'is_public_user': user.id == public_uid,
|
||||
'notifications': self._get_notifications(),
|
||||
'header': kwargs.get('header', dict()),
|
||||
'searches': kwargs.get('searches', dict())}
|
||||
if forum:
|
||||
values['forum'] = forum
|
||||
elif kwargs.get('forum_id'):
|
||||
values['forum'] = request.registry['forum.forum'].browse(request.cr, request.uid, kwargs.pop('forum_id'), context=request.context)
|
||||
values.update(kwargs)
|
||||
return values
|
||||
|
||||
# Forum
|
||||
# --------------------------------------------------
|
||||
|
||||
@http.route(['/forum'], type='http', auth="public", website=True, multilang=True)
|
||||
def forum(self, **kwargs):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Forum = request.registry['forum.forum']
|
||||
obj_ids = Forum.search(cr, uid, [], context=context)
|
||||
forums = Forum.browse(cr, uid, obj_ids, context=context)
|
||||
return request.website.render("website_forum.forum_all", {'forums': forums})
|
||||
|
||||
@http.route('/forum/new', type='http', auth="user", multilang=True, website=True)
|
||||
def forum_create(self, forum_name="New Forum", **kwargs):
|
||||
forum_id = request.registry['forum.forum'].create(request.cr, request.uid, {
|
||||
'name': forum_name,
|
||||
}, context=request.context)
|
||||
return request.redirect("/forum/%s" % slug(forum_id))
|
||||
|
||||
@http.route('/forum/notification_read', type='json', auth="user", multilang=True, methods=['POST'], website=True)
|
||||
def notification_read(self, **kwargs):
|
||||
request.registry['mail.message'].set_message_read(request.cr, request.uid, [int(kwargs.get('notification_id'))], read=True, context=request.context)
|
||||
return True
|
||||
|
||||
@http.route(['/forum/<model("forum.forum"):forum>',
|
||||
'/forum/<model("forum.forum"):forum>/page/<int:page>',
|
||||
'/forum/<model("forum.forum"):forum>/tag/<model("forum.tag"):tag>/questions'
|
||||
], type='http', auth="public", website=True, multilang=True)
|
||||
def questions(self, forum, tag=None, page=1, filters='all', sorting='date', search='', **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Post = request.registry['forum.post']
|
||||
user = request.registry['res.users'].browse(cr, uid, uid, context=context)
|
||||
|
||||
domain = [('forum_id', '=', forum.id), ('parent_id', '=', False)]
|
||||
if search:
|
||||
domain += ['|', ('name', 'ilike', search), ('content', 'ilike', search)]
|
||||
if tag:
|
||||
domain += [('tag_ids', 'in', tag.id)]
|
||||
if filters == 'unanswered':
|
||||
domain += [('child_ids', '=', False)]
|
||||
elif filters == 'followed':
|
||||
domain += [('message_follower_ids', '=', user.partner_id.id)]
|
||||
else:
|
||||
filters = 'all'
|
||||
|
||||
if sorting == 'answered':
|
||||
order = 'child_count desc'
|
||||
elif sorting == 'vote':
|
||||
order = 'vote_count desc'
|
||||
else:
|
||||
sorting = 'date'
|
||||
order = 'write_date desc'
|
||||
|
||||
question_count = Post.search(cr, uid, domain, count=True, context=context)
|
||||
pager = request.website.pager(url="/forum/%s" % slug(forum), total=question_count, page=page, step=self._post_per_page, scope=self._post_per_page)
|
||||
|
||||
obj_ids = Post.search(cr, uid, domain, limit=self._post_per_page, offset=pager['offset'], order=order, context=context)
|
||||
question_ids = Post.browse(cr, uid, obj_ids, context=context)
|
||||
|
||||
values = self._prepare_forum_values(forum=forum, searches=post)
|
||||
values.update({
|
||||
'question_ids': question_ids,
|
||||
'pager': pager,
|
||||
'tag': tag,
|
||||
'filters': filters,
|
||||
'sorting': sorting,
|
||||
'search': search,
|
||||
})
|
||||
return request.website.render("website_forum.forum_index", values)
|
||||
|
||||
@http.route(['/forum/<model("forum.forum"):forum>/faq'], type='http', auth="public", website=True, multilang=True)
|
||||
def forum_faq(self, forum, **post):
|
||||
values = self._prepare_forum_values(forum=forum, searches=dict(), **post)
|
||||
return request.website.render("website_forum.faq", values)
|
||||
|
||||
@http.route('/forum/get_tags', type='http', auth="public", multilang=True, methods=['GET'], website=True)
|
||||
def tag_read(self, **post):
|
||||
tags = request.registry['forum.tag'].search_read(request.cr, request.uid, [], ['name'], context=request.context)
|
||||
data = [tag['name'] for tag in tags]
|
||||
return simplejson.dumps(data)
|
||||
|
||||
@http.route(['/forum/<model("forum.forum"):forum>/tag'], type='http', auth="public", website=True, multilang=True)
|
||||
def tags(self, forum, page=1, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Tag = request.registry['forum.tag']
|
||||
obj_ids = Tag.search(cr, uid, [('forum_id', '=', forum.id)], limit=None, context=context)
|
||||
tags = Tag.browse(cr, uid, obj_ids, context=context)
|
||||
values = self._prepare_forum_values(forum=forum, searches={'tags': True}, **post)
|
||||
values.update({
|
||||
'tags': tags,
|
||||
})
|
||||
return request.website.render("website_forum.tag", values)
|
||||
|
||||
# Questions
|
||||
# --------------------------------------------------
|
||||
|
||||
@http.route(['/forum/<model("forum.forum"):forum>/ask'], type='http', auth="public", website=True, multilang=True)
|
||||
def question_ask(self, forum, **post):
|
||||
if not request.session.uid:
|
||||
return login_redirect()
|
||||
values = self._prepare_forum_values(forum=forum, searches={}, header={'ask_hide': True})
|
||||
return request.website.render("website_forum.ask_question", values)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/new', type='http', auth="user", multilang=True, methods=['POST'], website=True)
|
||||
def question_create(self, forum, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Tag = request.registry['forum.tag']
|
||||
question_tag_ids = []
|
||||
if post.get('question_tags').strip('[]'):
|
||||
tags = post.get('question_tags').strip('[]').replace('"', '').split(",")
|
||||
for tag in tags:
|
||||
tag_ids = Tag.search(cr, uid, [('name', '=', tag)], context=context)
|
||||
if tag_ids:
|
||||
question_tag_ids.append((4, tag_ids[0]))
|
||||
else:
|
||||
question_tag_ids.append((0, 0, {'name': tag, 'forum_id': forum.id}))
|
||||
|
||||
new_question_id = request.registry['forum.post'].create(
|
||||
request.cr, request.uid, {
|
||||
'forum_id': forum.id,
|
||||
'name': post.get('question_name'),
|
||||
'content': post.get('content'),
|
||||
'tag_ids': question_tag_ids,
|
||||
}, context=context)
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), new_question_id))
|
||||
|
||||
@http.route(['/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>'], type='http', auth="public", website=True, multilang=True)
|
||||
def question(self, forum, question, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
# increment view counter
|
||||
request.registry['forum.post'].set_viewed(cr, SUPERUSER_ID, [question.id], context=context)
|
||||
|
||||
filters = 'question'
|
||||
values = self._prepare_forum_values(forum=forum, searches=post)
|
||||
values.update({
|
||||
'question': question,
|
||||
'header': {'question_data': True},
|
||||
'filters': filters,
|
||||
'reversed': reversed,
|
||||
})
|
||||
return request.website.render("website_forum.post_description_full", values)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>/toggle_favourite', type='json', auth="user", multilang=True, methods=['POST'], website=True)
|
||||
def question_toggle_favorite(self, forum, question, **post):
|
||||
if not request.session.uid:
|
||||
return {'error': 'anonymous_user'}
|
||||
# TDE: add check for not public
|
||||
favourite = False if question.user_favourite else True
|
||||
if favourite:
|
||||
favourite_ids = [(4, request.uid)]
|
||||
else:
|
||||
favourite_ids = [(3, request.uid)]
|
||||
request.registry['forum.post'].write(request.cr, request.uid, [question.id], {'favourite_ids': favourite_ids}, context=request.context)
|
||||
return favourite
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>/ask_for_close', type='http', auth="user", multilang=True, website=True)
|
||||
def question_ask_for_close(self, forum, question, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Reason = request.registry['forum.post.reason']
|
||||
reason_ids = Reason.search(cr, uid, [], context=context)
|
||||
reasons = Reason.browse(cr, uid, reason_ids, context)
|
||||
|
||||
values = self._prepare_forum_values(**post)
|
||||
values.update({
|
||||
'post': question,
|
||||
'forum': forum,
|
||||
'reasons': reasons,
|
||||
})
|
||||
return request.website.render("website_forum.close_question", values)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>/edit_answer', type='http', auth="user", website=True, multilang=True)
|
||||
def question_edit_answer(self, forum, question, **kwargs):
|
||||
for record in question.child_ids:
|
||||
if record.create_uid.id == request.uid:
|
||||
answer = record
|
||||
break
|
||||
return werkzeug.utils.redirect("/forum/%s/post/%s/edit" % (slug(forum), slug(answer)))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/question/<model("forum.post"):question>/close', type='http', auth="user", multilang=True, methods=['POST'], website=True)
|
||||
def question_close(self, forum, question, **post):
|
||||
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': 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", multilang=True, website=True)
|
||||
def question_reopen(self, forum, question, **kwarg):
|
||||
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", multilang=True, website=True)
|
||||
def question_delete(self, forum, question, **kwarg):
|
||||
#instead of unlink record just change 'active' to false so user can undelete it.
|
||||
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", multilang=True, website=True)
|
||||
def question_undelete(self, forum, question, **kwarg):
|
||||
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)))
|
||||
|
||||
# Post
|
||||
# --------------------------------------------------
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/new', type='http', auth="public", multilang=True, methods=['POST'], website=True)
|
||||
def post_new(self, forum, post, **kwargs):
|
||||
if not request.session.uid:
|
||||
return login_redirect()
|
||||
request.registry['forum.post'].create(
|
||||
request.cr, request.uid, {
|
||||
'forum_id': forum.id,
|
||||
'parent_id': post.id,
|
||||
'content': kwargs.get('content'),
|
||||
}, context=request.context)
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(post)))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/comment', type='http', auth="public", methods=['POST'], website=True)
|
||||
def post_comment(self, forum, post, **kwargs):
|
||||
if not request.session.uid:
|
||||
return login_redirect()
|
||||
question = post.parent_id if post.parent_id else post
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
if kwargs.get('comment') and post.forum_id.id == forum.id:
|
||||
# TDE FIXME: check that post_id is the question or one of its answers
|
||||
if request.registry['res.users'].has_group(cr, uid, 'website_mail.group_comment'):
|
||||
request.registry['forum.post'].message_post(
|
||||
cr, uid, post.id,
|
||||
body=kwargs.get('comment'),
|
||||
type='comment',
|
||||
subtype='mt_comment',
|
||||
context=dict(context, mail_create_nosubcribe=True))
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/toggle_correct', type='json', auth="public", website=True)
|
||||
def post_toggle_correct(self, forum, post, **kwargs):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
if not request.session.uid:
|
||||
return {'error': 'anonymous_user'}
|
||||
# if user have not access to accept answer then reise warning
|
||||
if post.parent_id is False or post.parent_id.create_uid.id != uid:
|
||||
return {'error': 'own_post'}
|
||||
|
||||
# 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)
|
||||
request.registry['forum.post'].write(cr, uid, [post.id, post.parent_id.id], {'is_correct': not post.is_correct}, context=context)
|
||||
return not post.is_correct
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/delete', type='http', auth="user", multilang=True, website=True)
|
||||
def post_delete(self, forum, post, **kwargs):
|
||||
question = post.parent_id
|
||||
request.registry['forum.post'].unlink(request.cr, request.uid, [post.id], context=request.context)
|
||||
if question:
|
||||
werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/edit', type='http', auth="user", website=True, multilang=True)
|
||||
def post_edit(self, forum, post, **kwargs):
|
||||
tags = ""
|
||||
for tag_name in post.tag_ids:
|
||||
tags += tag_name.name + ","
|
||||
values = self._prepare_forum_values(forum=forum)
|
||||
values.update({
|
||||
'tags': tags,
|
||||
'post': post,
|
||||
'is_answer': bool(post.parent_id),
|
||||
'searches': kwargs
|
||||
})
|
||||
return request.website.render("website_forum.edit_post", values)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/save', type='http', auth="user", multilang=True, methods=['POST'], website=True)
|
||||
def post_save(self, forum, post, **kwargs):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
question_tags = []
|
||||
if kwargs.get('question_tag') and kwargs.get('question_tag').strip('[]'):
|
||||
Tag = request.registry['forum.tag']
|
||||
tags = kwargs.get('question_tag').strip('[]').replace('"', '').split(",")
|
||||
for tag in tags:
|
||||
tag_ids = Tag.search(cr, uid, [('name', '=', tag)], context=context)
|
||||
if tag_ids:
|
||||
question_tags += tag_ids
|
||||
else:
|
||||
new_tag = Tag.create(cr, uid, {'name': tag, 'forum_id': forum.id}, context=context)
|
||||
question_tags.append(new_tag)
|
||||
vals = {
|
||||
'tag_ids': [(6, 0, question_tags)],
|
||||
'name': kwargs.get('question_name'),
|
||||
'content': kwargs.get('content'),
|
||||
}
|
||||
request.registry['forum.post'].write(cr, uid, [post.id], vals, context=context)
|
||||
question = post.parent_id if post.parent_id else post
|
||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/upvote', type='json', auth="public", multilang=True, website=True)
|
||||
def post_upvote(self, forum, post, **kwargs):
|
||||
# check for karma and not self vote
|
||||
if not request.session.uid:
|
||||
return {'error': 'anonymous_user'}
|
||||
if request.uid == post.create_uid.id:
|
||||
return {'error': 'own_post'}
|
||||
user = request.registry['res.users'].browse(request.cr, SUPERUSER_ID, request.uid, context=request.context)
|
||||
if user.karma <= 5:
|
||||
return {'error': 'not_enough_karma', 'karma': 5}
|
||||
return request.registry['forum.post'].vote(request.cr, request.uid, [post.id], upvote=True, context=request.context)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/downvote', type='json', auth="public", multilang=True, website=True)
|
||||
def post_downvote(self, forum, post, **kwargs):
|
||||
if not request.session.uid:
|
||||
return {'error': 'anonymous_user'}
|
||||
if request.uid == post.create_uid.id:
|
||||
return {'error': 'own_post'}
|
||||
user = request.registry['res.users'].browse(request.cr, SUPERUSER_ID, request.uid, context=request.context)
|
||||
if user.karma <= 50:
|
||||
return {'error': 'not_enough_karma', 'karma': 50}
|
||||
return request.registry['forum.post'].vote(request.cr, request.uid, [post.id], upvote=False, context=request.context)
|
||||
|
||||
# User
|
||||
# --------------------------------------------------
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/users', type='http', auth="public", website=True, multilang=True)
|
||||
def users(self, forum, page=1, **searches):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
User = request.registry['res.users']
|
||||
|
||||
step = 30
|
||||
tag_count = User.search(cr, SUPERUSER_ID, [('karma', '>', 1)], count=True, context=context)
|
||||
pager = request.website.pager(url="/forum/users", total=tag_count, page=page, step=step, scope=30)
|
||||
|
||||
obj_ids = User.search(cr, SUPERUSER_ID, [('karma', '>', 1)], limit=step, offset=pager['offset'], context=context)
|
||||
users = User.browse(cr, SUPERUSER_ID, obj_ids, context=context)
|
||||
searches['users'] = 'True'
|
||||
|
||||
values = self._prepare_forum_values(forum=forum, searches=searches)
|
||||
values .update({
|
||||
'users': users,
|
||||
'notifications': self._get_notifications(),
|
||||
'pager': pager,
|
||||
})
|
||||
|
||||
return request.website.render("website_forum.users", values)
|
||||
|
||||
@http.route(['/forum/<model("forum.forum"):forum>/user/<int:user_id>'], type='http', auth="public", website=True, multilang=True)
|
||||
def open_user(self, forum, user_id=0, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
User = request.registry['res.users']
|
||||
Post = request.registry['forum.post']
|
||||
Vote = request.registry['forum.post.vote']
|
||||
Activity = request.registry['mail.message']
|
||||
Followers = request.registry['mail.followers']
|
||||
Data = request.registry["ir.model.data"]
|
||||
|
||||
user_id = User.search(cr, SUPERUSER_ID, [('id', '=', user_id), ('karma', '>', '1')], context=context)
|
||||
if not user_id:
|
||||
return werkzeug.utils.redirect("/forum/%s" % slug(forum))
|
||||
user = User.browse(cr, SUPERUSER_ID, user_id[0], context=context)
|
||||
|
||||
# questions and answers by user
|
||||
user_questions, user_answers = [], []
|
||||
user_post_ids = Post.search(
|
||||
cr, uid, [
|
||||
('forum_id', '=', forum.id), ('create_uid', '=', user.id),
|
||||
'|', ('active', '=', False), ('active', '=', True)], context=context)
|
||||
user_posts = Post.browse(cr, uid, user_post_ids, context=context)
|
||||
for record in user_posts:
|
||||
if record.parent_id:
|
||||
user_answers.append(record)
|
||||
else:
|
||||
user_questions.append(record)
|
||||
|
||||
# showing questions which user following
|
||||
obj_ids = Followers.search(cr, SUPERUSER_ID, [('res_model', '=', 'forum.post'), ('partner_id', '=', user.partner_id.id)], context=context)
|
||||
post_ids = [follower.res_id for follower in Followers.browse(cr, SUPERUSER_ID, obj_ids, context=context)]
|
||||
que_ids = Post.search(cr, uid, [('id', 'in', post_ids), ('forum_id', '=', forum.id), ('parent_id', '=', False)], context=context)
|
||||
followed = Post.browse(cr, uid, que_ids, context=context)
|
||||
|
||||
#showing Favourite questions of user.
|
||||
fav_que_ids = Post.search(cr, uid, [('favourite_ids', '=', user.id), ('forum_id', '=', forum.id), ('parent_id', '=', False)], context=context)
|
||||
favourite = Post.browse(cr, uid, fav_que_ids, context=context)
|
||||
|
||||
#votes which given on users questions and answers.
|
||||
data = Vote.read_group(cr, uid, [('post_id.forum_id', '=', forum.id), ('post_id.create_uid', '=', user.id)], ["vote"], groupby=["vote"], context=context)
|
||||
up_votes, down_votes = 0, 0
|
||||
for rec in data:
|
||||
if rec['vote'] == '1':
|
||||
up_votes = rec['vote_count']
|
||||
elif rec['vote'] == '-1':
|
||||
down_votes = rec['vote_count']
|
||||
total_votes = up_votes + down_votes
|
||||
|
||||
#Votes which given by users on others questions and answers.
|
||||
post_votes = Vote.search(cr, uid, [('user_id', '=', user.id)], context=context)
|
||||
vote_ids = Vote.browse(cr, uid, post_votes, context=context)
|
||||
|
||||
#activity by user.
|
||||
model, comment = Data.get_object_reference(cr, uid, 'mail', 'mt_comment')
|
||||
activity_ids = Activity.search(cr, uid, [('res_id', 'in', user_post_ids), ('model', '=', 'forum.post'), ('subtype_id', '!=', comment)], context=context)
|
||||
activities = Activity.browse(cr, uid, activity_ids, context=context)
|
||||
|
||||
posts = {}
|
||||
for act in activities:
|
||||
posts[act.res_id] = True
|
||||
posts_ids = Post.browse(cr, uid, posts.keys(), context=context)
|
||||
posts = dict(map(lambda x: (x.id, (x.parent_id or x, x.parent_id and x or False)), posts_ids))
|
||||
|
||||
post['users'] = 'True'
|
||||
|
||||
values = self._prepare_forum_values(**post)
|
||||
values.update({
|
||||
'uid': uid,
|
||||
'user': user,
|
||||
'main_object': user,
|
||||
'searches': post,
|
||||
'forum': forum,
|
||||
'questions': user_questions,
|
||||
'answers': user_answers,
|
||||
'followed': followed,
|
||||
'favourite': favourite,
|
||||
'total_votes': total_votes,
|
||||
'up_votes': up_votes,
|
||||
'down_votes': down_votes,
|
||||
'activities': activities,
|
||||
'posts': posts,
|
||||
'vote_post': vote_ids,
|
||||
})
|
||||
return request.website.render("website_forum.user_detail_full", values)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/user/<model("res.users"):user>/edit', type='http', auth="user", multilang=True, website=True)
|
||||
def edit_profile(self, forum, user, **kwargs):
|
||||
country = request.registry['res.country']
|
||||
country_ids = country.search(request.cr, SUPERUSER_ID, [], context=request.context)
|
||||
countries = country.browse(request.cr, SUPERUSER_ID, country_ids, context=request.context)
|
||||
values = self._prepare_forum_values(forum=forum, searches=kwargs)
|
||||
values.update({
|
||||
'countries': countries,
|
||||
'notifications': self._get_notifications(),
|
||||
})
|
||||
return request.website.render("website_forum.edit_profile", values)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/user/<model("res.users"):user>/save', type='http', auth="user", multilang=True, website=True)
|
||||
def save_edited_profile(self, forum, user, **kwargs):
|
||||
request.registry['res.users'].write(request.cr, request.uid, [user.id], {
|
||||
'name': kwargs.get('name'),
|
||||
'website': kwargs.get('website'),
|
||||
'email': kwargs.get('email'),
|
||||
'city': kwargs.get('city'),
|
||||
'country_id': kwargs.get('country'),
|
||||
'website_description': kwargs.get('description'),
|
||||
}, context=request.context)
|
||||
return werkzeug.utils.redirect("/forum/%s/user/%d" % (slug(forum), user.id))
|
||||
|
||||
# Badges
|
||||
# --------------------------------------------------
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/badge', type='http', auth="public", website=True, multilang=True)
|
||||
def badges(self, forum, **searches):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Badge = request.registry['gamification.badge']
|
||||
badge_ids = Badge.search(cr, SUPERUSER_ID, [('challenge_ids.category', '=', 'forum')], context=context)
|
||||
badges = Badge.browse(cr, uid, badge_ids, context=context)
|
||||
values = self._prepare_forum_values(forum=forum, searches={'badges': True})
|
||||
values.update({
|
||||
'badges': badges,
|
||||
})
|
||||
return request.website.render("website_forum.badge", values)
|
||||
|
||||
@http.route(['/forum/<model("forum.forum"):forum>/badge/<model("gamification.badge"):badge>'], type='http', auth="public", website=True, multilang=True)
|
||||
def badge_users(self, forum, badge, **kwargs):
|
||||
user_ids = [badge_user.user_id.id for badge_user in badge.owner_ids]
|
||||
users = request.registry['res.users'].browse(request.cr, SUPERUSER_ID, user_ids, context=request.context)
|
||||
|
||||
values = self._prepare_forum_values(forum=forum, searches={'badges': True})
|
||||
values.update({
|
||||
'badge': badge,
|
||||
'users': users,
|
||||
})
|
||||
return request.website.render("website_forum.badge_user", values)
|
||||
|
||||
# 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", multilang=True, website=True)
|
||||
def convert_comment_to_answer(self, forum, post, comment, **kwarg):
|
||||
values = {
|
||||
'content': comment.body,
|
||||
}
|
||||
request.registry['mail.message'].unlink(request.cr, request.uid, [comment.id], context=request.context)
|
||||
question = post.parent_id if post.parent_id else post
|
||||
return self.post_new(forum, question, **values)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/convert_to_comment', type='http', auth="user", multilang=True, 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)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/comment/<model("mail.message"):comment>/delete', type='json', auth="user", multilang=True, 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
|
|
@ -0,0 +1,263 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- QUALITY (VOTES) -->
|
||||
<!-- Teacher: at least 3 upvotes -->
|
||||
<!-- <record id="badge_a_1" model="gamification.badge">
|
||||
<field name="name">Teacher</field>
|
||||
<field name="description">Received at least 3 upvote for an answer for the first time</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_teacher">
|
||||
<field name="name">Teacher</field>
|
||||
<field name="description">Received at least 3 upvote for an answer for the first time</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '!=', False), ('vote_count', '>=', 3)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_teacher">
|
||||
<field name="name">Teacher</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_a_1')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_teacher">
|
||||
<field name="definition_id" eval="ref('definition_teacher')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_teacher')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Nice: at least 4 upvotes -->
|
||||
<!-- <record id="badge_a_2" model="gamification.badge">
|
||||
<field name="name">Nice Answer</field>
|
||||
<field name="description">Answer voted up 4 times</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_nice_answer">
|
||||
<field name="name">Nice Answer</field>
|
||||
<field name="description">Answer voted up 4 times</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '!=', False), ('vote_count', '>=', 4)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_nice_answer">
|
||||
<field name="name">Nice Answer</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_a_2')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_nice_answer">
|
||||
<field name="definition_id" eval="ref('definition_nice_answer')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_nice_answer')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Good: at least 6 upvotes -->
|
||||
<!-- <record id="badge_a_3" model="gamification.badge">
|
||||
<field name="name">Good Answer</field>
|
||||
<field name="description">Answer voted up 6 times</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_good_answer">
|
||||
<field name="name">Good Answer</field>
|
||||
<field name="description">Answer voted up 6 times</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '!=', False), ('vote_count', '>=', 6)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_good_answer">
|
||||
<field name="name">Good Answer</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_a_3')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_good_answer">
|
||||
<field name="definition_id" eval="ref('definition_good_answer')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_good_answer')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Great: at least 15 upvotes -->
|
||||
<!-- <record id="badge_a_4" model="gamification.badge">
|
||||
<field name="name">Great Answer</field>
|
||||
<field name="description">Answer voted up 15 times</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_great_answer">
|
||||
<field name="name">Great Answer</field>
|
||||
<field name="description">Answer voted up 15 times</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '!=', False), ('vote_count', '>=', 15)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_great_answer">
|
||||
<field name="name">Great Answer</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_a_4')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_great_answer">
|
||||
<field name="definition_id" eval="ref('definition_great_answer')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_great_answer')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
|
||||
<!-- ACCEPTANCE -->
|
||||
<!-- Enlightened: at least 3 upvotes for an accepted answer -->
|
||||
<!-- <record id="badge_a_5" model="gamification.badge">
|
||||
<field name="name">Enlightened</field>
|
||||
<field name="description">Answer was accepted with 3 or more votes</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_enlightened">
|
||||
<field name="name">Enlightened</field>
|
||||
<field name="description">Answer was accepted with 3 or more votes</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')"/>
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '!=', False), ('vote_count', '>=', 3), ('is_correct', '=', True)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_enlightened">
|
||||
<field name="name">Enlightened</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_a_5')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_enlightened">
|
||||
<field name="definition_id" eval="ref('definition_enlightened')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_enlightened')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Guru: at least 15 upvotes for an accepted answer -->
|
||||
<!-- <record id="badge_a_6" model="gamification.badge">
|
||||
<field name="name">Guru</field>
|
||||
<field name="description">Answer accepted with 15 or more votes</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_guru">
|
||||
<field name="name">Guru</field>
|
||||
<field name="description">Answer accepted with 15 or more votes</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '!=', False), ('vote_count', '>=', 15), ('is_correct', '=', True)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_guru">
|
||||
<field name="name">Great Answer</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_a_6')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_guru">
|
||||
<field name="definition_id" eval="ref('definition_guru')" />
|
||||
<field name="target_goal">1</field>
|
||||
<field name="challenge_id" eval="ref('challenge_guru')" />
|
||||
</record> -->
|
||||
|
||||
<!-- Necromancer: 30 days old question -->
|
||||
<!-- <record id="badge_a_7" model="gamification.badge">
|
||||
<field name="name">Necromancer</field>
|
||||
<field name="description">Answered a question more than 30 days later with at least 2 votes</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_necromancer">
|
||||
<field name="name">Necromancer</field>
|
||||
<field name="description">Answered a question more than 30 days later with at least 2 votes</field>
|
||||
<field name="computation_mode">python</field>
|
||||
<field name="compute_code">def get_posts(cr, uid, context=None):
|
||||
res = 1
|
||||
Post = self.pool['website.forum.post']
|
||||
user_posts = Post.search(cr, uid, [('create_uid','=',object.user_id.id), ('parent_id', '!=', False), ('vote_count', '>=', 2)], context=context)
|
||||
for post in Post.browse(cr, uid, user_posts, context=context):
|
||||
print post.parent_id.create_date
|
||||
question_date = datetime.strptime(post.parent_id.create_date, "%Y-%m-%d %H:%M:%S")
|
||||
answer_date = datetime.strptime(post.create_date, "%Y-%m-%d %H:%M:%S")
|
||||
if ((question_date - answer_date).days) >= 30:
|
||||
res += 1
|
||||
return res
|
||||
result = get_posts(cr, uid, context=context)
|
||||
</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_necromancer">
|
||||
<field name="name">Necromancer</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_18')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_necromancer">
|
||||
<field name="definition_id" eval="ref('definition_necromancer')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_necromancer')"/>
|
||||
<field name="target_goal">2</field>
|
||||
</record> -->
|
||||
|
||||
<!-- Sealf Leaner: own question, 3+ upvotes -->
|
||||
<!-- <record id="badge_a_8" model="gamification.badge">
|
||||
<field name="name">Self-Learner</field>
|
||||
<field name="description">Answered own question with at least 4 up votes</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_self_learner">
|
||||
<field name="name">Self-Learner</field>
|
||||
<field name="description">Answere own question with at least 4 up votes</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '!=', False), ('parent_id.create_uid', '=', user.id), ('vote_count', '>=', 3)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_self_learner">
|
||||
<field name="name">Self-Learner</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_a_8')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_self_learner">
|
||||
<field name="definition_id" eval="ref('definition_self_learner')"/>
|
||||
<field name="target_goal">1</field>
|
||||
<field name="challenge_id" eval="ref('challenge_self_learner')"/>
|
||||
</record> -->
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,303 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Cleanup: answer or question edition -->
|
||||
<!-- <record id="badge_3" model="gamification.badge">
|
||||
<field name="name">Cleanup</field>
|
||||
<field name="description">First rollback</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_cleanup">
|
||||
<field name="name">Cleanup</field>
|
||||
<field name="description">Edit answer or question</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('mail.model_mail_message')"/>
|
||||
<field name="domain" eval="[('author_id', '=', user.partner_id.id), ('model', '=', 'forum.post'), ('subtype_id', 'in', [ref('website_forum.mt_answer_edit'), ref('website_forum.mt_question_edit')])]"/>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_cleanup">
|
||||
<field name="name">Cleanup</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_3')"/>
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_cleanup">
|
||||
<field name="definition_id" eval="ref('definition_cleanup')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_cleanup')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
|
||||
<!-- Critic: downvote based -->
|
||||
<!-- <record id="badge_5" model="gamification.badge">
|
||||
<field name="name">Critic</field>
|
||||
<field name="description">First downvote</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_critic">
|
||||
<field name="name">Critic</field>
|
||||
<field name="description">First downvote</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post_vote')"/>
|
||||
<field name="domain">[('create_uid', '=', user.id), ('vote', '=', '-1')]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_critic">
|
||||
<field name="name">Critic</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_5')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_critic">
|
||||
<field name="definition_id" eval="ref('definition_critic')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_critic')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
|
||||
<!-- Disciplined: delete own post with >=3 upvotes -->
|
||||
<!-- <record id="badge_6" model="gamification.badge">
|
||||
<field name="name">Disciplined</field>
|
||||
<field name="description">Deleted own post with 3 or more upvotes</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_disciplined">
|
||||
<field name="name">Disciplined</field>
|
||||
<field name="description">Delete own post with 3 or more upvotes</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('vote_count', '>=', 3), ('active', '=', False)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_disciplined">
|
||||
<field name="name">Disciplined</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_6')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_disciplined">
|
||||
<field name="definition_id" eval="ref('definition_disciplined')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_disciplined')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
|
||||
<!-- Editor: first edit -->
|
||||
<!-- <record id="badge_7" model="gamification.badge">
|
||||
<field name="name">Editor</field>
|
||||
<field name="description">First edit</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_editor">
|
||||
<field name="name">Editor</field>
|
||||
<field name="description">First edit of answer or question</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('mail.model_mail_message')" />
|
||||
<field name="domain">[('create_uid','=',user.id), '|', ('name','!=',False), ('content','!=',False)]</field>
|
||||
<field name="domain" eval="[('author_id', '=', user.partner_id.id), ('model', '=', 'forum.post'), ('subtype_id', 'in', [ref('website_forum.mt_answer_edit'), ref('website_forum.mt_question_edit')])]"/>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_editor">
|
||||
<field name="name">Editor</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_7')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_editor">
|
||||
<field name="definition_id" eval="ref('definition_editor')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_editor')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
|
||||
|
||||
<!-- <record id="badge_22" model="gamification.badge">
|
||||
<field name="name">Organizer</field>
|
||||
<field name="description">First retag</field>
|
||||
<field name="level">bronze</field>
|
||||
</record> -->
|
||||
|
||||
<!-- <record model="gamification.goal.definition" id="definition_notable_question">
|
||||
<field name="name">Organizer</field>
|
||||
<field name="description">Your First retag</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_website_forum_post_history')" />
|
||||
<field name="domain">[('create_uid','=',user.id), ('tags','!=',False)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record> -->
|
||||
|
||||
<!-- <record model="gamification.challenge" id="challenge_notable_question">
|
||||
<field name="name">Organizer</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_22')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record> -->
|
||||
|
||||
<!-- <record model="gamification.challenge.line" id="line_notable_question">
|
||||
<field name="definition_id" eval="ref('definition_notable_question')" />
|
||||
<field name="target_goal">1</field>
|
||||
<field name="challenge_id" eval="ref('challenge_notable_question')" />
|
||||
</record> -->
|
||||
|
||||
|
||||
<!-- <record id="badge_29" model="gamification.badge">
|
||||
<field name="name">Associate Editor</field>
|
||||
<field name="description">Edited 30 entries</field>
|
||||
<field name="level">silver</field>
|
||||
</record> -->
|
||||
|
||||
|
||||
|
||||
<!-- <record model="gamification.goal.definition" id="definition_associate_editor">
|
||||
<field name="name">Associate Editor</field>
|
||||
<field name="description">Edit 30 answer or question</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_website_forum_post_history')" />
|
||||
<field name="domain">[('create_uid','=',user.id), '|', ('name','!=',False), ('content','!=',False)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record> -->
|
||||
|
||||
<!-- <record model="gamification.challenge" id="challenge_associate_editor">
|
||||
<field name="name">Associate Editor</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_29')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record> -->
|
||||
|
||||
<!-- <record model="gamification.challenge.line" id="line_associate_editor">
|
||||
<field name="definition_id" eval="ref('definition_associate_editor')" />
|
||||
<field name="target_goal">30</field>
|
||||
<field name="challenge_id" eval="ref('challenge_associate_editor')" />
|
||||
</record> -->
|
||||
|
||||
<!-- Enthusiast: vote for 15 days in a row -->
|
||||
<!-- <record id="badge_9" model="gamification.badge">
|
||||
<field name="name">Enthusiast</field>
|
||||
<field name="description">Voted on questions/answers for 15 days in a row</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_enthusiast">
|
||||
<field name="name">Enthusiast</field>
|
||||
<field name="description">Vote on questions/answers for 15 days in a row</field>
|
||||
<field name="computation_mode">python</field>
|
||||
<field name="compute_code">start_date = date.today() - timedelta(days=16)
|
||||
end_date = date.today() - timedelta(days=1)
|
||||
cr.execute('SELECT COUNT(id), create_date from forum_post_vote where create_date >= %s and create_date <= %s and user_id = %s GROUP BY create_date',(start_date,end_date, object.user_id.id,))
|
||||
data = cr.dictfetchall()
|
||||
result = int(len(data) >= 15)</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_enthusiast">
|
||||
<field name="name">Enthusiast</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_9')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_enthusiast">
|
||||
<field name="definition_id" eval="ref('definition_enthusiast')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_enthusiast')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_31" model="gamification.badge">
|
||||
<field name="name">Supporter</field>
|
||||
<field name="description">First upvote</field>
|
||||
<field name="level">gold</field>
|
||||
</record> -->
|
||||
|
||||
<!-- <record model="gamification.goal.definition" id="definition_supporter">
|
||||
<field name="name">Supporter</field>
|
||||
<field name="description">First upwnvote</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post_vote')" />
|
||||
<field name="domain">[('user_id','=',user.id), ('vote', '=', '1')]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
|
||||
<record model="gamification.challenge" id="challenge_supporter">
|
||||
<field name="name">Supporter</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_31')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
|
||||
<record model="gamification.challenge.line" id="line_supporter">
|
||||
<field name="definition_id" eval="ref('definition_supporter')" />
|
||||
<field name="target_goal">1</field>
|
||||
<field name="challenge_id" eval="ref('challenge_supporter')" />
|
||||
</record> -->
|
||||
|
||||
|
||||
<!-- <record id="badge_23" model="gamification.badge">
|
||||
<field name="name">Peer Pressure</field>
|
||||
<field name="description">Deleted own post with 3 or more downvotes</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record model="gamification.goal.definition" id="definition_peer_pressure">
|
||||
<field name="name">Peer Pressure</field>
|
||||
<field name="description">Delete own post with 3 or more down votes</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid','=',user.id), ('vote_count', '<=', -3), ('active', '=', False)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
|
||||
<record model="gamification.challenge" id="challenge_peer_pressure">
|
||||
<field name="name">Peer Pressure</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_23')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
|
||||
<record model="gamification.challenge.line" id="line_peer_pressure">
|
||||
<field name="definition_id" eval="ref('definition_peer_pressure')" />
|
||||
<field name="target_goal">1</field>
|
||||
<field name="challenge_id" eval="ref('challenge_peer_pressure')" />
|
||||
</record> -->
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,208 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Biography: complet your profile -->
|
||||
<!-- <record id="badge_p_1" model="gamification.badge">
|
||||
<field name="name">Autobiographer</field>
|
||||
<field name="description">Completed own biography</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_configure_profile">
|
||||
<field name="name">Completed own biography</field>
|
||||
<field name="description">Write some information about your self</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('base.model_res_users')" />
|
||||
<field name="domain">[('id','=',user.id),
|
||||
('partner_id.country_id', '!=', False),
|
||||
('partner_id.city', '!=', False),
|
||||
('partner_id.email', '!=', False)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_configure_profile">
|
||||
<field name="name">Complete own biography</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_p_1')"/>
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_configure_profile">
|
||||
<field name="definition_id" eval="ref('definition_configure_profile')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_configure_profile')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
|
||||
<!-- Commentator: at least 10 comments posted on posts -->
|
||||
<!-- <record id="badge_p_2" model="gamification.badge">
|
||||
<field name="name">Commentator</field>
|
||||
<field name="description">Posted 10 comments</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_commentator">
|
||||
<field name="name">Commentator</field>
|
||||
<field name="description">Comment an answer or a question</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('mail.model_mail_message')"/>
|
||||
<field name="domain" eval="[('author_id', '=', user.partner_id.id), ('type', '=', 'comment'), ('subtype_id', '=', ref('mail.mt_comment')), ('model', '=', 'forum post')]"/>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_commentator">
|
||||
<field name="name">Commentator</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_p_2')"/>
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_commentator">
|
||||
<field name="definition_id" eval="ref('definition_commentator')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_commentator')"/>
|
||||
<field name="target_goal">10</field>
|
||||
</record> -->
|
||||
|
||||
<!-- Pundit: 10 comments with at least score of 10 -->
|
||||
<!-- <record id="badge_25" model="gamification.badge">
|
||||
<field name="name">Pundit</field>
|
||||
<field name="description">Left 10 comments with score of 10 or more</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_pundit">
|
||||
<field name="name">Pundit</field>
|
||||
<field name="description">Post 10 comments with score of 10 or more</field>
|
||||
<field name="computation_mode">python</field>
|
||||
<field name="compute_code">def get_count(cr, uid, context=None):
|
||||
res = 1
|
||||
Message = self.pool['mail.message']
|
||||
Post = self.pool['website.forum.post']
|
||||
user_message = Message.read_group(cr, uid,[('create_uid','=',object.user_id.id), ('type', '=', 'comment'), ('model', '=', 'website.forum.post')], ['res_id'], groupby=['res_id'], context=context)
|
||||
for rec in user_message:
|
||||
if rec.get('res_id_count') >= 10:
|
||||
post = Post.browse(cr, uid, rec.get('res_id'), context=context)
|
||||
if post.vote_count >= 10:
|
||||
res += 1
|
||||
return res
|
||||
result = get_count(cr, uid, context=context)
|
||||
</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_pundit">
|
||||
<field name="name">Pundit</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_25')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_pundit">
|
||||
<field name="definition_id" eval="ref('definition_pundit')" />
|
||||
<field name="target_goal">2</field>
|
||||
<field name="challenge_id" eval="ref('challenge_pundit')" />
|
||||
</record> -->
|
||||
|
||||
<!-- Chief Commentator: 100 comments -->
|
||||
<!-- <record id="badge_p_4" model="gamification.badge">
|
||||
<field name="name">Chief Commentator</field>
|
||||
<field name="description">Posted 100 comments</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_chief_commentator">
|
||||
<field name="name">Commentator</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_p_4')"/>
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_chief_commentator">
|
||||
<field name="definition_id" eval="ref('definition_commentator')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_chief_commentator')"/>
|
||||
<field name="target_goal">100</field>
|
||||
</record> -->
|
||||
|
||||
<!-- Expert: tag-based activity -->
|
||||
<!-- <record id="badge_10" model="gamification.badge">
|
||||
<field name="name">Expert</field>
|
||||
<field name="description">Posted more than 10 questions or answers in one tag</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_expert">
|
||||
<field name="name">Expert</field>
|
||||
<field name="description">Post more than 10 questions in one tag</field>
|
||||
<field name="computation_mode">python</field>
|
||||
<field name="compute_code">def get_counter(cr, uid, context=None):
|
||||
res = 1
|
||||
Post = pool['forum.post']
|
||||
Tag = pool['forum.tag']
|
||||
for tag_id in Tag.search(cr, uid, [], context=context):
|
||||
post_count = Post.search_count(cr, uid , [('tag_ids', 'in', tag_id), ('user_id', '=', object.user_id.id)], context=context)
|
||||
if post_count >= 10:
|
||||
res += 1
|
||||
return res
|
||||
result = get_counter(cr, uid, context=context)
|
||||
</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_expert">
|
||||
<field name="name">Expert</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_10')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_expert">
|
||||
<field name="definition_id" eval="ref('definition_expert')" />
|
||||
<field name="target_goal">2</field>
|
||||
<field name="challenge_id" eval="ref('challenge_expert')" />
|
||||
</record> -->
|
||||
|
||||
<!-- <record id="badge_32" model="gamification.badge">
|
||||
<field name="name">Taxonomist</field>
|
||||
<field name="description">Created a tag used by 15 questions</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<record model="gamification.goal.definition" id="definition_taxonomist">
|
||||
<field name="name">Taxonomist</field>
|
||||
<field name="description">Create a tag which can used in minimum 15 questions</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_website_forum_tag')" />
|
||||
<field name="domain">[('create_uid','=',user.id), ('posts_count', '>=', 15)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
|
||||
<record model="gamification.challenge" id="challenge_taxonomist">
|
||||
<field name="name">Taxonomist</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_32')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
|
||||
<record model="gamification.challenge.line" id="line_taxonomist">
|
||||
<field name="definition_id" eval="ref('definition_taxonomist')" />
|
||||
<field name="target_goal">1</field>
|
||||
<field name="challenge_id" eval="ref('challenge_taxonomist')" />
|
||||
</record> -->
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,343 @@
|
|||
<!-- <?xml version="1.0" encoding="utf-8"?> -->
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- POPULARITY (VIEWS) -->
|
||||
<!-- Popular: 150 views -->
|
||||
<!-- <record id="badge_q_1" model="gamification.badge">
|
||||
<field name="name">Popular Question</field>
|
||||
<field name="description">Asked a question with at least 150 views</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_popular_question">
|
||||
<field name="name">Popular Question</field>
|
||||
<field name="description">Asked a question with at least 150 views</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('views', '>=', 150)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_popular_question">
|
||||
<field name="name">Popular Question</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_1')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_popular_question">
|
||||
<field name="definition_id" eval="ref('definition_popular_question')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_popular_question')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Notable: 250 views -->
|
||||
<!-- <record id="badge_q_2" model="gamification.badge">
|
||||
<field name="name">Notable Question</field>
|
||||
<field name="description">Asked a question with at least 250 views</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_notable_question">
|
||||
<field name="name">Notable Question</field>
|
||||
<field name="description">Asked a question with at least 250 views</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('views', '>=', 250)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_notable_question">
|
||||
<field name="name">Notable Question</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_2')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_notable_question">
|
||||
<field name="definition_id" eval="ref('definition_notable_question')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_notable_question')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Famous: 500 views -->
|
||||
<!-- <record id="badge_q_3" model="gamification.badge">
|
||||
<field name="name">Famous Question</field>
|
||||
<field name="description">Asked a question with at least 500 views</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_famous_question">
|
||||
<field name="name">Famous Question</field>
|
||||
<field name="description">Asked a question with at least 500 views</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('views', '>=', 500)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_famous_question">
|
||||
<field name="name">Famous Question</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_3')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_famous_question">
|
||||
<field name="definition_id" eval="ref('definition_famous_question')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_famous_question')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
|
||||
<!-- FAVORITE -->
|
||||
<!-- Credible: at least 1 user have it in favorite -->
|
||||
<!-- <record id="badge_q_4" model="gamification.badge">
|
||||
<field name="name">Credible Question</field>
|
||||
<field name="description">Question set as favorite by 1 user</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_favorite_question">
|
||||
<field name="name">Credible Question</field>
|
||||
<field name="description">Question set as favorite by 1 user</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('favourite_count', '>=', 1)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_favorite_question">
|
||||
<field name="name">Credible Question</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_4')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_favorite_question">
|
||||
<field name="definition_id" eval="ref('definition_favorite_question')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_favorite_question')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Favorite: at least 5 users have it in favorite -->
|
||||
<!-- <record id="badge_q_5" model="gamification.badge">
|
||||
<field name="name">Favorite Question</field>
|
||||
<field name="description">Question set as favorite by 5 users</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_favorite_question">
|
||||
<field name="name">Favorite Question</field>
|
||||
<field name="description">Question set as favorite by 5 users</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('favourite_count', '>=', 5)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_favorite_question">
|
||||
<field name="name">Favorite Question</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_5')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_favorite_question">
|
||||
<field name="definition_id" eval="ref('definition_favorite_question')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_favorite_question')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Stellar: at least 25 users have it in favorite -->
|
||||
<!-- <record id="badge_q_6" model="gamification.badge">
|
||||
<field name="name">Stellar Question</field>
|
||||
<field name="description">Question set as favorite by 5 users</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_stellar_question">
|
||||
<field name="name">Stellar Question</field>
|
||||
<field name="description">Question set as favorite by 5 users</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('favourite_count', '>=', 25)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_stellar_question">
|
||||
<field name="name">Stellar Question</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_6')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_stellar_question">
|
||||
<field name="definition_id" eval="ref('definition_stellar_question')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_stellar_question')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
|
||||
<!-- QUALITY (VOTES) -->
|
||||
<!-- Student: at least 1 upvote -->
|
||||
<!-- <record id="badge_q_7" model="gamification.badge">
|
||||
<field name="name">Student</field>
|
||||
<field name="description">Asked first question with at least one up vote</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_student">
|
||||
<field name="name">Student</field>
|
||||
<field name="description">Asked first question with at least one up vote</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('vote_count', '>=', 1)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_student">
|
||||
<field name="name">Student</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_7')"/>
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_student">
|
||||
<field name="definition_id" eval="ref('definition_student')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_student')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Nice: at least 4 upvotes -->
|
||||
<!-- <record id="badge_q_8" model="gamification.badge">
|
||||
<field name="name">Nice Quesiotn</field>
|
||||
<field name="description">Question voted up 4 times</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_nice_question">
|
||||
<field name="name">Nice Question</field>
|
||||
<field name="description">Question voted up 4 times</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')"/>
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('vote_count', '>=', 4)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_nice_question">
|
||||
<field name="name">Nice Question</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_8')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')"/>
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_nice_question">
|
||||
<field name="definition_id" eval="ref('definition_nice_question')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_nice_question')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Good: at least 6 upvotes -->
|
||||
<!-- <record id="badge_q_9" model="gamification.badge">
|
||||
<field name="name">Good Question</field>
|
||||
<field name="description">Question voted up 6 times</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_good_question">
|
||||
<field name="name">Good Question</field>
|
||||
<field name="description">Question voted up 6 times</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('vote_count', '>=', 6)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_good_question">
|
||||
<field name="name">Good Question</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_9')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_good_question">
|
||||
<field name="definition_id" eval="ref('definition_good_question')"/>
|
||||
<field name="challenge_id" eval="ref('challenge_good_question')"/>
|
||||
<field name="target_goal">1</field>
|
||||
</record> -->
|
||||
<!-- Great: at least 15 upvotes -->
|
||||
<!-- <record id="badge_q_10" model="gamification.badge">
|
||||
<field name="name">Great Question</field>
|
||||
<field name="description">Question voted up 15 times</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_great_question">
|
||||
<field name="name">Great Question</field>
|
||||
<field name="description">Question voted up 15 times</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('vote_count', '>=', 15)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_great_question">
|
||||
<field name="name">Great Question</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_q_10')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_great_question">
|
||||
<field name="definition_id" eval="ref('definition_great_question')" />
|
||||
<field name="target_goal">1</field>
|
||||
<field name="challenge_id" eval="ref('challenge_great_question')" />
|
||||
</record> -->
|
||||
|
||||
<!-- Question + Answer -->
|
||||
<!-- <record id="badge_26" model="gamification.badge">
|
||||
<field name="name">Scholar</field>
|
||||
<field name="description">Asked a question and accepted an answer</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
<record model="gamification.goal.definition" id="definition_scholar">
|
||||
<field name="name">Scholar</field>
|
||||
<field name="description">Ask a question and accept an answer</field>
|
||||
<field name="computation_mode">count</field>
|
||||
<field name="display_mode">boolean</field>
|
||||
<field name="model_id" eval="ref('website_forum.model_forum_post')" />
|
||||
<field name="domain">[('create_uid', '=', user.id), ('parent_id', '=', False), ('is_correct', '=', True)]</field>
|
||||
<field name="condition">higher</field>
|
||||
</record>
|
||||
<record model="gamification.challenge" id="challenge_scholar">
|
||||
<field name="name">Scholar</field>
|
||||
<field name="period">once</field>
|
||||
<field name="visibility_mode">personal</field>
|
||||
<field name="report_message_frequency">never</field>
|
||||
<field name="reward_id" eval="ref('badge_26')" />
|
||||
<field name="autojoin_group_id" eval="ref('base.group_user')" />
|
||||
<field name="state">inprogress</field>
|
||||
<field name="category">forum</field>
|
||||
</record>
|
||||
<record model="gamification.challenge.line" id="line_scholar">
|
||||
<field name="definition_id" eval="ref('definition_scholar')" />
|
||||
<field name="target_goal">1</field>
|
||||
<field name="challenge_id" eval="ref('challenge_scholar')" />
|
||||
</record> -->
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="forum_help" model="forum.forum">
|
||||
<field name="name">Help</field>
|
||||
</record>
|
||||
|
||||
<record id="menu_questions" model="website.menu">
|
||||
<field name="name">Forum</field>
|
||||
<field name="url" eval="'/forum/'+str(ref('website_forum.forum_help'))"/>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence" type="int">35</field>
|
||||
</record>
|
||||
|
||||
<record id="default_allow_auth_signup" model="ir.config_parameter">
|
||||
<field name="key">auth_signup.allow_uninvited</field>
|
||||
<field name="value" eval="True"/>
|
||||
</record>
|
||||
|
||||
<!-- JUMP TO FORUM AT INSTALL -->
|
||||
<record id="action_open_forum" model="ir.actions.act_url">
|
||||
<field name="name">Forum</field>
|
||||
<field name="target">self</field>
|
||||
<field name="url" eval="'/forum/'+str(ref('website_forum.forum_help'))+'/#tutorial.forum=true'"/>
|
||||
</record>
|
||||
<record id="base.open_menu" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_open_forum"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
|
||||
<!-- Answers subtypes -->
|
||||
<record id="mt_answer_new" model="mail.message.subtype">
|
||||
<field name="name">New Answer</field>
|
||||
<field name="res_model">forum.post</field>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="hidden" eval="False"/>
|
||||
<field name="description">New Answer</field>
|
||||
</record>
|
||||
<record id="mt_answer_edit" model="mail.message.subtype">
|
||||
<field name="name">Answer Edited</field>
|
||||
<field name="res_model">forum.post</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Answer Edited</field>
|
||||
</record>
|
||||
<!-- Questions subtypes -->
|
||||
<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="description">New Question</field>
|
||||
</record>
|
||||
<record id="mt_question_edit" model="mail.message.subtype">
|
||||
<field name="name">Question Edited</field>
|
||||
<field name="res_model">forum.post</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Question Edited</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- Reasons for closing Post -->
|
||||
<record id="reason_1" model="forum.post.reason">
|
||||
<field name="name">duplicate question</field>
|
||||
</record>
|
||||
<record id="reason_2" model="forum.post.reason">
|
||||
<field name="name">off-topic or not relevant</field>
|
||||
</record>
|
||||
<record id="reason_3" model="forum.post.reason">
|
||||
<field name="name">too subjective and argumentative</field>
|
||||
</record>
|
||||
<record id="reason_4" model="forum.post.reason">
|
||||
<field name="name">not a real question</field>
|
||||
</record>
|
||||
<record id="reason_5" model="forum.post.reason">
|
||||
<field name="name">already answered and an answer was accepted</field>
|
||||
</record>
|
||||
<record id="reason_6" model="forum.post.reason">
|
||||
<field name="name">not relevant or out dated</field>
|
||||
</record>
|
||||
<record id="reason_7" model="forum.post.reason">
|
||||
<field name="name">contains offensive or malicious remarks</field>
|
||||
</record>
|
||||
<record id="reason_8" model="forum.post.reason">
|
||||
<field name="name">spam or advertising</field>
|
||||
</record>
|
||||
<record id="reason_9" model="forum.post.reason">
|
||||
<field name="name">too localized</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,147 @@
|
|||
<h1>Guidelines</h1>
|
||||
<h2><a class="faq-question">What kinds of questions can I ask here?</a></h2>
|
||||
<p>
|
||||
This community is for professional and enthusiast users,
|
||||
partners and programmers. You can ask questions about:
|
||||
</p>
|
||||
<ul>
|
||||
<li>how to install OpenERP on a specific infrastructure,</li>
|
||||
<li>how to configure or customize OpenERP to specific business needs,</li>
|
||||
<li>what's the best way to use OpenERP for a specific business need,</li>
|
||||
<li>how to develop modules for your own need,</li>
|
||||
<li>specific questions about OpenERP service offers, etc.</li>
|
||||
</ul>
|
||||
<p>
|
||||
<b>Before you ask - please make sure to search for a similar question.</b> You can
|
||||
search questions by their title or tags. It’s also OK to
|
||||
answer your own question.
|
||||
</p><p>
|
||||
<b>Please avoid asking questions that are too subjective
|
||||
and argumentative</b> or not relevant to this community.
|
||||
</p>
|
||||
<h2><a class="faq-question">What should I avoid in my questions?</a></h2>
|
||||
<p>
|
||||
You should only ask practical, answerable questions based
|
||||
on actual problems that you face. Chatty, open-ended
|
||||
questions diminish the usefulness of this site and push
|
||||
other questions off the front page.
|
||||
</p><p>
|
||||
To prevent your question from being flagged and possibly removed, avoid asking
|
||||
subjective questions where …
|
||||
</p>
|
||||
<ul>
|
||||
<li>every answer is equally valid: “What’s your favorite ______?”</li>
|
||||
<li>your answer is provided along with the question, and you expect more answers: “I use ______ for ______, what do you use?”</li>
|
||||
<li>there is no actual problem to be solved: “I’m curious if other people feel like I do.”</li>
|
||||
<li>we are being asked an open-ended, hypothetical question: “What if ______ happened?”</li>
|
||||
<li>it is a rant disguised as a question: “______ sucks, am I right?”</li>
|
||||
</ul>
|
||||
<p>
|
||||
If you fit in one of these example or if your motivation for asking the
|
||||
question is “I would like to participate in a discussion about ______”, then
|
||||
you should not be asking here but on our mailing lists.
|
||||
However, if your motivation is “I would like others to explain ______ to me”,
|
||||
then you are probably OK.
|
||||
</p><p>
|
||||
(The above section was adapted from Stackoverflow’s FAQ.)
|
||||
</p><p>
|
||||
More over:
|
||||
</p>
|
||||
<ul>
|
||||
<li><b>Answers should not add or expand questions</b>. Instead either edit the question edit or add a question comment.</li>
|
||||
<li><b>Answers should not comment other answers</b>. Instead add a comment on the other answers.</li>
|
||||
<li><b>Answers shouldn't just point to other Questions</b>. Instead add a question comment indication "Possible duplicate of...". However, it's ok to include links to other questions or answers providing relevant additional information.</li>
|
||||
<li><b>Answers shouldn't just provide a link a solution</b>. Instead provide the solution description text in your answer, even if it's just a copy/paste. Links are welcome, but should complementary to answer, referring sources or additional reading.</li>
|
||||
</ul>
|
||||
|
||||
<h2><a class="faq-question">What should I avoid in my answers?</a></h2>
|
||||
<p>
|
||||
<b>Answers should not add or expand questions</b>. Instead
|
||||
either edit the question or add a comment.
|
||||
</p><p>
|
||||
<b>Answers should not comment other answers</b>. Instead
|
||||
add a comment on the other answers.
|
||||
</p><p>
|
||||
<b>Answers shouldn't just point to other questions</b>.
|
||||
Instead add a comment indicating <i>"Possible duplicate
|
||||
of..."</i>. However, it's fine to include links to other
|
||||
questions or answers providing relevant additional
|
||||
information. </p> <p> <b>Answers shouldn't just provide a
|
||||
link a solution</b>. Instead provide the solution
|
||||
description text in your answer, even if it's just a
|
||||
copy/paste. Links are welcome, but should complementary to
|
||||
answer, referring sources or additional reading.
|
||||
</p><p>
|
||||
<b>Answers should not start debates</b>
|
||||
This community Q&A is not a discussion group. Please avoid holding debates in
|
||||
your answers as they tend to dilute the essence of questions and answers. For
|
||||
brief discussions please use commenting facility.
|
||||
</p> <p>
|
||||
When a question or answer is upvoted, the user who posted them will gain some
|
||||
points, which are called "karma points". These points serve as a rough
|
||||
measure of the community trust to him/her. Various moderation tasks are
|
||||
gradually assigned to the users based on those points.
|
||||
</p> <p>
|
||||
For example, if you ask an interesting question or give a helpful answer, your
|
||||
input will be upvoted. On the other hand if the answer is misleading - it will
|
||||
be downvoted. Each vote in favor will generate 10 points, each vote against
|
||||
will subtract 10 points. There is a limit of 200 points that can be accumulated
|
||||
for a question or answer per day. The table below explains reputation point
|
||||
requirements for each type of moderation task.
|
||||
</p>
|
||||
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="faq-rep-item"><strong>1</strong></td>
|
||||
<td>upvote, add comments</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>10</strong></td>
|
||||
<td>downvote</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>30</strong></td>
|
||||
<td>insert text link, upload files</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>50</strong></td>
|
||||
<td>insert clickable link, answer own question immediately</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>75</strong></td>
|
||||
<td>retag, edit wiki questions and answers</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>100</strong></td>
|
||||
<td>flag offensive, close own questions</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>200</strong></td>
|
||||
<td>answer/comment by email</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>300</strong></td>
|
||||
<td>edit any post, view offensive flags</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>500</strong></td>
|
||||
<td>accept any answer (after 1 week)</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>750</strong></td>
|
||||
<td>delete any comment</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>900</strong></td>
|
||||
<td>lock posts</td>
|
||||
</tr><tr>
|
||||
<td class="faq-rep-item"><strong>1000</strong></td>
|
||||
<td>delete any question or answer</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2><a class="faq-question">Why can other people edit my questions/answers?</a></h2>
|
||||
<p>
|
||||
The goal of this site is create a relevant knowledge base that would answer
|
||||
questions related to OpenERP.
|
||||
</p><p>
|
||||
Therefore questions and answers can be edited like wiki pages by experienced users of
|
||||
this site in order to improve the overall quality of the knowledge base content.
|
||||
Such privileges are granted based on user karma level: you will be able to do the same
|
||||
once your karma gets high enough.
|
||||
</p><p>
|
||||
If this approach is not for you, please respect the community and use Google+
|
||||
communities instead.
|
||||
</p>
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Tag -->
|
||||
<record id="tags_0" model="forum.tag">
|
||||
<field name="name">Contract</field>
|
||||
<field name="forum_id" ref="website_forum.forum_help"/>
|
||||
</record>
|
||||
<record id="tags_1" model="forum.tag">
|
||||
<field name="name">Action</field>
|
||||
<field name="forum_id" ref="website_forum.forum_help"/>
|
||||
</record>
|
||||
<record id="tags_2" model="forum.tag">
|
||||
<field name="name">ecommerce</field>
|
||||
<field name="forum_id" ref="website_forum.forum_help"/>
|
||||
</record>
|
||||
|
||||
<!-- Questions -->
|
||||
<record id="question_0" model="forum.post">
|
||||
<field name="name">How to configure alerts for employee contract expiration</field>
|
||||
<field name="forum_id" ref="website_forum.forum_help"/>
|
||||
<field name="views">3</field>
|
||||
<field name="tag_ids" eval="[(4,ref('website_forum.tags_0')), (4,ref('website_forum.tags_1'))]"/>
|
||||
</record>
|
||||
<record id="question_1" model="forum.post">
|
||||
<field name="name">CMS replacement for ERP and eCommerce</field>
|
||||
<field name="views">8</field>
|
||||
<field name="forum_id" ref="website_forum.forum_help"/>
|
||||
<field name="content"><![CDATA[<p>I use Wordpress as a CMS and eCommerce platform. The developing in Wordpress is quite easy and solid but it missing ERP feature (there is single plugin to integrate with Frontaccounting) so I wonder:
|
||||
|
||||
Can I use OpenERP as a replacement CMS of Wordpress + eCommerce plugin?
|
||||
|
||||
In simple words does OpenERP became CMS+ERP platform?</p>]]></field>
|
||||
<field name="tag_ids" eval="[(4,ref('website_forum.tags_2'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- Answer -->
|
||||
<record id="answer_0" model="forum.post">
|
||||
<field name="forum_id" ref="website_forum.forum_help"/>
|
||||
<field name="content"><![CDATA[<p>Just for posterity so other can see. Here are the steps to set automatic alerts on any contract.. i.e. HR Employee, or Fleet for example. I will use fleet as an example.</p>
|
||||
<ul>
|
||||
<li>Step 1. As a user who has access rights to Technical Features, go to Settings --> Automated Actions. Create A new Automated Action. For the Related Document Model choose.. Contract information on a vehicle (you can also type in the actual model name.. fleet.vehicle.log.contract ) . Set the trigger date to ... Contract Expiration Date. The Next Field (Delay After Trigger Date) is a bit ridiculous. Who wants to be reminded of a contract expiration AFTER the fact? The field should say Days Before Date to Fire Action and the number should be converted to a negative. IMHO. Any way... to get a workable solution you must enter in the number in the negative. So for instance like me if you want to be warned 35 days BEFORE the expiration... put in Delay After Trigger Date.. the number -35 But the sake of testing, right now just put in -1 for 1 day before. Save the Action.
|
||||
<li>Step 2. Go to Server Actions and create new Action. Call it Fleet Contract Expiration Warning. The Object will be the same as above .. Contract information on a vehicle. The Action Type is Email. For email address I just put my email. Under subject put in... [[object.name]]. This will tell you the name of the car. Message you can put any text message you like. Now save the Server Action.</li>
|
||||
<li>Step 3. Now go back to the Automated Action you created and go to the Action tab next to the conditions tab. Click Add and add the server action you created . In this case Fleet Contract Expiration Warning. Then Save.</li>
|
||||
<li>Step 4. To test, set a contract to expire tomorrow under one of your fleets vehicles. Then Save it.</li>
|
||||
<li>Step 5. Go to Scheduled Actions.. Set interval number to 1. Interval Unit to Minutes. Then Set the Next Execution date to 2 minutes from now. If your SMTP is configured correctly you will start to get a mail every minute with the reminder.</li></ul>]]></field>
|
||||
<field name="parent_id" ref="question_0" />
|
||||
</record>
|
||||
<record id="answer_1" model="forum.post">
|
||||
<field name="forum_id" ref="website_forum.forum_help"/>
|
||||
<field name="content">OpenERP v8 (next release) provides a web module and an e-commerce module: www.openerp.com/website_cms
|
||||
The CMS editor in OpernERP web is nice but I prefer drupal for customization and there is a drupal module for OpenERP. I think WP is better than OpenERP web too.
|
||||
</field>
|
||||
<field name="parent_id" ref="question_1"/>
|
||||
</record>
|
||||
|
||||
<!-- Post Vote -->
|
||||
<record id="post_vote_0" model="forum.post.vote">
|
||||
<field name="post_id" ref="question_0"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="vote">1</field>
|
||||
</record>
|
||||
<record id="post_vote_1" model="forum.post.vote">
|
||||
<field name="post_id" ref="answer_0"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="vote">1</field>
|
||||
</record>
|
||||
|
||||
<!-- Run Scheduler -->
|
||||
<function model="gamification.challenge" name="_cron_update"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import gamification
|
||||
import res_users
|
||||
import forum
|
|
@ -0,0 +1,286 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import openerp
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.addons.website.models.website import slug
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class Forum(osv.Model):
|
||||
_name = 'forum.forum'
|
||||
_description = 'Forums'
|
||||
_inherit = ['website.seo.metadata']
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True, translate=True),
|
||||
'faq': fields.html('Guidelines'),
|
||||
'description': fields.html('Description'),
|
||||
}
|
||||
|
||||
def _get_default_faq(self, cr, uid, context=None):
|
||||
fname = openerp.modules.get_module_resource('website_forum', 'data', 'forum_default_faq.html')
|
||||
with open(fname, 'r') as f:
|
||||
return f.read()
|
||||
return False
|
||||
|
||||
_defaults = {
|
||||
'description': 'This community is for professionals and enthusiasts of our products and services.',
|
||||
'faq': _get_default_faq,
|
||||
}
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
create_context = dict(context, mail_create_nolog=True)
|
||||
return super(Forum, self).create(cr, uid, values, context=create_context)
|
||||
|
||||
|
||||
class Post(osv.Model):
|
||||
_name = 'forum.post'
|
||||
_description = 'Forum Post'
|
||||
_inherit = ['mail.thread', 'website.seo.metadata']
|
||||
|
||||
def _get_user_vote(self, cr, uid, ids, field_name, arg, context):
|
||||
res = dict.fromkeys(ids, 0)
|
||||
vote_ids = self.pool['forum.post.vote'].search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], context=context)
|
||||
for vote in self.pool['forum.post.vote'].browse(cr, uid, vote_ids, context=context):
|
||||
res[vote.post_id.id] = vote.vote
|
||||
return res
|
||||
|
||||
def _get_vote_count(self, cr, uid, ids, field_name, arg, context):
|
||||
res = dict.fromkeys(ids, 0)
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
for vote in post.vote_ids:
|
||||
res[post.id] += int(vote.vote)
|
||||
return res
|
||||
|
||||
def _get_post_from_vote(self, cr, uid, ids, context=None):
|
||||
result = {}
|
||||
for vote in self.pool['forum.post.vote'].browse(cr, uid, ids, context=context):
|
||||
result[vote.post_id.id] = True
|
||||
return result.keys()
|
||||
|
||||
def _get_user_favourite(self, cr, uid, ids, field_name, arg, context):
|
||||
res = dict.fromkeys(ids, False)
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
if uid in [f.id for f in post.favourite_ids]:
|
||||
res[post.id] = True
|
||||
return res
|
||||
|
||||
def _get_favorite_count(self, cr, uid, ids, field_name, arg, context):
|
||||
res = dict.fromkeys(ids, 0)
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
res[post.id] += len(post.favourite_ids)
|
||||
return res
|
||||
|
||||
def _get_post_from_hierarchy(self, cr, uid, ids, context=None):
|
||||
post_ids = set(ids)
|
||||
for post in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||
if post.parent_id:
|
||||
post_ids.add(post.parent_id.id)
|
||||
return list(post_ids)
|
||||
|
||||
def _get_child_count(self, cr, uid, ids, field_name=False, arg={}, context=None):
|
||||
res = dict.fromkeys(ids, 0)
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
if post.parent_id:
|
||||
res[post.parent_id.id] = len(post.parent_id.child_ids)
|
||||
else:
|
||||
res[post.id] = len(post.child_ids)
|
||||
return res
|
||||
|
||||
def _get_uid_answered(self, cr, uid, ids, field_name, arg, context=None):
|
||||
res = dict.fromkeys(ids, False)
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
res[post.id] = any(answer.create_uid.id == uid for answer in post.child_ids)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Title', size=128),
|
||||
'forum_id': fields.many2one('forum.forum', 'Forum', required=True),
|
||||
'content': fields.html('Content'),
|
||||
'tag_ids': fields.many2many('forum.tag', 'forum_tag_rel', 'forum_id', 'forum_tag_id', 'Tags'),
|
||||
'state': fields.selection([('active', 'Active'), ('close', 'Close'), ('offensive', 'Offensive')], 'Status'),
|
||||
'views': fields.integer('Number of Views'),
|
||||
'active': fields.boolean('Active'),
|
||||
'is_correct': fields.boolean('Valid Answer', help='Correct Answer/ Answer on this question accepted.'),
|
||||
'website_message_ids': fields.one2many(
|
||||
'mail.message', 'res_id',
|
||||
domain=lambda self: [
|
||||
'&', ('model', '=', self._name), ('type', '=', 'comment')
|
||||
],
|
||||
string='Post Messages', help="Comments on forum post",
|
||||
),
|
||||
# history
|
||||
'create_date': fields.datetime('Asked on', select=True, readonly=True),
|
||||
'create_uid': fields.many2one('res.users', 'Created by', select=True, readonly=True),
|
||||
'write_date': fields.datetime('Update on', select=True, readonly=True),
|
||||
'write_uid': fields.many2one('res.users', 'Updated by', select=True, readonly=True),
|
||||
# vote fields
|
||||
'vote_ids': fields.one2many('forum.post.vote', 'post_id', 'Votes'),
|
||||
'user_vote': fields.function(_get_user_vote, string='My Vote', type='integer'),
|
||||
'vote_count': fields.function(
|
||||
_get_vote_count, string="Votes", type='integer',
|
||||
store={
|
||||
'forum.post': (lambda self, cr, uid, ids, c={}: ids, ['vote_ids'], 10),
|
||||
'forum.post.vote': (_get_post_from_vote, [], 10),
|
||||
}),
|
||||
# favorite fields
|
||||
'favourite_ids': fields.many2many('res.users', string='Favourite'),
|
||||
'user_favourite': fields.function(_get_user_favourite, string="My Favourite", type='boolean'),
|
||||
'favourite_count': fields.function(
|
||||
_get_favorite_count, string='Favorite Count', type='integer',
|
||||
store={
|
||||
'forum.post': (lambda self, cr, uid, ids, c={}: ids, ['favourite_ids'], 10),
|
||||
}),
|
||||
# hierarchy
|
||||
'parent_id': fields.many2one('forum.post', 'Question', ondelete='cascade'),
|
||||
'child_ids': fields.one2many('forum.post', 'parent_id', 'Answers'),
|
||||
'child_count': fields.function(
|
||||
_get_child_count, string="Answers", type='integer',
|
||||
store={
|
||||
'forum.post': (_get_post_from_hierarchy, ['parent_id', 'child_ids'], 10),
|
||||
}),
|
||||
'uid_has_answered': fields.function(
|
||||
_get_uid_answered, string='Has Answered', type='boolean',
|
||||
),
|
||||
# closing
|
||||
'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),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'state': 'active',
|
||||
'views': 0,
|
||||
'active': True,
|
||||
'vote_ids': list(),
|
||||
'favourite_ids': list(),
|
||||
'child_ids': list(),
|
||||
}
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
create_context = dict(context, mail_create_nolog=True)
|
||||
post_id = super(Post, self).create(cr, uid, vals, context=create_context)
|
||||
post = self.browse(cr, uid, post_id, context=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)
|
||||
else:
|
||||
self.message_post(cr, uid, post.id, subject=post.name, body=_('New Question Created'), subtype='website_forum.mt_question_new', context=context)
|
||||
self.pool['res.users'].write(cr, SUPERUSER_ID, [post.create_uid.id], {'karma': 2}, context=context)
|
||||
return post_id
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
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):
|
||||
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)
|
||||
# update karma of related user when any answer accepted
|
||||
if 'correct' in vals:
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
karma_value = 15 if vals.get('correct') else -15
|
||||
self.pool['res.users'].write(cr, SUPERUSER_ID, [post.create_uid.id], {'karma': karma_value}, context=context)
|
||||
return res
|
||||
|
||||
def vote(self, cr, uid, ids, upvote=True, context=None):
|
||||
Vote = self.pool['forum.post.vote']
|
||||
vote_ids = Vote.search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], context=context)
|
||||
if vote_ids:
|
||||
for vote in Vote.browse(cr, uid, vote_ids, context=context):
|
||||
if upvote:
|
||||
new_vote = '0' if vote.vote == '-1' else '1'
|
||||
else:
|
||||
new_vote = '0' if vote.vote == '1' else '-1'
|
||||
Vote.write(cr, uid, vote_ids, {'vote': new_vote}, context=context)
|
||||
else:
|
||||
for post_id in ids:
|
||||
new_vote = '1' if upvote else '-1'
|
||||
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 set_viewed(self, cr, uid, ids, context=None):
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
self.write(cr, uid, [post.id], {'views': post.views + 1}, context=context)
|
||||
return True
|
||||
|
||||
|
||||
class PostReason(osv.Model):
|
||||
_name = "forum.post.reason"
|
||||
_description = "Post Closing Reason"
|
||||
_columns = {
|
||||
'name': fields.char('Post Reason', required=True),
|
||||
}
|
||||
|
||||
|
||||
class Vote(osv.Model):
|
||||
_name = 'forum.post.vote'
|
||||
_description = 'Vote'
|
||||
_columns = {
|
||||
'post_id': fields.many2one('forum.post', 'Post', ondelete='cascade', required=True),
|
||||
'user_id': fields.many2one('res.users', 'User'),
|
||||
'vote': fields.selection([('1', '1'), ('-1', '-1'), ('0', '0')], 'Vote', required=True),
|
||||
'create_date': fields.datetime('Create Date', select=True, readonly=True),
|
||||
}
|
||||
_defaults = {
|
||||
'user_id': lambda self, cr, uid, ctx: uid,
|
||||
'vote': lambda *args: '1',
|
||||
}
|
||||
|
||||
def update_karma(self, cr, uid, ids, new_vote='0', old_vote='0', context=None):
|
||||
karma_value = (int(new_vote) - int(old_vote)) * 10
|
||||
if karma_value:
|
||||
for vote in self.browse(cr, uid, ids, context=context):
|
||||
self.pool['res.users'].add_karma(cr, SUPERUSER_ID, [vote.post_id.create_uid.id], karma_value, context=context)
|
||||
return True
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
vote_id = super(Vote, self).create(cr, uid, vals, context=context)
|
||||
self.update_karma(cr, uid, [vote_id], new_vote=vals.get('vote', '1'), context=context)
|
||||
return vote_id
|
||||
|
||||
def write(self, cr, uid, ids, values, context=None):
|
||||
res = super(Vote, self).write(cr, uid, ids, values, context=context)
|
||||
if 'vote' in values:
|
||||
for vote in self.browse(cr, uid, ids, context=context):
|
||||
self.update_karma(cr, uid, ids, new_vote=values['vote'], old_vote=vote.vote, context=context)
|
||||
return res
|
||||
|
||||
|
||||
class Tags(osv.Model):
|
||||
_name = "forum.tag"
|
||||
_description = "Tag"
|
||||
_inherit = ['website.seo.metadata']
|
||||
|
||||
def _get_posts_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
return dict((tag_id, self.pool['forum.post'].search_count(cr, uid, [('tag_ids', 'in', tag_id)], context=context)) for tag_id in ids)
|
||||
|
||||
def _get_tag_from_post(self, cr, uid, ids, context=None):
|
||||
return list(set(
|
||||
[tag.id for post in self.pool['forum.post'].browse(cr, SUPERUSER_ID, ids, context=context) for tag in post.tag_ids]
|
||||
))
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True),
|
||||
'forum_id': fields.many2one('forum.forum', 'Forum', required=True),
|
||||
'post_ids': fields.many2many('forum.post', 'forum_tag_rel', 'tag_id', 'post_id', 'Posts'),
|
||||
'posts_count': fields.function(
|
||||
_get_posts_count, type='integer', string="Number of Posts",
|
||||
store={
|
||||
'forum.post': (_get_tag_from_post, ['tag_ids'], 10),
|
||||
}
|
||||
),
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
|
||||
class gamification_challenge(osv.Model):
|
||||
_inherit = 'gamification.challenge'
|
||||
|
||||
def _get_categories(self, cr, uid, context=None):
|
||||
res = super(gamification_challenge, self)._get_categories(cr, uid, context=context)
|
||||
res.append(('forum', 'Website / Forum'))
|
||||
return res
|
||||
|
||||
|
||||
class Badge(osv.Model):
|
||||
_inherit = 'gamification.badge'
|
||||
_columns = {
|
||||
'level': fields.selection([('bronze', 'bronze'), ('silver', 'silver'), ('gold', 'gold')], 'Forum Badge Level'),
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
|
||||
class Users(osv.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
def _get_user_badge_level(self, cr, uid, ids, name, args, context=None):
|
||||
"""Return total badge per level of users"""
|
||||
result = dict.fromkeys(ids, False)
|
||||
badge_user_obj = self.pool['gamification.badge.user']
|
||||
for id in ids:
|
||||
result[id] = {
|
||||
'gold_badge': badge_user_obj.search(cr, uid, [('badge_id.level', '=', 'gold'), ('user_id', '=', id)], context=context, count=True),
|
||||
'silver_badge': badge_user_obj.search(cr, uid, [('badge_id.level', '=', 'silver'), ('user_id', '=', id)], context=context, count=True),
|
||||
'bronze_badge': badge_user_obj.search(cr, uid, [('badge_id.level', '=', 'bronze'), ('user_id', '=', id)], context=context, count=True),
|
||||
}
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'create_date': fields.datetime('Create Date', select=True, readonly=True),
|
||||
'karma': fields.integer('Karma'),
|
||||
'badge_ids': fields.one2many('gamification.badge.user', 'user_id', 'Badges'),
|
||||
'gold_badge': fields.function(_get_user_badge_level, string="Number of gold badges", type='integer', multi='badge_level'),
|
||||
'silver_badge': fields.function(_get_user_badge_level, string="Number of silver badges", type='integer', multi='badge_level'),
|
||||
'bronze_badge': fields.function(_get_user_badge_level, string="Number of bronze badges", type='integer', multi='badge_level'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'karma': 0,
|
||||
}
|
||||
|
||||
def add_karma(self, cr, uid, ids, karma, context=None):
|
||||
for user in self.browse(cr, uid, ids, context=context):
|
||||
self.write(cr, uid, [user.id], {'karma': user.karma + karma}, context=context)
|
||||
return True
|
|
@ -0,0 +1,19 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_forum_forum,forum.forum,model_forum_forum,,1,0,0,0
|
||||
access_forum_forum_manager,forum.forum.maanger,model_forum_forum,base.group_erp_manager,1,1,1,1
|
||||
|
||||
access_forum_post_public,forum.post.public,model_forum_post,base.group_public,1,0,0,0
|
||||
access_forum_post_portal,forum.post.portal,model_forum_post,base.group_portal,1,1,1,0
|
||||
access_forum_post_user,forum.post.user,model_forum_post,base.group_user,1,1,1,1
|
||||
|
||||
access_forum_post_vote_public,forum.post.vote.public,model_forum_post_vote,base.group_public,1,0,0,0
|
||||
access_forum_post_vote_portal,orum.post.vote.portal,model_forum_post_vote,base.group_portal,1,1,1,0
|
||||
access_forum_post_vote_user,forum.post.vote.user,model_forum_post_vote,base.group_user,1,1,1,1
|
||||
|
||||
access_forum_post_reason_public,forum.post.reason.public,model_forum_post_reason,base.group_public,1,0,0,0
|
||||
access_forum_post_reason_portal,forum.post.reason.portal,model_forum_post_reason,base.group_portal,1,0,0,0
|
||||
access_forum_post_reason_user,forum.post.reason.user,model_forum_post_reason,base.group_user,1,1,1,1
|
||||
|
||||
access_forum_tag_public,forum.tag.public,model_forum_tag,base.group_public,1,0,1,0
|
||||
access_forum_tag_portal,forum.tag.portal,model_forum_tag,base.group_portal,1,0,1,0
|
||||
access_forum_tag_user,forum.tag.user,model_forum_tag,base.group_user,1,1,1,1
|
|
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
|
@ -0,0 +1,5 @@
|
|||
all: website_forum.css
|
||||
%.css: %.sass
|
||||
sass -t expanded --compass --unix-newlines $< $@
|
||||
watch:
|
||||
sass -t expanded --compass --unix-newlines --watch .:.
|
|
@ -0,0 +1,82 @@
|
|||
.box {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
border-radius: 4px;
|
||||
min-width: 80px;
|
||||
}
|
||||
.box span {
|
||||
font-size: 200%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.question .question-name {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
.oe_grey {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.img-avatar {
|
||||
max-width: 50px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.badge-gold {
|
||||
color: #ffcc00;
|
||||
}
|
||||
|
||||
.badge-silver {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.badge-bronze {
|
||||
color: #eea91e;
|
||||
}
|
||||
|
||||
.oe_answer_true {
|
||||
color: #428bca;
|
||||
}
|
||||
|
||||
.oe_answer_false {
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.forum_favourite_question {
|
||||
color: #ffcc00 !important;
|
||||
}
|
||||
|
||||
.load_tags {
|
||||
width: 845px !important;
|
||||
}
|
||||
|
||||
a.no-decoration {
|
||||
cursor: pointer;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.faq-question:hover {
|
||||
text-decoration: none !important;
|
||||
color: #428bca;
|
||||
}
|
||||
|
||||
.oe_comment_grey {
|
||||
background-color: whitesmoke;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.country_flag {
|
||||
max-height: 16px;
|
||||
display: inline-block;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.tag_text .text-core .text-wrap textarea, .tag_text .text-core .text-wrap input, .tag_text .text-core .text-wrap .text-dropdown, .tag_text .text-core .text-wrap .text-prompt {
|
||||
font: 1.2em "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
||||
}
|
||||
.tag_text .text-core .text-wrap .text-tags .text-tag .text-button {
|
||||
font: 1.2em "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
||||
height: 1.2em !important;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
.box
|
||||
padding-left: 8px
|
||||
padding-right: 8px
|
||||
margin-left: 4px
|
||||
margin-right: 4px
|
||||
border-radius: 4px
|
||||
min-width: 80px
|
||||
span
|
||||
font-size: 200%
|
||||
font-weight: bold
|
||||
|
||||
.question
|
||||
.question-name
|
||||
font-size: 150%
|
||||
|
||||
.oe_grey
|
||||
background-color: #eeeeee
|
||||
|
||||
.img-avatar
|
||||
max-width: 50px
|
||||
margin-right: 10px
|
||||
|
||||
.badge-gold
|
||||
color: #ffcc00
|
||||
|
||||
.badge-silver
|
||||
color: #cccccc
|
||||
|
||||
.badge-bronze
|
||||
color: #eea91e
|
||||
|
||||
.oe_answer_true
|
||||
color: #428bca
|
||||
|
||||
.oe_answer_false
|
||||
color: #999999
|
||||
|
||||
.forum_favourite_question
|
||||
color: #ffcc00 !important
|
||||
|
||||
.load_tags
|
||||
width: 845px !important
|
||||
|
||||
a.no-decoration
|
||||
cursor: pointer
|
||||
text-decoration: none !important
|
||||
|
||||
.faq-question:hover
|
||||
text-decoration: none !important
|
||||
color: #428bca
|
||||
|
||||
.oe_comment_grey
|
||||
background-color: #f5f5f5
|
||||
padding: 4px
|
||||
|
||||
.country_flag
|
||||
max-height: 16px
|
||||
display: inline-block
|
||||
margin-left: 2px
|
||||
|
||||
.tag_text .text-core .text-wrap
|
||||
textarea, input, .text-dropdown, .text-prompt
|
||||
font: 1.2em "Helvetica Neue", Helvetica, Arial, sans-serif !important
|
||||
.text-tags .text-tag .text-button
|
||||
font: 1.2em "Helvetica Neue", Helvetica, Arial, sans-serif !important
|
||||
height: 1.2em !important
|
|
@ -0,0 +1,31 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
var website = openerp.website;
|
||||
var _t = openerp._t;
|
||||
|
||||
// website.EditorBar.include({
|
||||
// start: function () {
|
||||
// this.registerTour(new website.Tour.Forum(this));
|
||||
// return this._super();
|
||||
// },
|
||||
// });
|
||||
|
||||
// website.Tour.Forum = website.Tour.extend({
|
||||
// id: 'question',
|
||||
// name: "Create a question",
|
||||
// testPath: '/forum(/[0-9]+/register)?',
|
||||
// init: function (editor) {
|
||||
// var self = this;
|
||||
// self.steps = [
|
||||
// {
|
||||
// title: _t("Create a question"),
|
||||
// content: _t("Let's go through the first steps to create a new question."),
|
||||
// popover: { next: _("Start Tutorial"), end: _("Skip It") },
|
||||
// },
|
||||
// ];
|
||||
// return this._super();
|
||||
// }
|
||||
// });
|
||||
|
||||
}());
|
|
@ -0,0 +1,31 @@
|
|||
(function() {
|
||||
"use strict";
|
||||
|
||||
var website = openerp.website;
|
||||
var _t = openerp._t;
|
||||
website.add_template_file('/website_forum/static/src/xml/website_forum.xml');
|
||||
|
||||
website.is_editable = true;
|
||||
website.EditorBar.include({
|
||||
start: function() {
|
||||
website.is_editable_button = website.is_editable_button || !!$("#wrap").size();
|
||||
var res = this._super();
|
||||
this.$(".dropdown:has(.oe_content_menu)").removeClass("hidden");
|
||||
return res;
|
||||
},
|
||||
events: _.extend({}, website.EditorBar.prototype.events, {
|
||||
'click a[data-action=new_forum]': function (ev) {
|
||||
ev.preventDefault();
|
||||
website.prompt({
|
||||
id: "editor_new_forum",
|
||||
window_title: _t("New Forum"),
|
||||
input: "Forum Name",
|
||||
}).then(function (forum_name) {
|
||||
website.form('/forum/new', 'POST', {
|
||||
forum_name: forum_name
|
||||
});
|
||||
});
|
||||
}
|
||||
}),
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,156 @@
|
|||
$(document).ready(function () {
|
||||
|
||||
$('.vote_up ,.vote_down').on('click', function (ev) {
|
||||
ev.preventDefault();
|
||||
var $link = $(ev.currentTarget);
|
||||
openerp.jsonRpc($link.attr('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;">'+
|
||||
'<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;">'+
|
||||
'<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="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'+
|
||||
'</div>');
|
||||
}
|
||||
vote_alert = $link.parent().find("#vote_alert");
|
||||
if (vote_alert.length == 0) {
|
||||
$link.parent().append($warning);
|
||||
}
|
||||
} else {
|
||||
$link.parent().find("#vote_count").html(data['vote_count']);
|
||||
if (data['vote_count'] == 0) {
|
||||
$link.parent().find(".text-success").removeClass("text-success");
|
||||
$link.parent().find(".text-warning").removeClass("text-warning");
|
||||
} else {
|
||||
if (data['vote_count'] == 1) {
|
||||
$link.addClass("text-success");
|
||||
} else {
|
||||
$link.addClass("text-warning");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
});
|
||||
|
||||
$('.accept_answer').on('click', function (ev) {
|
||||
ev.preventDefault();
|
||||
var $link = $(ev.currentTarget);
|
||||
openerp.jsonRpc($link.attr('href'), 'call', {}).then(function (data) {
|
||||
if (data['error']) {
|
||||
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'] == 'own_post'){
|
||||
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, the user who asked this question can only accept the answer as correct.'+
|
||||
'</div>');
|
||||
}
|
||||
correct_answer_alert = $link.parent().find("#correct_answer_alert");
|
||||
if (correct_answer_alert.length == 0) {
|
||||
$link.parent().append($warning);
|
||||
}
|
||||
} else {
|
||||
$link.parents().find(".oe_answer_true").removeClass("oe_answer_true alert alert-info").addClass('oe_answer_false');
|
||||
$link.parents().find(".answer_correct").removeClass("answer_correct alert alert-info")
|
||||
if (data) {
|
||||
$link.removeClass("oe_answer_false").addClass('oe_answer_true');
|
||||
$link.parents('.forum_answer').first().addClass("answer_correct alert alert-info");
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
});
|
||||
|
||||
$('.favourite_question').on('click', function (ev) {
|
||||
ev.preventDefault();
|
||||
var $link = $(ev.currentTarget);
|
||||
openerp.jsonRpc($link.attr('href'), 'call', {}).then(function (data) {
|
||||
if (data) {
|
||||
$link.addClass("forum_favourite_question")
|
||||
} else {
|
||||
$link.removeClass("forum_favourite_question")
|
||||
}
|
||||
});
|
||||
return true;
|
||||
});
|
||||
|
||||
$('.comment_delete').on('click', function (ev) {
|
||||
ev.preventDefault();
|
||||
var $link = $(ev.currentTarget);
|
||||
openerp.jsonRpc($link.attr('href'), 'call', {}).then(function (data) {
|
||||
$link.parents('.comment').first().remove();
|
||||
});
|
||||
return true;
|
||||
});
|
||||
|
||||
$('.notification_close').on('click', function (ev) {
|
||||
ev.preventDefault();
|
||||
var $link = $(ev.currentTarget);
|
||||
openerp.jsonRpc("/forum/notification_read", 'call', {
|
||||
'notification_id': $link.attr("id")})
|
||||
return true;
|
||||
});
|
||||
|
||||
if($('input.load_tags').length){
|
||||
var tags = $("input.load_tags").val();
|
||||
$("input.load_tags").val("");
|
||||
set_tags(tags);
|
||||
};
|
||||
|
||||
function set_tags(tags) {
|
||||
$("input.load_tags").textext({
|
||||
plugins: 'tags focus autocomplete ajax',
|
||||
tagsItems: tags.split(","),
|
||||
//Note: The following list of keyboard keys is added. All entries are default except {32 : 'whitespace!'}.
|
||||
keys: {8: 'backspace', 9: 'tab', 13: 'enter!', 27: 'escape!', 37: 'left', 38: 'up!', 39: 'right',
|
||||
40: 'down!', 46: 'delete', 108: 'numpadEnter', 32: 'whitespace!'},
|
||||
ajax: {
|
||||
url: '/forum/get_tags',
|
||||
dataType: 'json',
|
||||
cacheResults: true
|
||||
}
|
||||
});
|
||||
// Note: Adding event handler of whitespaceKeyDown event.
|
||||
$("input.load_tags").bind("whitespaceKeyDown",function () {
|
||||
$(this).textext()[0].tags().addTags([ $(this).val() ]);
|
||||
$(this).val("");
|
||||
});
|
||||
}
|
||||
|
||||
if ($('textarea.load_editor').length) {
|
||||
var editor = CKEDITOR.instances['content'];
|
||||
editor.on('instanceReady', CKEDITORLoadComplete);
|
||||
}
|
||||
});
|
||||
|
||||
function IsKarmaValid(eventNumber,minKarma){
|
||||
"use strict";
|
||||
if(parseInt($("#karma").val()) >= minKarma){
|
||||
CKEDITOR.tools.callFunction(eventNumber,this);
|
||||
return false;
|
||||
} else {
|
||||
alert("Sorry you need more than 30 Karma.");
|
||||
}
|
||||
}
|
||||
|
||||
function CKEDITORLoadComplete(){
|
||||
"use strict";
|
||||
$('.cke_button__link').attr('onclick','IsKarmaValid(33,30)');
|
||||
$('.cke_button__unlink').attr('onclick','IsKarmaValid(37,30)');
|
||||
$('.cke_button__image').attr('onclick','IsKarmaValid(41,30)');
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<templates id="template" xml:space="preserve">
|
||||
<t t-extend="website.editorbar">
|
||||
<t t-jquery="ul.oe_content_menu" t-operation="append">
|
||||
<li><a href="#" data-action="new_forum">New Forum</a></li>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- MAIN FORUM MENU -->
|
||||
<menuitem name="Forum" id="menu_website_forum"
|
||||
parent="mail.mail_feeds_main" sequence="50"/>
|
||||
|
||||
<!-- FORUM VIEWS -->
|
||||
<record id="view_forum_forum_list" model="ir.ui.view">
|
||||
<field name="name">forum.forum.list</field>
|
||||
<field name="model">forum.forum</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Forums">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_forum_forum_form" model="ir.ui.view">
|
||||
<field name="name">forum.forum.form</field>
|
||||
<field name="model">forum.forum</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Forum" version="7.0">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="description"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_forum_forum" model="ir.actions.act_window">
|
||||
<field name="name">Forums</field>
|
||||
<field name="res_model">forum.forum</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_forum" parent="menu_website_forum" name="Forums" action="action_forum_forum" sequence="10"/>
|
||||
|
||||
<!-- POST VIEWS -->
|
||||
<record id="view_forum_post_list" model="ir.ui.view">
|
||||
<field name="name">forum.post.list</field>
|
||||
<field name="model">forum.post</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Forum Posts">
|
||||
<field name="name"/>
|
||||
<field name="forum_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_forum_post_form" model="ir.ui.view">
|
||||
<field name="name">forum.post.form</field>
|
||||
<field name="model">forum.post</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Forum Post" version="7.0">
|
||||
<sheet>
|
||||
<h1><field name="name" placeholder="Name"/></h1>
|
||||
<group>
|
||||
<field name="tag_ids" widget="many2many_tags"/>
|
||||
<field name="forum_id"/>
|
||||
<field name="parent_id"/>
|
||||
<field name="content" placeholder="e.g. Once upon a time..." widget="html"/>
|
||||
<group>
|
||||
<field name="create_date"/>
|
||||
<field name="create_uid"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="write_uid"/>
|
||||
<field name="write_date"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
|
||||
<field name="message_ids" widget="mail_thread" options='{"thread_level": 1}' placeholder="Send a message to the group"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_forum_post_search" model="ir.ui.view">
|
||||
<field name="name">forum.post.search</field>
|
||||
<field name="model">forum.post</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search in Post">
|
||||
<field name="name" string="Content" filter_domain="['|', ('name', 'ilike', self), ('content', 'ilike', self)]"/>
|
||||
<field name="create_uid"/>
|
||||
<field name="forum_id"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Forum" domain="[]" context="{'group_by': 'forum_id'}"/>
|
||||
<filter string="Author" domain="[]" context="{'group_by': 'create_uid'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_forum_post" model="ir.actions.act_window">
|
||||
<field name="name">Forum Posts</field>
|
||||
<field name="res_model">forum.post</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_forum_post_list"/>
|
||||
<field name="search_view_id" ref="view_forum_post_search"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_forum_posts" parent="menu_website_forum" name="Posts" action="action_forum_post" sequence="20"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,24 @@
|
|||
<openerp>
|
||||
<data>
|
||||
<template id="contact" inherit_id="base.contact" name="Forum Contact Widget">
|
||||
<xpath expr="//div[@itemprop='address']" position="after">
|
||||
<div>
|
||||
<div t-if="'karma' in fields" class='css_editable_mode_hidden'>
|
||||
<b><t t-esc="object.karma"/></b>
|
||||
<div t-if="options.get('badges')" style="display: inline-block">
|
||||
<t t-raw="separator"/>
|
||||
<b>|</b>
|
||||
<span class="fa fa-circle badge-gold"/>
|
||||
<t t-esc="object.gold_badge"/>
|
||||
<span class="fa fa-circle badge-silver"/>
|
||||
<t t-esc="object.silver_badge"/>
|
||||
<span class="fa fa-circle badge-bronze"/>
|
||||
<t t-esc="object.bronze_badge"/>
|
||||
</div>
|
||||
<t t-raw="0"/>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Update user form !-->
|
||||
<record id="view_users_form_forum" model="ir.ui.view">
|
||||
<field name="name">res.users.form.forum</field>
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base.view_users_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="signature" position="after">
|
||||
<field name="karma" string="Forum Karma"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,906 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Editor custo -->
|
||||
<template id="editor_head" inherit_id="website.editor_head"
|
||||
name="Event Editor">
|
||||
<xpath expr="//script[@id='website_tour_js']" position="after">
|
||||
<script type="text/javascript" src="/website_forum/static/src/js/website.tour.forum.js"/>
|
||||
<script type="text/javascript" src="/website_forum/static/src/js/website_forum.editor.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Layout add nav and footer -->
|
||||
<template id="header_footer_custom" inherit_id="website.layout"
|
||||
name="Footer Questions Link">
|
||||
<xpath expr="//footer//ul[@name='products']" position="inside">
|
||||
<li><a t-attf-href="/forum/%(website_forum.forum_help)d">Q&A</a></li>
|
||||
<li><a href="/forum">Forums</a></li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- Page Index -->
|
||||
<template id="header" name="Forum Index">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="head">
|
||||
<link rel='stylesheet' href="/web/static/lib/jquery.textext/jquery.textext.css"/>
|
||||
<link rel='stylesheet' href='/website_forum/static/src/css/website_forum.css'/>
|
||||
<!--
|
||||
FP Note: Why do we need this ? Can we remove this code?
|
||||
The problem is that you add your script for every page, not only for the forum
|
||||
-->
|
||||
<script type="text/javascript" src="/website_forum/static/src/js/website_forum.js"/>
|
||||
<script type="text/javascript" src="/web/static/lib/jquery.textext/jquery.textext.js"/>
|
||||
<script type="text/javascript" src="/web/static/lib/ckeditor/ckeditor.js"/>
|
||||
<script type="text/javascript">
|
||||
CKEDITOR.config.toolbar = [['Bold','Italic','Underline','Strike'],['NumberedList','BulletedList', 'Blockquote']
|
||||
,['Outdent','Indent','Link','Unlink','Image'],] ;
|
||||
</script>
|
||||
</t>
|
||||
<div class="container mt16">
|
||||
<div class="navbar navbar-default">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#oe-help-navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<!-- <span class="icon-bar"></span> -->
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" t-attf-href="/forum/#{slug(forum)}">
|
||||
<span t-field="forum.name"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="oe-help-navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li t-att-class="filters in ('all', 'unanswered','followed','question','tag') and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }">Questions</a>
|
||||
</li>
|
||||
<li t-att-class="searches.get('users') and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/users">People</a>
|
||||
</li>
|
||||
<li t-att-class="searches.get('tags') and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/tag">Tags</a>
|
||||
</li>
|
||||
<li t-att-class="searches.get('badges') and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/badge">Badges</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="navbar-form navbar-right" role="search" t-attf-action="/forum/#{ slug(forum) }" method="get">
|
||||
<div class="form-group">
|
||||
<input type="search" class="form-control"
|
||||
name="search" placeholder="Search a question..."
|
||||
t-att-value="search or ''"/>
|
||||
<button type="submit" class="btn btn-default">Search</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="wrap" class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-9">
|
||||
<div t-foreach="notifications or []" t-as="notification" class="alert alert-success alert-dismissable">
|
||||
<button type="button" class="close notification_close" t-att-id="notification.id" data-dismiss="alert" aria-hidden="true">&times;</button>
|
||||
<div t-field="notification.body"/>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/user/#{ slug(user) }#badges" class="fa fa-arrow-right">View Your Badges</a>
|
||||
</div>
|
||||
<t t-raw="0"/>
|
||||
</div>
|
||||
<div class="col-sm-3" id="right-column">
|
||||
<a t-if="not header.get('ask_hide')" class="btn btn-primary btn-lg btn-block mb16" t-attf-href="/forum/#{slug(forum)}/ask">Ask a Question</a>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">About This Forum</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<t t-raw="forum.description"/><br/>
|
||||
<a t-attf-href="/forum/#{slug(forum)}/faq" class="fa fa-arrow-right"> Read Guidelines</a>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="header.get('question_data')">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading text-center">
|
||||
<h3 class="panel-title">Question tools</h3>
|
||||
</div>
|
||||
<div class="panel-body text-center">
|
||||
<t t-call="website_mail.follow"><t t-set="object" t-value="question"/></t>
|
||||
<div class="mt8">
|
||||
<strong><t t-raw="len(question.message_follower_ids)"/></strong> follower(s)
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-heading text-center">
|
||||
<h3 class="panel-title ">Stats</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table">
|
||||
<thead><tr><td> Asked: <strong><span t-field="question.create_date" t-field-options='{"format":"short"}'/></strong></td></tr></thead>
|
||||
<tr><td> Seen: <strong><t t-raw="question.views"/></strong>
|
||||
<span t-if="question.views>1">times</span>
|
||||
<span t-if="question.views<=1">time</span>
|
||||
</td></tr>
|
||||
<tr><td> Last updated: <strong><span t-field="question.write_date" t-field-options='{"format":"short"}'/></strong></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_structure"/>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Display a post -->
|
||||
<template id="display_post">
|
||||
<div class="question clearfix">
|
||||
<div class="pull-left text-center">
|
||||
<div t-attf-class="box #{question.child_count and 'oe_green' or 'oe_grey'}">
|
||||
<span t-esc="question.child_count"/>
|
||||
<span t-if="question.is_correct" class="fa fa-2x fa-check-circle"/>
|
||||
<div t-if="question.child_count>1">Answers</div>
|
||||
<div t-if="question.child_count<=1">Answer</div>
|
||||
</div>
|
||||
<div class="text-muted text-center">
|
||||
<span t-field="question.views"/> Views
|
||||
</div>
|
||||
</div>
|
||||
<div class="pull-right text-center">
|
||||
<div class="box oe_grey">
|
||||
<span t-esc="question.vote_count or 0"/>
|
||||
<div t-if="question.vote_count>1">Votes</div>
|
||||
<div t-if="question.vote_count<=1">Vote</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-left: 95px;">
|
||||
<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>
|
||||
<span t-if="question.state == 'close'"><b> [Closed]</b></span>
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
by <a t-attf-href="/forum/#{ slug(forum) }/user/#{ question.create_uid.id }"
|
||||
t-field="question.create_uid" t-field-options='{"widget": "contact", "country_image": true, "fields": ["name", "country_id"]}'
|
||||
style="display: inline-block;"/>
|
||||
on <span t-field="question.write_date" t-field-options='{"format":"short"}'/>
|
||||
</div>
|
||||
<t t-foreach="question.tag_ids" t-as="tag">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/tag/#{ tag.id }/questions" class="badge" t-field="tag.name"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Display a post as an answer -->
|
||||
<template id="display_post_answer">
|
||||
<div class="clearfix">
|
||||
<div t-attf-class="pull-left text-center mb16 box #{len(answer.vote_ids) and 'oe_green' or 'oe_grey'}">
|
||||
<div t-esc="len(answer.vote_ids)"/>
|
||||
</div>
|
||||
<div class="question-name" style="margin-left: 32px;">
|
||||
<a style="font-size: 15px;" t-attf-href="/forum/#{ slug(forum) }/question/#{ answer.parent_id.id }/#answer-#{ answer.id }" t-esc="answer.parent_id.name"/>
|
||||
<t t-if="len(answer.website_message_ids)>0">
|
||||
(<t t-esc="len(answer.website_message_ids)"/>
|
||||
<t t-if="len(answer.website_message_ids)>1">Comments</t>
|
||||
<t t-if="len(answer.website_message_ids)<=1">Comment</t>)
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- FAQ Layout -->
|
||||
<template id="faq">
|
||||
<t t-call="website_forum.header">
|
||||
<div t-field="forum.faq"/>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- All Forums Layout -->
|
||||
<template id="forum_all">
|
||||
<t t-call="website.layout">
|
||||
<div class="container">
|
||||
<h1 class="mb32">Our forums</h1>
|
||||
<div class="row">
|
||||
<div t-foreach="forums" t-as="forum" class="col-sm-3 text-center mb32">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }">
|
||||
<div class="fa fa-5x fa-comment mb16"/>
|
||||
<div t-field="forum.name"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Specific Forum Layout -->
|
||||
<template id="forum_index" name="Forum">
|
||||
<t t-call="website_forum.header">
|
||||
<h1 class="page-header mt0">
|
||||
<t t-esc="len(question_ids)"/> <span>Questions</span>
|
||||
<t t-esc="search"/>
|
||||
<small class="dropdown" t-if="filters in ('all', 'unanswered','followed', 'tag')">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<t t-if="filters == 'all'">All</t>
|
||||
<t t-if="filters == 'unanswered'">Unanswered</t>
|
||||
<t t-if="filters == 'followed'">Followed</t>
|
||||
<t t-if="filters == 'tag'">Tag</t>
|
||||
<t t-if="sorting == 'date'"> by activity date</t>
|
||||
<t t-if="sorting == 'answered'"> by most answered</t>
|
||||
<t t-if="sorting == 'vote'"> by most voted</t>
|
||||
<b class="caret"/>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="dropdown-header">Filter on</li>
|
||||
<li t-att-class="filters == 'all' and 'active' or '' ">
|
||||
<a t-att-href="url_for('') + '?' + keep_query( 'search', 'sorting', filters='all')">All</a>
|
||||
</li>
|
||||
<li t-att-class="filters == 'unanswered' and 'active' or '' ">
|
||||
<a t-att-href="url_for('') + '?' + keep_query( 'search', 'sorting', filters='unanswered')">Unanswered</a>
|
||||
</li>
|
||||
<li t-if="uid" t-att-class="filters == 'followed' and 'active' or '' ">
|
||||
<a t-att-href="url_for('') + '?' + keep_query( 'search', 'sorting', filters='followed')">Followed</a>
|
||||
</li>
|
||||
<li class="dropdown-header">Tags</li>
|
||||
<li t-if="tag" t-att-class="tag and 'active' or '' ">
|
||||
<a href=""><t t-esc="tag.name"/></a>
|
||||
</li>
|
||||
<li class="dropdown-header">Sort by</li>
|
||||
<li t-att-class="sorting == 'date' and 'active' or '' ">
|
||||
<a t-att-href="url_for('') + '?' + keep_query( 'search', 'filters', sorting='date')">Last activity date</a>
|
||||
</li>
|
||||
<li t-att-class="sorting == 'answered' and 'active' or '' ">
|
||||
<a t-att-href="url_for('') + '?' + keep_query( 'search', 'filters', sorting='answered')">Most answered</a>
|
||||
</li>
|
||||
<li t-att-class="sorting == 'vote' and 'active' or '' ">
|
||||
<a t-att-href="url_for('') + '?' + keep_query( 'search', 'filters', sorting='vote')">Most voted</a>
|
||||
</li>
|
||||
</ul>
|
||||
</small>
|
||||
</h1>
|
||||
<div t-foreach="question_ids" t-as="question" class="mb16">
|
||||
<t t-call="website_forum.display_post"/>
|
||||
</div>
|
||||
<t t-call="website.pager"/>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="404">
|
||||
<t t-call="website_forum.header">
|
||||
<div class="oe_structure oe_empty"/>
|
||||
<h1 class="mt32">Question not found!</h1>
|
||||
<p>Sorry, this question is not available anymore.</p>
|
||||
<p>
|
||||
<a t-attf-href="/forum">Return to the question list.</a>
|
||||
</p>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Edition: ask your question -->
|
||||
<template id="ask_question">
|
||||
<t t-call="website_forum.header">
|
||||
<h1 class="mt0">Ask your Question</h1>
|
||||
<ul>
|
||||
<li> please, try to make your question interesting to others </li>
|
||||
<li> provide enough details and, if possible, give an example </li>
|
||||
<li> be clear and concise, avoid unnecessary introductions (Hi, ... Thanks...) </li>
|
||||
</ul>
|
||||
<form t-attf-action="/forum/#{ slug(forum) }/question/new" method="post" role="form" class="tag_text">
|
||||
<input type="text" name="question_name" required="True" t-attf-value="#{question_name}"
|
||||
class="form-control" placeholder="Enter your Question"/>
|
||||
<h5 class="mt20">Please enter a descriptive question (should finish by a '?')</h5>
|
||||
<input type="hidden" name="karma" t-attf-value="#{user.karma}" id="karma"/>
|
||||
<textarea name="content" required="True" class="form-control load_editor">
|
||||
<t t-esc="question_content"/>
|
||||
</textarea>
|
||||
<br/>
|
||||
<input type="text" name="question_tags" placeholder="Tags" class="form-control load_tags"/>
|
||||
<br/>
|
||||
<button class="btn btn-primary" id="btn_ask_your_question">Post Your Question</button>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
CKEDITOR.replace("content");
|
||||
</script>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Edition: edit a post -->
|
||||
<template id="edit_post">
|
||||
<t t-call="website_forum.header">
|
||||
<h3 t-if="not is_answer">Edit question</h3>
|
||||
<h3 t-if="is_answer">Edit answer</h3>
|
||||
<form t-attf-action="/forum/#{slug(forum)}/post/#{slug(post)}/save" method="post" role="form" class="tag_text">
|
||||
<div t-if="not is_answer">
|
||||
<input type="text" name="question_name" id="question_name" required="True"
|
||||
t-attf-value="#{post.name}" class="form-control" placeholder="Edit your Question"/>
|
||||
<h5 class="mt20">Please enter a descriptive question (should finish by a '?')</h5>
|
||||
</div>
|
||||
<input type="hidden" name="karma" t-attf-value="#{user.karma}" id="karma"/>
|
||||
<textarea name="content" required="True" class="form-control load_editor">
|
||||
<t t-esc="post.content"/>
|
||||
</textarea>
|
||||
<div t-if="not is_answer">
|
||||
<br/>
|
||||
<input type="text" name="question_tag" class="form-control col-md-9 load_tags" placeholder="Tags" t-attf-value="#{tags}"/>
|
||||
<br/>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-lg">Save</button>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
CKEDITOR.replace("content");
|
||||
</script>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Moderation: close a question -->
|
||||
<template id="close_question">
|
||||
<t t-call="website_forum.header">
|
||||
<h3 class=""><b>Close question</b></h3><br/>
|
||||
<form t-attf-action="/forum/#{ slug(forum) }/question/#{slug(question)}/close" method="post" role="form">
|
||||
<input name="post_id" t-att-value="post.id" type="hidden"/>
|
||||
<span class="pull-left">Close the question:</span>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/question/#{ slug(post) }" t-field="post.name"/>
|
||||
<div class="mt16">
|
||||
<label class="col-md-2 control-label mb16" for="reason">Reasons:</label>
|
||||
<div class="col-md-9 mb16">
|
||||
<select class="form-control" name="reason">
|
||||
<t t-foreach="reasons or []" t-as="reason">
|
||||
<option t-att-value="reason.id" t-att-selected="reason.id == post.closed_reason_id.id"><t t-esc="reason.name"/></option>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-primary btn-lg">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Edition: post an answer -->
|
||||
<template id="post_answer">
|
||||
<h3 class="mt10">Your answer</h3>
|
||||
<p>
|
||||
<b>Please try to give a substantial answer.</b> If you wanted to comment on the question or answer, just
|
||||
<b>use the commenting tool.</b> Please remember that you can always <b>revise your answers</b>
|
||||
- no need to answer the same question twice. Also, please <b>don't forget to vote</b>
|
||||
- it really helps to select the best questions and answers!
|
||||
</p>
|
||||
<form t-attf-action="/forum/#{ slug(forum) }/post/#{slug(question)}/new" method="post" role="form">
|
||||
<input type="hidden" name="karma" t-attf-value="#{user.karma}" id="karma"/>
|
||||
<textarea name="content" class="form-control load_editor" required="True"/>
|
||||
<button class="btn btn-primary" id="btn_ask_your_question">Post Your Answer</button>
|
||||
</form>
|
||||
<script type="text/javascript">
|
||||
CKEDITOR.replace("content");
|
||||
</script>
|
||||
</template>
|
||||
|
||||
<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 ''}"
|
||||
t-attf-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 ''}"
|
||||
t-attf-href="/forum/#{slug(post.forum_id)}/post/#{slug(post)}/downvote"/>
|
||||
<div>
|
||||
votes
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Specific Post Layout -->
|
||||
<template id="post_description_full" name="Question Navigation">
|
||||
<t t-call="website_forum.header">
|
||||
|
||||
<div t-attf-class="question #{not question.active and 'alert alert-danger' or ''}">
|
||||
<div class="text-center pull-left">
|
||||
<t t-call="website_forum.vote">
|
||||
<t t-set="post" t-value="question"/>
|
||||
</t>
|
||||
<div class="text-muted">
|
||||
<span t-esc="question.child_count"/>
|
||||
<span t-if="question.child_count>1">Answers</span>
|
||||
<span t-if="question.child_count<=1">Answer</span>
|
||||
</div>
|
||||
<div>
|
||||
<a t-attf-href="/forum/#{slug(question.forum_id)}/question/#{slug(question)}/toggle_favourite"
|
||||
t-attf-class="favourite_question no-decoration fa fa-2x fa-star #{question.user_favourite and 'forum_favourite_question' or ''}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-left: 95px;">
|
||||
<h1 class="mt0">
|
||||
<span t-field="question.name"/>
|
||||
<span t-if="not question.active"><b> [Deleted]</b></span>
|
||||
<span t-if="question.state == 'close'"><b> [Closed]</b></span>
|
||||
</h1>
|
||||
<t t-raw="question.content"/>
|
||||
|
||||
<div class="mt16 clearfix">
|
||||
<div class="pull-right">
|
||||
<div class="text-right">
|
||||
<t t-foreach="question.tag_ids" t-as="tag">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/tag/#{ tag.id }/questions" class="badge" t-field="tag.name"/>
|
||||
</t>
|
||||
</div>
|
||||
<ul class="list-inline">
|
||||
<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) }">
|
||||
comment
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="question.state != 'close' and (user.id == question.create_uid.id or user.karma>=100)">
|
||||
<a class="text-muted fa fa-times" t-attf-href="/forum/#{ slug(forum) }/question/#{slug(question)}/ask_for_close">close</a>
|
||||
</li>
|
||||
<li t-if="question.state == 'close' and user.karma>=500">
|
||||
<a class="text-muted fa fa-undo" t-attf-href="/forum/#{ slug(forum) }/question/#{slug(question)/reopen">reopen</a>
|
||||
</li>
|
||||
<li t-if="user.id == question.create_uid.id or user.karma>=300">
|
||||
<a class="text-muted fa fa-edit" t-attf-href="/forum/#{ slug(forum) }/post/#{slug(question)}/edit">edit</a>
|
||||
</li>
|
||||
<li t-if="question.active and user.id == question.create_uid.id or user.karma>=1000">
|
||||
<a class="text-muted fa fa-trash-o" t-attf-href="/forum/#{ slug(forum) }/question/#{slug(question)}/delete">delete</a>
|
||||
</li>
|
||||
<li t-if="uid == question.create_uid.id and not question.active">
|
||||
<a class="text-muted fa fa-trash-o" t-attf-href="/forum/#{ slug(forum) }/question/#{slug(question)}/undelete">undelete</a>
|
||||
</li>
|
||||
<li><a class="text-muted fa fa-share" t-attf-href="/forum/#{slug(forum)}/question/#{slug(question)}">share</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<span t-field="question.create_uid.image" t-field-options='{"widget": "image", "class":"pull-left img img-circle img-avatar"}'/>
|
||||
<div>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/user/#{ user.id }"
|
||||
t-field="question.create_uid"
|
||||
t-field-options='{"widget": "contact", "country_image": true, "fields": ["name", "country_id"]}'
|
||||
style="display: inline-block;"/>
|
||||
<div t-field="question.create_uid" t-field-options='{"widget": "contact", "badges": true, "fields": ["karma"]}'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-info" t-if="question.state == 'close'">
|
||||
<p class="mt32 mb32 text-center">
|
||||
<b>The question has been closed for the following reason "<span t-field="question.closed_reason_id.name"/>"
|
||||
<t t-if="question.closed_uid">
|
||||
<i>by <a t-attf-href="/forum/#{ slug(forum) }/user/#{ slug(question.closed_uid) }" t-field="question.closed_uid.name"/> </i>
|
||||
</t>
|
||||
<br/>close date <span t-field="question.closed_date"/></b>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<t t-call="website_forum.post_comment">
|
||||
<t t-set="object" t-value="question"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
|
||||
<div t-foreach="question.child_ids" t-as="answer" class="mt16 mb32">
|
||||
<a t-attf-id="answer-#{str(answer.id)}"/>
|
||||
<div t-attf-class="forum_answer #{answer.is_correct and 'alert alert-info answer_correct' or ''}" t-attf-id="answer_#{answer.id}" >
|
||||
<div class="text-center pull-left">
|
||||
<t t-call="website_forum.vote">
|
||||
<t t-set="post" t-value="answer"/>
|
||||
</t>
|
||||
<div class="text-muted">
|
||||
<a t-attf-class="accept_answer fa fa-2x fa-check-circle no-decoration oe_answer_true #{answer.is_correct and 'oe_answer_true' or 'oe_answer_false'}"
|
||||
t-attf-href="/forum/#{slug(question.forum_id)}/post/#{slug(answer)}/toggle_correct"/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-left: 95px;" class="clearfix">
|
||||
<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
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="user.id == answer.create_uid.id or user.karma>=300">
|
||||
<a class="text-muted fa fa-edit" t-attf-href="/forum/#{slug(forum)}/post/#{slug(answer)}/edit">edit</a>
|
||||
</li>
|
||||
<li t-if="user.id == answer.create_uid.id or user.karma>=1000">
|
||||
<a class="text-muted fa fa-trash-o" t-attf-href="/forum/#{slug(forum)}/post/#{slug(answer)}/delete">delete</a>
|
||||
</li>
|
||||
<li t-if="user.id == answer.create_uid.id">
|
||||
<a class="text-muted fa fa-magic" t-attf-href="/forum/#{slug(forum)}/post/#{slug(answer)}/convert_to_comment">Convert as a comment</a>
|
||||
</li>
|
||||
<li><a class="text-muted fa fa-share" t-attf-href="/forum/#{slug(forum)}/question/#{slug(question)}/#answer_#{answer.id}">share</a></li>
|
||||
</ul>
|
||||
<span t-field="answer.create_uid.image" t-field-options='{"widget": "image", "class":"pull-left img img-circle img-avatar"}'/>
|
||||
<div>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/user/#{ user.id }"
|
||||
t-field="answer.create_uid"
|
||||
t-field-options='{"widget": "contact", "country_image": true, "fields": ["name", "country_id"]}'
|
||||
style="display: inline-block;"/>
|
||||
<div t-field="answer.create_uid" t-field-options='{"widget": "contact", "badges": true, "fields": ["karma"]}'/>
|
||||
<span class="text-muted">Answered on <span t-field="answer.create_date" t-field-options='{"format":"short"}'/></span>
|
||||
</div>
|
||||
</div>
|
||||
<t t-call="website_forum.post_comment">
|
||||
<t t-set="object" t-value="answer"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="not question.uid_has_answered">
|
||||
<t t-call="website_forum.post_answer"/>
|
||||
</div>
|
||||
<div t-if="question.uid_has_answered" class="mb16">
|
||||
<a class="btn btn-primary" t-attf-href="/forum/#{slug(forum)}/question/#{slug(question)}/edit_answer">Edit Your Previous Answer</a>
|
||||
<span class="text-muted">(only one answer per question is allowed)</span>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- Utility template: Post a Comment -->
|
||||
<template id="post_comment">
|
||||
<div class="row clearfix">
|
||||
<div class="col-sm-10 col-sm-offset-2">
|
||||
<div t-foreach="reversed(object.website_message_ids)" t-as="message" class="comment oe_comment_grey mb8">
|
||||
<small class="text-muted">
|
||||
<button type="button" t-if="user.partner_id.id == message.author_id.id and user.karma>=750"
|
||||
t-attf-href="/forum/#{slug(forum)}/post/#{slug(object)}/comment/#{slug(message)}/delete"
|
||||
class="close comment_delete">&times;</button>
|
||||
<span t-field="message.body"/>
|
||||
<a t-attf-href="/forum/#{slug(forum)}/user/#{message.id}"
|
||||
t-field="message.author_id" t-field-options='{"widget": "contact", "country_image": true, "fields": ["name", "country_id"]}'
|
||||
style="display: inline-block;"/>
|
||||
on <span t-field="message.date" t-field-options='{"format":"short"}'/>
|
||||
<a class="fa fa-magic text-muted pull-right"
|
||||
t-attf-href="/forum/#{slug(forum)}/post/#{slug(object)}/comment/#{slug(message)}/convert_to_answer">Convert as an answer</a>
|
||||
</small>
|
||||
</div>
|
||||
<div class="css_editable_mode_hidden">
|
||||
<form t-attf-id="comment#{ object._name.replace('.','') + '-' + str(object.id) }" class="collapse"
|
||||
t-attf-action="/forum/#{slug(forum)}/post/#{slug(object)}/comment" method="POST">
|
||||
<input name="post_id" t-att-value="object.id" type="hidden"/>
|
||||
<textarea name="comment" class="form-control" placeholder="Comment this post..."/>
|
||||
<button type="submit" class="btn btn-primary mt8">Post</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="tag">
|
||||
<t t-call="website_forum.header">
|
||||
<h1 class="mt0">
|
||||
Tags
|
||||
</h1>
|
||||
<p class="text-muted">
|
||||
A tag is a label that categorizes your question with other,
|
||||
similar questions. Using the right tags makes it easier for
|
||||
others to find and answer your question.
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 mt16" t-foreach="tags" t-as="tag">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/tag/#{ slug(tag) }/questions?{{ keep_query( filters='tag') }}" class="badge">
|
||||
<span t-field="tag.name"/>
|
||||
</a>
|
||||
<span>
|
||||
X <t t-esc="tag.posts_count"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="badge">
|
||||
<t t-call="website_forum.header">
|
||||
<h1 class="mt0">
|
||||
Badges
|
||||
</h1>
|
||||
<p>
|
||||
Besides gaining reputation with your questions and answers,
|
||||
you receive badges for being especially helpful. Badges
|
||||
appear on your profile page, and your posts.
|
||||
</p>
|
||||
<table class="table mt32 mb64">
|
||||
<tr t-foreach="badges" t-as="badge">
|
||||
<td>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/badge/#{ slug(badge) }" class="badge pull-left">
|
||||
<span t-if="badge.level == 'gold'" class="fa fa-circle badge-gold"/>
|
||||
<span t-if="badge.level == 'silver'" class="fa fa-circle badge-silver"/>
|
||||
<span t-if="badge.level == 'bronze'" class="fa fa-circle badge-bronze"/>
|
||||
<span t-field="badge.name"/>
|
||||
</a>
|
||||
</td><td>
|
||||
<b t-esc="badge.stat_count_distinct"/>
|
||||
<i class="text-muted">awarded users</i>
|
||||
</td><td>
|
||||
<span t-field="badge.description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="badge_user">
|
||||
<t t-call="website_forum.header">
|
||||
<h3 class="mt32 mb32">
|
||||
<b>Badge "<span t-field="badge.name"/>"</b>
|
||||
</h3>
|
||||
<div>
|
||||
<div class="pull-left badge">
|
||||
<span t-if="badge.level == 'gold'" class="fa fa-circle badge-gold"/>
|
||||
<span t-if="badge.level == 'silver'" class="fa fa-circle badge-silver"/>
|
||||
<span t-if="badge.level == 'bronze'" class="fa fa-circle badge-bronze"/>
|
||||
<span t-field="badge.name"/>
|
||||
</div>
|
||||
<span t-field="badge.description" style="margin-left:20px"/>
|
||||
</div>
|
||||
<h4 class="mt32">
|
||||
<t class="pull-left" t-esc="badge.stat_count_distinct"/>
|
||||
<span t-if="badge.stat_count_distinct>1">users</span>
|
||||
<span t-if="badge.stat_count_distinct<=1">user</span>
|
||||
received this badge:
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 mt16" t-foreach="users" t-as="user">
|
||||
<span t-field="user.image" t-field-options='{"widget": "image", "class":"pull-left img img-circle img-avatar"}'/>
|
||||
<div>
|
||||
<a t-attf-href="/forum/#{slug(forum)}/user/#{user.id}" t-field="user.name"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="users">
|
||||
<t t-call="website_forum.header">
|
||||
<div class="row">
|
||||
<div t-foreach="users" t-as="user" class="col-sm-4">
|
||||
<span t-field="user.image" t-field-options='{"widget": "image", "class":"pull-left img img-circle img-avatar"}'/>
|
||||
<div>
|
||||
<a t-attf-href="/forum/#{slug(forum)}/user/#{user.id}" t-field="user.name"/>
|
||||
<t t-if="user.country_id">
|
||||
<span t-field="user.country_id.image" t-field-options='{"widget": "image", "class": "country_flag"}'/>
|
||||
</t>
|
||||
<b><t t-esc="user.karma"/></b>
|
||||
<t t-raw="separator"/>
|
||||
<div>
|
||||
<b> badges:</b>
|
||||
<span class="fa fa-circle badge-gold"/>
|
||||
<t t-esc="user.gold_badge"/>
|
||||
<span class="fa fa-circle badge-silver"/>
|
||||
<t t-esc="user.silver_badge"/>
|
||||
<span class="fa fa-circle badge-bronze"/>
|
||||
<t t-esc="user.bronze_badge"/>
|
||||
</div>
|
||||
<t t-raw="0"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pull-left">
|
||||
<t t-call="website.pager"/>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="edit_profile">
|
||||
<t t-call="website_forum.header">
|
||||
<h3>Edit Profile </h3>
|
||||
<div class="col-md-2">
|
||||
<span t-field="user.image" t-field-options='{"widget": "image", "class": "img img-responsive img-circle"}'/>
|
||||
</div>
|
||||
<form t-attf-action="/forum/#{slug(forum)}/user/#{slug(user)}/save" method="post" role="form" class="form-horizontal">
|
||||
<input name="user_id" t-att-value="user.id" type="hidden"/>
|
||||
<label class="col-md-2 control-label mb16" for="user.name">Real name</label>
|
||||
<div class="col-md-7 mb16">
|
||||
<input type="text" class="col-md-7 mb16 form-control" name="name" required="True" t-attf-value="#{user.name}"/>
|
||||
</div>
|
||||
<label class="col-md-2 control-label mb16" for="user.partner_id.website">Website</label>
|
||||
<div class="col-md-7 mb16">
|
||||
<input type="text" class="form-control" name="website" t-attf-value="#{user.partner_id.website or ''}"/>
|
||||
</div>
|
||||
<label class="col-md-4 control-label mb16" for="user.partner_id.email">Email</label>
|
||||
<div class="col-md-7 mb16">
|
||||
<input type="text" class="form-control" name="email" required="True" t-attf-value="#{user.partner_id.email}"/>
|
||||
</div>
|
||||
<label class="col-md-4 control-label mb16" for="user.partner_id.city">City</label>
|
||||
<div class="col-md-7 mb16">
|
||||
<input type="text" class="form-control" name="city" t-attf-value="#{user.partner_id.city or ''}"/>
|
||||
</div>
|
||||
<label class="col-md-4 control-label mb16" for="contact_name">Country</label>
|
||||
<div class="col-md-7 mb16">
|
||||
<select class="form-control" name="country">
|
||||
<option value="">Country...</option>
|
||||
<t t-foreach="countries or []" t-as="country">
|
||||
<option t-att-value="country.id" t-att-selected="country.id == user.partner_id.country.id"><t t-esc="country.name"/></option>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
<!--Note: using website_description fiels instead of using commnt firld of partner-->
|
||||
<label class="col-md-4 control-label mb16" for="user.partner_id.website_description">Biography</label>
|
||||
<div class="col-md-7 mb16">
|
||||
<textarea name="description" style="min-height: 120px" required="True"
|
||||
class="form-control"><t t-esc="user.partner_id.website_description"/></textarea>
|
||||
</div>
|
||||
<div class="col-sm-offset-4 col-md-4 mb16">
|
||||
<button class="btn btn-primary btn-lg">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="user_detail_full">
|
||||
<t t-call="website_forum.header">
|
||||
<h1 class="mt0 page-header">
|
||||
<span t-field="user.name"/>
|
||||
<small>profile</small>
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<span t-field="user.image"
|
||||
t-field-options='{"widget": "image", "class": "img img-responsive img-circle"}'/>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<table class="table table-condensed">
|
||||
<tr>
|
||||
<td rowspan="2" valign="top"><span class="text-muted">contributions</span></td>
|
||||
<td>member since</td>
|
||||
<td><span t-field="user.create_date" t-field-options='{"format": "short"}'/></td>
|
||||
</tr><tr>
|
||||
<td>last connection</td>
|
||||
<td><span t-field="user.login_date" t-field-options='{"format": "short"}'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" valign="top"><span class="text-muted">bio</span></td>
|
||||
<td>website</td>
|
||||
<td>
|
||||
<a t-att-href="user.website" t-if="user.website">
|
||||
<span t-field="user.website"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>location</td>
|
||||
<td>
|
||||
<span t-field="user.city"/>
|
||||
<span t-if="user.city and user.country_id">, </span>
|
||||
<span t-field="user.country_id"/>
|
||||
<t t-if="user.country_id"> <span t-field="user.country_id.image" t-field-options='{"widget": "image", "class": "country_flag"}'/></t>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" valign="top"><span class="text-muted">stats</span></td>
|
||||
<td>karma</td>
|
||||
<td><span t-field="user.karma"/></td>
|
||||
</tr><tr>
|
||||
<td>votes</td>
|
||||
<td>
|
||||
<span class="fa fa-thumbs-up"/>
|
||||
<span t-esc="up_votes"/>
|
||||
<span class="fa fa-thumbs-down"/>
|
||||
<span t-esc="down_votes"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="well well-sm">
|
||||
<span t-field="user.partner_id.website_description"/>
|
||||
<t t-if="uid == user.id">
|
||||
<a class="fa fa-arrow-right" t-attf-href="/forum/#{slug(forum)}/user/#{slug(user)}/edit"> Edit Your Bio</a>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active">
|
||||
<a href="#questions" data-toggle="tab"><t t-esc="len(questions)"/> Questions</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#answers" data-toggle="tab"><t t-esc="len(answers)"/> Answers</a>
|
||||
</li>
|
||||
<li t-if="uid == user.id">
|
||||
<a href="#favourite_question" data-toggle="tab"><t t-esc="len(favourite)"/> Favourite Questions</a>
|
||||
</li>
|
||||
<li t-if="uid == user.id">
|
||||
<a href="#followed_question" data-toggle="tab"><t t-esc="len(followed)"/> Followed Questions</a>
|
||||
</li>
|
||||
<li t-if="uid == user.id">
|
||||
<a href="#activity" data-toggle="tab">Activity</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#badges" data-toggle="tab">Badges</a>
|
||||
</li>
|
||||
<li t-if="uid == user.id">
|
||||
<a href="#votes" data-toggle="tab">Votes</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content mt16">
|
||||
<div class="tab-pane active" id="questions">
|
||||
<div class="mb16" t-foreach="questions" t-as="question">
|
||||
<t t-call="website_forum.display_post"/>
|
||||
</div>
|
||||
</div><div class="tab-pane" id="answers">
|
||||
<div t-foreach="answers" t-as="answer">
|
||||
<t t-call="website_forum.display_post_answer"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="karma">
|
||||
<h1>Karma</h1>
|
||||
</div>
|
||||
<div class="tab-pane" id="badges">
|
||||
<t t-call="website_forum.user_badges"/>
|
||||
</div>
|
||||
<div class="tab-pane" id="favourite_question">
|
||||
<div t-foreach="favourite" t-as="question">
|
||||
<t t-call="website_forum.display_post"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="followed_question">
|
||||
<div t-foreach="followed" t-as="question">
|
||||
<t t-call="website_forum.display_post"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="votes">
|
||||
<t t-call="website_forum.user_votes"/>
|
||||
</div>
|
||||
<div class="tab-pane" id="activity">
|
||||
<ul class="list-unstyled">
|
||||
<li t-foreach="activities" t-as="activity">
|
||||
<span t-field="activity.date" t-field-options='{"format": "short"}'/>
|
||||
<span t-esc="activity.subtype_id.name" class="label label-info"/>
|
||||
<t t-set="post" t-value="posts[activity.res_id]"/>
|
||||
<span t-if="post[1]">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/question/#{ slug(post[0]) }#answer-#{ str(post[1].id) }">
|
||||
<span t-esc="post[0].name"/>
|
||||
</a>
|
||||
</span>
|
||||
<span t-if="not post[1]">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/question/#{ slug(post[0]) }">
|
||||
<span t-esc="post[0].name"/>
|
||||
</a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="user_badges">
|
||||
<table class="table mt32 mb64">
|
||||
<tr t-foreach="user.badge_ids" t-as="badge">
|
||||
<td>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/badge/#{ slug(badge.badge_id) }" class="badge pull-left">
|
||||
<span t-if="badge.badge_id.level == 'gold'" class="fa fa-circle badge-gold"/>
|
||||
<span t-if="badge.badge_id.level == 'silver'" class="fa fa-circle badge-silver"/>
|
||||
<span t-if="badge.badge_id.level == 'bronze'" class="fa fa-circle badge-bronze"/>
|
||||
<span t-field="badge.badge_id.name"/>
|
||||
</a>
|
||||
</td><td>
|
||||
<b t-esc="badge.badge_id.stat_count_distinct"/>
|
||||
<i class="text-muted">awarded users</i>
|
||||
</td><td>
|
||||
<span t-field="badge.badge_id.description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="mb16" t-if="not user.badge_ids">
|
||||
<b>No badge yet!</b><br/>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/badge" class="fa fa-arrow-right"> Check available badges</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="user_votes">
|
||||
<div t-foreach="vote_post" t-as="vote">
|
||||
<t t-esc="vote.post_id.create_date"/>
|
||||
<span t-if="vote.vote == '1'" class="fa fa-thumbs-up text-success" style="margin-left:30px"/>
|
||||
<span t-if="vote.vote == '-1'" class="fa fa-thumbs-down text-warning" style="margin-left:30px"/>
|
||||
<t t-if="vote.post_id.parent_id">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/question/#{ vote.post_id.parent_id.id }/#answer-#{ vote.post_id.id }" t-esc="vote.post_id.parent_id.name" style="margin-left:10px"/>
|
||||
</t>
|
||||
<t t-if="not vote.post_id.parent_id">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/question/#{ vote.post_id.id }" style=" color:black;margin-left:10px" t-esc="vote.post_id.name"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="mb16" t-if="not vote_post">
|
||||
<b>No vote given by you yet!</b>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
Loading…
Reference in New Issue