diff --git a/addons/portal_gamification/security/ir.model.access.csv b/addons/portal_gamification/security/ir.model.access.csv index 1a75ab2c0ad..448e483d7cf 100644 --- a/addons/portal_gamification/security/ir.model.access.csv +++ b/addons/portal_gamification/security/ir.model.access.csv @@ -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 diff --git a/addons/website_forum/data/forum_data.xml b/addons/website_forum/data/forum_data.xml index 81ea39b700d..878b05ce9aa 100644 --- a/addons/website_forum/data/forum_data.xml +++ b/addons/website_forum/data/forum_data.xml @@ -2,7 +2,7 @@ - + Help @@ -32,32 +32,24 @@ New Answer - website.forum.post + forum.post New Answer Answer Edited - website.forum.post + forum.post Answer Edited Question Edited - website.forum.post + forum.post Question Edited - - @@ -68,31 +60,31 @@ - + duplicate question - + off-topic or not relevant - + too subjective and argumentative - + not a real question - + already answered and an answer was accepted - + not relevant or out dated - + contains offensive or malicious remarks - + spam or advertising - + too localized diff --git a/addons/website_forum/data/forum_demo.xml b/addons/website_forum/data/forum_demo.xml index 98c871e9bc5..57cf87d4f08 100644 --- a/addons/website_forum/data/forum_demo.xml +++ b/addons/website_forum/data/forum_demo.xml @@ -3,39 +3,32 @@ - + Contract - + Action - + Alert - + ecommerce - - - + How to configure alerts for employee contract expiration 5 - + CMS replacement for ERP and eCommerce 23 @@ -49,7 +42,7 @@ In simple words does OpenERP became CMS+ERP platform? - + 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. 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. @@ -62,7 +55,7 @@ In simple words does OpenERP became CMS+ERP platform? - + 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. @@ -72,12 +65,12 @@ In simple words does OpenERP became CMS+ERP platform? - + 1 - + 1 diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py index 3372bcd30c6..878e94db188 100644 --- a/addons/website_forum/models/forum.py +++ b/addons/website_forum/models/forum.py @@ -9,14 +9,14 @@ from openerp.tools.translate import _ class Forum(osv.Model): - _name = 'website.forum' + _name = 'forum.forum' _description = 'Forums' - _inherit = ['mail.thread', 'website.seo.metadata'] + _inherit = ['website.seo.metadata'] _columns = { 'name': fields.char('Name', required=True, translate=True), 'faq': fields.html('Guidelines'), - 'description': fields.text('Description'), + 'description': fields.html('Description'), } def _get_default_faq(self, cr, uid, context=None): @@ -38,24 +38,50 @@ class Forum(osv.Model): class Post(osv.Model): - _name = 'website.forum.post' - _description = "Question" + _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): - if post.vote_ids: - for vote in post.vote_ids: - res[post.id] += int(vote.vote) + for vote in post.vote_ids: + res[post.id] += int(vote.vote) return res - def _get_vote(self, cr, uid, ids, context=None): + def _get_post_from_vote(self, cr, uid, ids, context=None): result = {} - for vote in self.pool['website.forum.post.vote'].browse(cr, uid, ids, context=context): + 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.user_id.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.favorite_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): @@ -65,71 +91,62 @@ class Post(osv.Model): res[post.id] = len(post.child_ids) return res - def _get_user_vote(self, cr, uid, ids, field_name, arg, context): - res = dict.fromkeys(ids, 0) - vote_ids = self.pool['website.forum.post.vote'].search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], context=context) - for vote in self.pool['website.forum.post.vote'].browse(cr, uid, vote_ids, context=context): - res[vote.post_id.id] = vote.vote - return res - - def _get_user_favourite(self, cr, uid, ids, field_name, arg, context): - res = dict.fromkeys(ids, False) - user = self.pool['res.users'].browse(cr, uid, uid, context=context) - for post in self.browse(cr, uid, ids, context=context): - if user in post.favourite_ids: - res[post.id] = True - return res - _columns = { 'name': fields.char('Title', size=128), - 'forum_id': fields.many2one('website.forum', 'Forum', required=True), - 'content': fields.text('Content'), - 'create_date': fields.datetime('Asked on', select=True, readonly=True), - 'user_id': fields.many2one('res.users', 'Asked by', select=True, readonly=True), - 'write_date': fields.datetime('Update on', select=True, readonly=True), - 'write_uid': fields.many2one('res.users', 'Update by', select=True, readonly=True), - 'tag_ids': fields.many2many('website.forum.tag', 'forum_tag_rel', 'forum_id', 'forum_tag_id', 'Tag'), - 'vote_ids': fields.one2many('website.forum.post.vote', 'post_id', 'Votes'), - 'user_vote': fields.function(_get_user_vote, string="My Vote", type='integer'), - 'favourite_ids': fields.many2many('res.users', 'forum_favourite_rel', 'forum_id', 'user_id', 'Favourite'), - 'user_favourite': fields.function(_get_user_favourite, string="My Favourite", type='boolean'), + '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'), - 'active': fields.boolean('Active'), 'views': fields.integer('Number of Views'), - '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': (lambda self, cr, uid, ids, c={}: ids, ['parent_id', 'child_ids'], 10), - } - ), + '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", + 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={ - 'website.forum.post': (lambda self, cr, uid, ids, c={}: ids, ['vote_ids'], 10), - 'website.forum.post.vote': (_get_vote, [], 10), - } - ), - 'is_correct': fields.boolean('Valid Answer', help='Correct Answer/ Answer on this question accepted.'), - 'closed_reason_id': fields.many2one('website.forum.post.reason', 'Reason'), - 'closed_by': fields.many2one('res.users', 'Closed by'), + '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', 'Favourite'), + 'user_favourite': fields.function(_get_user_favourite, string="My Favourite", type='boolean'), + 'favorite_count': fields.function( + _get_favorite_count, string='Favorite Count', type='integer', + store={ + 'forum.post': (lambda self, cr, uid, ids, c={}: ids, ['favorite_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), + }), + # 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 = { - 'user_id': lambda self, cr, uid, ctx=None: uid, + 'create_uid': lambda self, cr, uid, ctx=None: uid, 'state': 'active', 'views': 0, - 'vote_count': 0, 'active': True, } @@ -172,13 +189,13 @@ class Post(osv.Model): return res def vote(self, cr, uid, ids, upvote=True, context=None): - Vote = self.pool['website.forum.post.vote'] + Vote = self.pool['forum.post.vote'] user = self.pool['res.users'].browse(cr, uid, uid, context=context) # must have at least 10 karma to vote if not upvote and user.karma <= 10: return {'error': 'lessthen_10_karma'} # user can not vote on own post - posts = self.pool['website.forum.post'].browse(cr, uid, ids, context=context) + posts = self.browse(cr, uid, ids, context=context) if any(post.user_id.id == uid for post in posts): return {'error': 'own_post'} @@ -203,18 +220,18 @@ class Post(osv.Model): class PostReason(osv.Model): - _name = "website.forum.post.reason" - _description = "Post Reason" + _name = "forum.post.reason" + _description = "Post Closing Reason" _columns = { - 'name': fields.char('Post Reason'), + 'name': fields.char('Post Reason', required=True), } class Vote(osv.Model): - _name = 'website.forum.post.vote' + _name = 'forum.post.vote' _description = 'Vote' _columns = { - 'post_id': fields.many2one('website.forum.post', 'Post', ondelete='cascade', required=True), + '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), @@ -234,8 +251,6 @@ class Vote(osv.Model): 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) - # body = "voted %s %s" % ('answer' if record.parent_id else 'question','up' if vals.get('vote')==1 else 'down') - # Post.message_post(cr, uid, [record.id], body=_(body), context=context) return vote_id def write(self, cr, uid, ids, values, context=None): @@ -247,25 +262,26 @@ class Vote(osv.Model): class Tags(osv.Model): - _name = "website.forum.tag" + _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['website.forum.post'].search_count(cr, uid, [('tag_ids', 'in', tag_id)], context=context)) for tag_id in ids) + 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['website.forum.post'].browse(cr, SUPERUSER_ID, ids, context=context) for tag in post.tag_ids] + [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', size=64, required=True), - 'forum_id': fields.many2one('website.forum', 'Forum', required=True), + '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="# of Posts", + _get_posts_count, type='integer', string="Number of Posts", store={ - 'website.forum.post': (_get_tag_from_post, ['tag_ids'], 10), + 'forum.post': (_get_tag_from_post, ['tag_ids'], 10), } ), } diff --git a/addons/website_forum/security/ir.model.access.csv b/addons/website_forum/security/ir.model.access.csv index 0482778ad15..f7a0e666ad7 100644 --- a/addons/website_forum/security/ir.model.access.csv +++ b/addons/website_forum/security/ir.model.access.csv @@ -1,8 +1,19 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_website_forum,website.forum,model_website_forum,,1,0,0,0 -access_website_forum_post,website.forum.post,model_website_forum_post,,1,1,1,0 -access_website_forum_post_vote,website.forum.post.vote,model_website_forum_post_vote,,1,1,1,0 -access_website_forum_post_reason,website.forum.post.reason,model_website_forum_post_reason,,1,0,0,0 -access_website_forum_tag,website.forum.tag,model_website_forum_tag,,1,0,1,0 -access_gamification_badge_user,gamification.badge.user,gamification.model_gamification_badge_user,,1,0,0,0 -access_gamification_badge,gamification_badge,gamification.model_gamification_badge,,1,0,0,0 +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 diff --git a/addons/website_forum/static/src/css/website_forum.sass b/addons/website_forum/static/src/css/website_forum.sass index 19c0ef11217..555250bd6f3 100644 --- a/addons/website_forum/static/src/css/website_forum.sass +++ b/addons/website_forum/static/src/css/website_forum.sass @@ -50,9 +50,7 @@ a.no-decoration color: #428bca .oe_comment_grey - -moz-box-shadow: 0px 4px 6px 2px #eeeeee - -webkit-box-shadow: 0px 4px 6px 2px #eeeeee - box-shadow: 0px 4px 6px 2px #eeeeee + color: #f5f5f5 .forum_user_flag max-width: 25px diff --git a/addons/website_forum/views/forum.xml b/addons/website_forum/views/forum.xml index 00c7269e3f8..7c6048ec250 100644 --- a/addons/website_forum/views/forum.xml +++ b/addons/website_forum/views/forum.xml @@ -6,9 +6,9 @@ parent="mail.mail_feeds_main" sequence="50"/> - - website.forum.list - website.forum + + forum.forum.list + forum.forum @@ -16,9 +16,9 @@ - - website.forum.form - website.forum + + forum.forum.form + forum.forum
@@ -27,27 +27,23 @@ -
- - -
- + Forums - website.forum + forum.forum form tree,form - + - website.forum.post.list - website.forum.post + forum.post.list + forum.post @@ -56,9 +52,9 @@ - - website.forum.post.form - website.forum.post + + forum.post.form + forum.post
@@ -70,7 +66,7 @@ - + @@ -86,17 +82,17 @@ - - website.forum.post.search - website.forum.post + + forum.post.search + forum.post - + - + - + @@ -104,11 +100,11 @@ Forum Posts - website.forum.post + forum.post form tree,form - +