[mrg]:lp:~openerp-dev/openobject-addons/trunk-website-forum-tpa
bzr revid: sunilsharma.sharma07@gmail.com-20140312121725-52xm14zs5ryrimej
This commit is contained in:
commit
371333bd52
|
@ -23,7 +23,7 @@
|
|||
{
|
||||
'name': 'Forum',
|
||||
'category': 'Website',
|
||||
'summary': 'Ask Questions and give Answers',
|
||||
'summary': 'Forum, FAQ, Q&A',
|
||||
'version': '1.0',
|
||||
'description': """
|
||||
Ask questions, get answers, no distractions
|
||||
|
|
|
@ -54,10 +54,11 @@ class website_forum(http.Controller):
|
|||
return request.redirect("/forum/%s" % forum_id)
|
||||
|
||||
@http.route(['/forum/<model("website.forum"):forum>', '/forum/<model("website.forum"):forum>/page/<int:page>'], type='http', auth="public", website=True, multilang=True)
|
||||
def questions(self, forum, page=1, **searches):
|
||||
def questions(self, forum, page=1, filters='', sorting='', **searches):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Forum = request.registry['website.forum.post']
|
||||
domain = [('forum_id', '=', forum.id), ('parent_id', '=', False)]
|
||||
order = "id desc"
|
||||
|
||||
search = searches.get('search',False)
|
||||
if search:
|
||||
|
@ -65,20 +66,26 @@ class website_forum(http.Controller):
|
|||
('name', 'ilike', search),
|
||||
('content', 'ilike', search)]
|
||||
|
||||
type = searches.get('type',False)
|
||||
if not type:
|
||||
searches['type'] = 'all'
|
||||
if type == 'unanswered':
|
||||
if not filters:
|
||||
filters = 'all'
|
||||
if filters == 'unanswered':
|
||||
domain += [ ('child_ids', '=', False) ]
|
||||
#TODO: update domain to show followed questions of user
|
||||
if type == 'followed':
|
||||
if filters == 'followed':
|
||||
domain += [ ('create_uid', '=', uid) ]
|
||||
|
||||
if sorting == 'date':
|
||||
order = 'write_date desc'
|
||||
if sorting == 'answered':
|
||||
order = 'child_count desc'
|
||||
if sorting == 'vote':
|
||||
order = 'vote_count desc'
|
||||
|
||||
step = 10
|
||||
question_count = Forum.search(cr, uid, domain, count=True, context=context)
|
||||
pager = request.website.pager(url="/forum/%s/" % slug(forum), total=question_count, page=page, step=step, scope=10)
|
||||
|
||||
obj_ids = Forum.search(cr, uid, domain, limit=step, offset=pager['offset'], context=context)
|
||||
obj_ids = Forum.search(cr, uid, domain, limit=step, offset=pager['offset'], order=order, context=context)
|
||||
question_ids = Forum.browse(cr, uid, obj_ids, context=context)
|
||||
|
||||
values = {
|
||||
|
@ -86,6 +93,8 @@ class website_forum(http.Controller):
|
|||
'question_ids': question_ids,
|
||||
'forum': forum,
|
||||
'pager': pager,
|
||||
'filters': filters,
|
||||
'sorting': sorting,
|
||||
'searches': searches,
|
||||
}
|
||||
|
||||
|
@ -107,10 +116,11 @@ class website_forum(http.Controller):
|
|||
for answer in question.child_ids:
|
||||
if answer.create_uid.id == request.uid:
|
||||
answer_done = True
|
||||
post['type'] = 'question'
|
||||
filters = 'question'
|
||||
values = {
|
||||
'question': question,
|
||||
'searches': post,
|
||||
'filters': filters,
|
||||
'answer_done': answer_done,
|
||||
'reversed': reversed,
|
||||
'forum': forum,
|
||||
|
@ -243,10 +253,9 @@ class website_forum(http.Controller):
|
|||
def tag_questions(self, forum, tag, page=1, **kwargs):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Post = request.registry['website.forum.post']
|
||||
post_ids = [que.id for que in tag.post_ids]
|
||||
obj_ids = Post.search(cr, uid, [('forum_id', '=', forum.id), ('id', 'in', post_ids)], context=context)
|
||||
obj_ids = Post.search(cr, uid, [('forum_id', '=', forum.id), ('tags', '=', tag.id)], context=context)
|
||||
question_ids = Post.browse(cr, uid, obj_ids, context=context)
|
||||
pager = request.website.pager(url="/forum/%s/tag" % slug(forum), total=len(tag.post_ids), page=page, step=10, scope=10)
|
||||
pager = request.website.pager(url="/forum/%s/tag" % slug(forum), total=len(obj_ids), page=page, step=10, scope=10)
|
||||
kwargs['tags'] = 'True'
|
||||
|
||||
values = {
|
||||
|
@ -257,7 +266,7 @@ class website_forum(http.Controller):
|
|||
}
|
||||
return request.website.render("website_forum.index", values)
|
||||
|
||||
@http.route(['/forum/<model("website.forum"):forum>/tags'], type='http', auth="public", website=True, multilang=True)
|
||||
@http.route(['/forum/<model("website.forum"):forum>/tag'], type='http', auth="public", website=True, multilang=True)
|
||||
def tags(self, forum, page=1, **searches):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Tag = request.registry['website.forum.tag']
|
||||
|
@ -270,11 +279,11 @@ class website_forum(http.Controller):
|
|||
}
|
||||
return request.website.render("website_forum.tag", values)
|
||||
|
||||
@http.route(['/forum/<model("website.forum"):forum>/badges'], type='http', auth="public", website=True, multilang=True)
|
||||
@http.route(['/forum/<model("website.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, uid, [('forum', '=', True)], context=context)
|
||||
badge_ids = Badge.search(cr, uid, [('level', '!=', False)], context=context)
|
||||
badges = Badge.browse(cr, uid, badge_ids, context=context)
|
||||
values = {
|
||||
'badges': badges,
|
||||
|
@ -322,20 +331,7 @@ class website_forum(http.Controller):
|
|||
def post_vote(self, **post):
|
||||
cr, uid, context, post_id = request.cr, request.uid, request.context, int(post.get('post_id'))
|
||||
Vote = request.registry['website.forum.post.vote']
|
||||
Post = request.registry['website.forum.post']
|
||||
vote_ids = Vote.search(cr, uid, [('post_id', '=', post_id)], context=context)
|
||||
|
||||
if vote_ids:
|
||||
Vote.unlink(cr, uid, vote_ids, context=context)
|
||||
else:
|
||||
Vote.create(cr, uid, {
|
||||
'post_id': post_id,
|
||||
'user_id': uid,
|
||||
'vote': post.get('vote'),
|
||||
}, context=context)
|
||||
record = Post.browse(cr, uid, post_id, context=context)
|
||||
|
||||
return record.vote_count
|
||||
return Vote.vote(cr, uid, post_id, post.get('vote'), context)
|
||||
|
||||
@http.route('/forum/post_delete/', type='json', auth="user", multilang=True, methods=['POST'], website=True)
|
||||
def delete_answer(self, **kwarg):
|
||||
|
|
|
@ -6,230 +6,191 @@
|
|||
<!--TODO: Have to add condition when badge will be given-->
|
||||
<record id="badge_1" model="gamification.badge">
|
||||
<field name="name">Autobiographer</field>
|
||||
<field name="description">Completed all user profile fields</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_2" model="gamification.badge">
|
||||
<field name="name">Citizen Patrol</field>
|
||||
<field name="description">First flagged post</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
<field name="description">Completed own biography</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_3" model="gamification.badge">
|
||||
<field name="name">Cleanup</field>
|
||||
<field name="description">First rollback</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_4" model="gamification.badge">
|
||||
<field name="name">Commentator</field>
|
||||
<field name="description">Posted 10 comments</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="badge_5" model="gamification.badge">
|
||||
<field name="name">Critic</field>
|
||||
<field name="description">First downvote</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<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="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="badge_7" model="gamification.badge">
|
||||
<field name="name">Editor</field>
|
||||
<field name="description">First edit</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_8" model="gamification.badge">
|
||||
<field name="name">Enlightened</field>
|
||||
<field name="description">First answer was accepted with 3 or more votes</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="badge_9" model="gamification.badge">
|
||||
<field name="name">Enthusiast</field>
|
||||
<field name="description">Visited site every day for 30 days in a row</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="description">Voted on questions/answers for 15 days in a row</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="badge_10" model="gamification.badge">
|
||||
<field name="name">Expert</field>
|
||||
<field name="description">Very active in one tag</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="description">Posted more than 10 questions or answers in one tag</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_11" model="gamification.badge">
|
||||
<field name="name">Famous Question</field>
|
||||
<field name="description">Asked a question with 500 views</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_12" model="gamification.badge">
|
||||
<field name="name">Favorite Question</field>
|
||||
<field name="description">Question favorited by 5 users</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_13" model="gamification.badge">
|
||||
<field name="name">Good Answer</field>
|
||||
<field name="description">Answer voted up 6 times</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_14" model="gamification.badge">
|
||||
<field name="name">Good Question</field>
|
||||
<field name="description">Question voted up 6 times</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_15" model="gamification.badge">
|
||||
<field name="name">Great Answer</field>
|
||||
<field name="description">Answer voted up 15 times</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_16" model="gamification.badge">
|
||||
<field name="name">Great Question</field>
|
||||
<field name="description">Question voted up 15 times</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_17" model="gamification.badge">
|
||||
<field name="name">Guru</field>
|
||||
<field name="description">Answer accepted with 15 or more votes</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_18" 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="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
<record id="badge_19" model="gamification.badge">
|
||||
<field name="name">Nice Answer</field>
|
||||
<field name="description">Answer voted up 4 times</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_20" model="gamification.badge">
|
||||
<field name="name">Nice Quesiotn</field>
|
||||
<field name="description">Question voted up 4 times</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_21" model="gamification.badge">
|
||||
<field name="name">Notable Question</field>
|
||||
<field name="description">Asked a question with 250 views</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_22" model="gamification.badge">
|
||||
<field name="name">Organizer</field>
|
||||
<field name="description">First retag</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">bronze</field>
|
||||
</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="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_24" model="gamification.badge">
|
||||
<field name="name">Popular Question</field>
|
||||
<field name="description">Asked a question with 150 views</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<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="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<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="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_27" model="gamification.badge">
|
||||
<field name="name">self-Learner</field>
|
||||
<field name="description">Answered own question with at least 4 up votes</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_28" model="gamification.badge">
|
||||
<field name="name">Stellar Question</field>
|
||||
<field name="description">Question favorited by 25 users</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">bronze</field>
|
||||
</record>
|
||||
<record id="badge_29" model="gamification.badge">
|
||||
<field name="name">Associate Editor</field>
|
||||
<field name="description">Edited 30 entries</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_30" model="gamification.badge">
|
||||
<field name="name">Student</field>
|
||||
<field name="description">Asked first question with at least one up vote</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_31" model="gamification.badge">
|
||||
<field name="name">Supporter</field>
|
||||
<field name="description">First upvote</field>
|
||||
<field name="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</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="forum">True</field>
|
||||
<field name="level">silver</field>
|
||||
</record>
|
||||
|
||||
<record id="badge_33" 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="forum">True</field>
|
||||
<field name="level">gold</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -62,7 +62,6 @@ class Post(osv.Model):
|
|||
_name = 'website.forum.post'
|
||||
_description = "Question"
|
||||
_inherit = ['mail.thread', 'website.seo.metadata']
|
||||
_order = "id desc"
|
||||
|
||||
def _get_votes(self, cr, uid, ids, field_name, arg, context):
|
||||
res = dict.fromkeys(ids, False)
|
||||
|
@ -94,6 +93,16 @@ class Post(osv.Model):
|
|||
result[vote.post_id.id] = True
|
||||
return result.keys()
|
||||
|
||||
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)
|
||||
return res
|
||||
|
||||
def _get_child(self, cr, uid, ids, context=None):
|
||||
return ids
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Title', size=128),
|
||||
'forum_id': fields.many2one('website.forum', 'Forum', required=True),
|
||||
|
@ -114,6 +123,11 @@ class Post(osv.Model):
|
|||
|
||||
'parent_id': fields.many2one('website.forum.post', 'Question', ondelete='cascade'),
|
||||
'child_ids': fields.one2many('website.forum.post', 'parent_id', 'Answers'),
|
||||
'child_count':fields.function(_get_child_count, string="Answers", type='integer',
|
||||
store={
|
||||
'website.forum.post': (_get_child, [], 10),
|
||||
}
|
||||
),
|
||||
|
||||
'history_ids': fields.one2many('blog.post.history', 'post_id', 'History', help='Last post modifications'),
|
||||
# TODO FIXME: when website_mail/mail_thread.py inheritance work -> this field won't be necessary
|
||||
|
@ -144,26 +158,20 @@ class Post(osv.Model):
|
|||
_defaults = {
|
||||
'state': 'active',
|
||||
'vote_count': 0,
|
||||
'active': True
|
||||
'active': True,
|
||||
}
|
||||
|
||||
def create_history(self, cr, uid, ids, vals, context=None):
|
||||
History = self.pool['website.forum.post.history']
|
||||
for post in ids:
|
||||
if vals.get('content'):
|
||||
create_date = vals.get('create_date')
|
||||
res = {
|
||||
'name': 'Update %s - %s' % (create_date, vals.get('name')),
|
||||
'content': vals.get('content', ''),
|
||||
'post_id': post
|
||||
}
|
||||
if vals.get('version'):
|
||||
res.update({'version':vals.get('version')})
|
||||
|
||||
if vals.get('tags'):
|
||||
res.update({'tags':vals.get('tags')})
|
||||
|
||||
History.create(cr, uid, res, context=context)
|
||||
hist_obj = self.pool['website.forum.post.history']
|
||||
for post in self.browse(cr, uid, ids, context=context):
|
||||
hist_obj.create(cr, uid, {
|
||||
'post_id': post.id,
|
||||
'content': post.content,
|
||||
'name': post.name,
|
||||
'tags': [(6,0, [x.id for x in post.tags])],
|
||||
'date': post.write_date or post.create_date,
|
||||
'user_id': post.write_uid and post.write_uid.id or post.create_uid.id
|
||||
}, context=context)
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
|
@ -206,7 +214,7 @@ class Users(osv.Model):
|
|||
|
||||
_columns = {
|
||||
'create_date': fields.datetime('Create Date', select=True, readonly=True),
|
||||
'karma': fields.integer('Karma'), # Use Gamification for this
|
||||
'karma': fields.integer('Karma'), # Use a function field for this
|
||||
'forum': fields.boolean('Is Forum Member'),
|
||||
|
||||
'badges': fields.one2many('gamification.badge.user', 'user_id', 'Badges'),
|
||||
|
@ -224,11 +232,10 @@ class PostHistory(osv.Model):
|
|||
_description = 'Post History'
|
||||
_inherit = ['website.seo.metadata']
|
||||
_columns = {
|
||||
'name': fields.char('Update Notes', size=64, required=True),
|
||||
'name': fields.char('Post Title'),
|
||||
'post_id': fields.many2one('website.forum.post', 'Post', ondelete='cascade'),
|
||||
'create_date': fields.datetime('Created on', select=True, readonly=True),
|
||||
'create_uid': fields.many2one('res.users', 'Created by', select=True, readonly=True),
|
||||
'version': fields.integer('Version'),
|
||||
'date': fields.datetime('Created on', select=True, readonly=True),
|
||||
'user_id': fields.many2one('res.users', 'Created by', select=True, readonly=True),
|
||||
'content': fields.html('Contents', help='Automatically sanitized HTML contents'),
|
||||
'tags': fields.many2many('website.forum.tag', 'forum_tag_rel', 'forum_id', 'forum_tag_id', 'Tag'),
|
||||
}
|
||||
|
@ -239,9 +246,15 @@ class Vote(osv.Model):
|
|||
_columns = {
|
||||
'post_id': fields.many2one('website.forum.post', 'Post', required=True),
|
||||
'user_id': fields.many2one('res.users', 'User'),
|
||||
'vote': fields.selection([('1', '1'),('-1', '-1')], 'rate'),
|
||||
'vote': fields.selection([('1', '1'),('-1', '-1'),('0','0')], 'Vote'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'user_id': lambda self, cr, uid, ctx: uid,
|
||||
'vote': lambda *args: 1
|
||||
}
|
||||
# TODO: improve this: translate strings _()
|
||||
# no need to have different text for question/answer
|
||||
# need different text for upvote, downvote
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
vote_id = super(Vote, self).create(cr, uid, vals, context=context)
|
||||
Post = self.pool["website.forum.post"]
|
||||
|
@ -252,33 +265,40 @@ class Vote(osv.Model):
|
|||
Post.message_post(cr, uid, [record.id], body=body, context=context)
|
||||
return vote_id
|
||||
|
||||
def vote(self, cr, uid, post_id, vote, context=None):
|
||||
assert int(vote) in (1, -1, 0), "vote can be -1 or 1, nothing else"
|
||||
post_obj = self.pool.get('website.forum.post')
|
||||
vote_ids = self.search(cr, uid, [('post_id', '=', post_id), ('user_id','=',uid)], context=context)
|
||||
if vote_ids:
|
||||
self.write(cr, uid, vote_uid, {
|
||||
'vote': vote
|
||||
}, context=context)
|
||||
else:
|
||||
self.create(cr, uid, {
|
||||
'post_id': post_id,
|
||||
'vote': vote,
|
||||
}, context=context)
|
||||
return post_obj.browse(cr, uid, post_id, context=context).vote_count
|
||||
|
||||
class Badge(osv.Model):
|
||||
_inherit = 'gamification.badge'
|
||||
_columns = {
|
||||
'forum': fields.boolean('Is a Forum Badge'),
|
||||
'level': fields.selection([('bronze', 'bronze'), ('silver', 'silver'), ('gold', 'gold')], 'Badge Level'),
|
||||
}
|
||||
_defaults = {
|
||||
'forum': False,
|
||||
'level': 'bronze'
|
||||
'level': fields.selection([('bronze', 'bronze'), ('silver', 'silver'), ('gold', 'gold')], 'Forum Badge Level'),
|
||||
}
|
||||
|
||||
class Tags(osv.Model):
|
||||
_name = "website.forum.tag"
|
||||
_description = "Tag"
|
||||
_inherit = ['website.seo.metadata']
|
||||
|
||||
def _get_questions(self, cr, uid, ids, field_name, arg, context=None):
|
||||
def _get_posts_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
result = {}
|
||||
Post = self.pool['website.forum.post']
|
||||
for tag in ids:
|
||||
question_ids = Post.search(cr, uid , [('tags.id', '=', tag)], context=context)
|
||||
result[tag] = question_ids
|
||||
result[tag] = Post.search_count(cr, uid , [('tags', '=', tag)], context=context)
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64, required=True),
|
||||
'forum_id': fields.many2one('website.forum', 'Forum', required=True),
|
||||
'post_ids': fields.function(_get_questions, type='many2many', relation="website.forum.post", string="Questions",
|
||||
),
|
||||
'posts_count': fields.function(_get_posts_count, type='integer', string="# of Posts"),
|
||||
}
|
||||
|
|
|
@ -19,6 +19,3 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
#import test_ui
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2013-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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import openerp.tests
|
||||
|
||||
class TestUi(openerp.tests.HttpCase):
|
||||
def test_admin(self):
|
||||
self.phantom_js("/", "openerp.website.Tour.run_test('question')", "openerp.website.Tour")
|
||||
|
|
@ -35,10 +35,10 @@
|
|||
<template id="post_list">
|
||||
<div class="question clearfix">
|
||||
<div class="pull-left text-center">
|
||||
<div t-attf-class="box #{len(question.child_ids) and 'oe_green' or 'oe_grey'}">
|
||||
<span t-esc="len(question.child_ids)"/>
|
||||
<div t-if="len(question.child_ids)>1">Answers</div>
|
||||
<div t-if="len(question.child_ids)<=1">Answer</div>
|
||||
<div t-attf-class="box #{question.child_count and 'oe_green' or 'oe_grey'}">
|
||||
<span t-esc="question.child_count"/>
|
||||
<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
|
||||
|
@ -51,8 +51,8 @@
|
|||
<div class="text-muted">
|
||||
by <a t-attf-href="/forum/#{ slug(forum) }/user/#{ question.create_uid.id }" t-field="question.create_uid"/>,
|
||||
on <span t-field="question.write_date"/>
|
||||
<div t-if="len(question.vote_ids)">
|
||||
<strong>with <span t-esc="len(question.vote_ids)"/> votes</strong>
|
||||
<div t-if="question.vote_count">
|
||||
<strong>with <span t-esc="question.vote_count"/> votes</strong>
|
||||
</div>
|
||||
</div>
|
||||
<t t-foreach="question.tags" t-as="tag">
|
||||
|
@ -83,17 +83,17 @@
|
|||
</div>
|
||||
<div class="collapse navbar-collapse" id="oe-help-navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li t-att-class="searches.get('type') in ('all', 'unanswered','followed','question') and 'active' or '' ">
|
||||
<li t-att-class="filters in ('all', 'unanswered','followed','question') 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) }/tags">Tags</a>
|
||||
<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) }/badges">Badges</a>
|
||||
<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">
|
||||
|
@ -154,33 +154,36 @@
|
|||
<h1 class="page-header mt0">
|
||||
<t t-esc="total_questions"/>
|
||||
<span>Questions</span>
|
||||
<small class="dropdown" t-if="searches.get('type') in ('all', 'unanswered','followed')">
|
||||
<small class="dropdown" t-if="filters in ('all', 'unanswered','followed')">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<t t-if="searches.get('type') == 'all'">No filter</t>
|
||||
<t t-if="searches.get('type') == 'unanswered'">Filter: Unanswered</t>
|
||||
<t t-if="searches.get('type') == 'followed'">Filter: Followed</t>
|
||||
<t t-if="filters == 'all'">No filter</t>
|
||||
<t t-if="filters == 'unanswered'">filter: Unanswered</t>
|
||||
<t t-if="filters == 'followed'">filter: Followed</t>
|
||||
<t t-if="sorting == 'date'"> Sort by: Last activity date</t>
|
||||
<t t-if="sorting == 'answered'"> Sort by: Most answered</t>
|
||||
<t t-if="sorting == 'vote'"> Sort by: Most votes</t>
|
||||
<b class="caret"/>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="dropdown-header">Filter on</li>
|
||||
<li t-att-class="searches.get('type') == 'all' and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/?{{ keep_query( type='all') }}">All</a>
|
||||
<li t-att-class="filters == 'all' and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }?{{ keep_query( 'sorting', filters='all') }}">All</a>
|
||||
</li>
|
||||
<li t-att-class="searches.get('type') == 'unanswered' and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/?{{ keep_query( type='unanswered') }}">Unanswered</a>
|
||||
<li t-att-class="filters == 'unanswered' and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }?{{ keep_query( 'sorting', filters='unanswered') }}">Unanswered</a>
|
||||
</li>
|
||||
<li t-att-class="searches.get('type') == 'followed' and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/?{{ keep_query( type='followed') }}">Followed</a>
|
||||
<li t-att-class="filters == 'followed' and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }?{{ keep_query( 'sorting', filters='followed') }}">Followed</a>
|
||||
</li>
|
||||
<li class="dropdown-header">Sort by</li>
|
||||
<li>
|
||||
<a href="#" class="active">Last activity date</a> <!-- default order to implement -->
|
||||
<li t-att-class="sorting == 'date' and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }?{{ keep_query( 'filters', sorting='date') }}">Last activity date</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">Most answered</a>
|
||||
<li t-att-class="sorting == 'answered' and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }?{{ keep_query( 'filters', sorting='answered') }}">Most answered</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">Most voted</a>
|
||||
<li t-att-class="sorting == 'vote' and 'active' or '' ">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }?{{ keep_query( 'filters', sorting='vote') }}">Most voted</a>
|
||||
</li>
|
||||
</ul>
|
||||
</small>
|
||||
|
@ -318,9 +321,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<span t-esc="len(question.child_ids)"/>
|
||||
<span t-if="len(question.child_ids)>1">Answers</span>
|
||||
<span t-if="len(question.child_ids)<=1">Answer</span>
|
||||
<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>
|
||||
<div style="margin-left: 95px;">
|
||||
|
@ -371,8 +374,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="text-muted" id="correct">
|
||||
<a t-attf-id="#{answer.id}" t-if="answer.correct" class="fa fa-2x fa-check oe_answer_true"/>
|
||||
<a t-attf-id="#{answer.id}" t-if="not answer.correct" class="fa fa-2x fa-check oe_answer_false"/>
|
||||
<a href="" t-attf-id="#{answer.id}" t-if="answer.correct" class="fa fa-2x fa-check oe_answer_true"/>
|
||||
<a href="" t-attf-id="#{answer.id}" t-if="not answer.correct" class="fa fa-2x fa-check oe_answer_false"/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-left: 95px;" class="clearfix">
|
||||
|
@ -446,7 +449,7 @@
|
|||
<span t-field="tag.name" />
|
||||
</a>
|
||||
<span>
|
||||
X <t t-esc="len(tag.post_ids)"/>
|
||||
X <t t-esc="tag.posts_count"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -473,7 +476,7 @@
|
|||
<span t-field="badge.name" />
|
||||
</a>
|
||||
</td><td>
|
||||
<b t-esc="len(badge.owner_ids)"/>
|
||||
<b t-esc="badge.stat_count_distinct"/>
|
||||
<i class="text-muted">awarded users</i>
|
||||
</td><td>
|
||||
<span t-field="badge.description"/>
|
||||
|
@ -498,9 +501,9 @@
|
|||
<span t-field="badge.description" style="margin-left:20px"/>
|
||||
</div>
|
||||
<h4 class="mt32">
|
||||
<t class="pull-left" t-esc="len(badge.owner_ids)"/>
|
||||
<span t-if="len(badge.owner_ids)>1">users</span>
|
||||
<span t-if="len(badge.owner_ids)<=1">user</span>
|
||||
<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">
|
||||
|
@ -649,13 +652,13 @@
|
|||
<span t-field="badge.badge_id.name" />
|
||||
</a>
|
||||
<span>
|
||||
X <t t-esc="len(badge.badge_id.owner_ids)"/>
|
||||
X <t t-esc="badge.badge_id.stat_count_distinct"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb16" t-if="not user.badges">
|
||||
<b>No badge yet!</b><br/>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/badges" class="fa fa-arrow-right"> Check available badges</a>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/badge" class="fa fa-arrow-right"> Check available badges</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
Loading…
Reference in New Issue