diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py index 828bcbbfa98..5daa2ddfb7c 100644 --- a/addons/website_forum/controllers/main.py +++ b/addons/website_forum/controllers/main.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - from datetime import datetime import werkzeug.exceptions import werkzeug.urls @@ -8,15 +7,12 @@ import simplejson import lxml from urllib2 import urlopen, URLError -from openerp import tools +from openerp import tools, _ 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 -controllers = controllers() - class WebsiteForum(http.Controller): _post_per_page = 10 @@ -37,7 +33,7 @@ class WebsiteForum(http.Controller): 'notifications': self._get_notifications(), 'header': kwargs.get('header', dict()), 'searches': kwargs.get('searches', dict()), - 'no_introduction_message': request.httprequest.cookies.get('no_introduction_message', False), + 'forum_welcome_message': request.httprequest.cookies.get('forum_welcome_message', False), 'validation_email_sent': request.session.get('validation_email_sent', False), 'validation_email_done': request.session.get('validation_email_done', False), } @@ -86,8 +82,15 @@ class WebsiteForum(http.Controller): return request.website.render("website_forum.forum_all", {'forums': forums}) @http.route('/forum/new', type='http', auth="user", methods=['POST'], website=True) - def forum_create(self, forum_name="New Forum", **kwargs): + def forum_create(self, forum_name="New Forum", add_menu=False): forum_id = request.env['forum.forum'].create({'name': forum_name}) + if add_menu: + request.env['website.menu'].create({ + 'name': forum_name, + 'url': "/forum/%s" % slug(forum_id), + 'parent_id': request.website.menu_id.id, + 'website_id': request.website.id, + }) return request.redirect("/forum/%s" % slug(forum_id)) @http.route('/forum/notification_read', type='json', auth="user", methods=['POST'], website=True) @@ -166,16 +169,37 @@ class WebsiteForum(http.Controller): ) return simplejson.dumps(data) - @http.route(['/forum//tag'], type='http', auth="public", website=True) - def tags(self, forum, page=1, **post): - tags = request.env['forum.tag'].search([('forum_id', '=', forum.id), ('posts_count', '>', 0)], limit=None, order='posts_count DESC') + @http.route(['/forum//tag', '/forum//tag/'], type='http', auth="public", website=True) + def tags(self, forum, tag_char=None, **post): + # build the list of tag first char, with their value as tag_char param Ex : [('All', 'all'), ('C', 'c'), ('G', 'g'), ('Z', z)] + first_char_tag = forum.get_tags_first_char() + first_char_list = [(t, t.lower()) for t in first_char_tag] + first_char_list.insert(0, (_('All'), 'all')) + # get active first char tag + active_char_tag = first_char_list[1][1] if len(first_char_list) > 1 else 'all' + if tag_char: + active_char_tag = tag_char.lower() + # generate domain for searched tags + domain = [('forum_id', '=', forum.id), ('posts_count', '>', 0)] + order_by = 'name' + if active_char_tag and active_char_tag != 'all': + domain.append(('name', '=ilike', active_char_tag+'%')) + order_by = 'posts_count DESC' + tags = request.env['forum.tag'].search(domain, limit=None, order=order_by) + # prepare values and render template values = self._prepare_forum_values(forum=forum, searches={'tags': True}, **post) values.update({ 'tags': tags, - 'main_object': forum, + 'pager_tag_chars': first_char_list, + 'active_char_tag': active_char_tag, }) return request.website.render("website_forum.tag", values) + + @http.route('/forum//edit_welcome_message', auth="user", website=True) + def edit_welcome_message(self, forum, **kw): + return request.website.render("website_forum.edit_welcome_message", {'forum': forum}) + # Questions # -------------------------------------------------- @@ -339,17 +363,21 @@ class WebsiteForum(http.Controller): 'tags': tags, 'post': post, 'is_answer': bool(post.parent_id), - 'searches': kwargs + 'searches': kwargs, + 'post_name': post.content_link, + 'content': post.name, }) - return request.website.render("website_forum.edit_post", values) + template = "website_forum.new_link" if post.post_type == 'link' and not post.parent_id else "website_forum.edit_post" + return request.website.render(template, values) @http.route('/forum//post//save', type='http', auth="user", methods=['POST'], website=True) def post_save(self, forum, post, **kwargs): - post_tags = forum._tag_to_write_vals(kwargs.get('post_tag', '')) + post_tags = forum._tag_to_write_vals(kwargs.get('post_tags', '')) vals = { 'tag_ids': post_tags, 'name': kwargs.get('post_name'), 'content': kwargs.get('content'), + 'content_link': kwargs.get('content_link'), } post.write(vals) question = post.parent_id if post.parent_id else post diff --git a/addons/website_forum/data/forum_default_faq.html b/addons/website_forum/data/forum_default_faq.html index 9891c930a21..f2169cd2616 100644 --- a/addons/website_forum/data/forum_default_faq.html +++ b/addons/website_forum/data/forum_default_faq.html @@ -86,52 +86,10 @@ 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 + for a question or answer per day. The table given at the end explains reputation point requirements for each type of moderation task.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1upvote, add comments
10downvote
30insert text link, upload files
50insert clickable link, answer own question immediately
75retag, edit wiki questions and answers
100flag offensive, close own questions
200answer/comment by email
300edit any post, view offensive flags
500accept any answer (after 1 week)
750delete any comment
900lock posts
1000delete any question or answer
-

Why can other people edit my questions/answers?

The goal of this site is create a relevant knowledge base that would answer diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py index db57629611c..10fc95d3c3b 100644 --- a/addons/website_forum/models/forum.py +++ b/addons/website_forum/models/forum.py @@ -46,12 +46,25 @@ class Forum(models.Model): # description and use name = fields.Char('Forum Name', required=True, translate=True) faq = fields.Html('Guidelines', default=_get_default_faq, translate=True) - description = fields.Html( + description = fields.Text( 'Description', translate=True, - default='

This community is for professionals and enthusiasts of our products and services.' + default='This community is for professionals and enthusiasts of our products and services.' 'Share and discuss the best content and new marketing ideas,' - 'build your professional profile and become a better marketer together.

') + 'build your professional profile and become a better marketer together.') + welcome_message = fields.Html( + 'Welcome Message', + default = """
+
+
+

Welcome!

+

This community is for professionals and enthusiasts of our products and services. Share and discuss the best content and new marketing ideas, build your professional profile and become a better marketer together.

+
+
+      Hide Intro    Register 
+
+
+
""") default_order = fields.Selection([ ('create_date desc', 'Newest'), ('write_date desc', 'Last Updated'), @@ -59,7 +72,7 @@ class Forum(models.Model): ('relevancy desc', 'Relevancy'), ('child_count desc', 'Answered')], string='Default Order', required=True, default='write_date desc') - relevancy_post_vote = fields.Float('First Relevancy Parameter', default=0.8) + relevancy_post_vote = fields.Float('First Relevancy Parameter', default=0.8, help="This formula is used in order to sort by relevancy. The variable 'votes' represents number of votes for a post, and 'days' is number of days since the post creation") relevancy_time_decay = fields.Float('Second Relevancy Parameter', default=1.8) default_post_type = fields.Selection([ ('question', 'Question'), @@ -119,6 +132,13 @@ class Forum(models.Model): or (self.default_post_type == 'link' and not self.allow_link): raise UserError(_('You cannot choose %s as default post since the forum does not allow it.' % self.default_post_type)) + @api.one + @api.constrains('allow_link', 'allow_question', 'allow_discussion', 'default_post_type') + def _check_default_post_type(self): + if self.default_post_type == 'link' and not self.allow_link or self.default_post_type == 'question' and not self.allow_question or self.default_post_type == 'discussion' and not self.allow_discussion: + raise Warning(_('Post type in "Default post" must be activated')) + + @api.model def create(self, values): return super(Forum, self.with_context(mail_create_nolog=True)).create(values) @@ -145,8 +165,14 @@ class Forum(models.Model): post_tags.insert(0, [6, 0, existing_keep]) return post_tags + def get_tags_first_char(self): + """ get set of first letter of forum tags """ + tags = self.env['forum.tag'].search([('forum_id', '=', self.id), ('posts_count', '>', 0)]) + return sorted(set([tag.name[0].upper() for tag in tags])) + class Post(models.Model): + _name = 'forum.post' _description = 'Forum Post' _inherit = ['mail.thread', 'website.seo.metadata'] @@ -210,7 +236,7 @@ class Post(models.Model): vote.user_vote = mapped_vote.get(vote.id, 0) @api.multi - @api.depends('vote_ids') + @api.depends('vote_ids.vote') def _get_vote_count(self): read_group_res = self.env['forum.post.vote'].read_group([('post_id', 'in', self._ids)], ['post_id', 'vote'], ['post_id', 'vote'], lazy=False) result = dict.fromkeys(self._ids, 0) diff --git a/addons/website_forum/static/src/css/website_forum.css b/addons/website_forum/static/src/css/website_forum.css index 79fd7dd330c..395167cf615 100644 --- a/addons/website_forum/static/src/css/website_forum.css +++ b/addons/website_forum/static/src/css/website_forum.css @@ -50,9 +50,17 @@ img.img-avatar { .oe_answer_true { color: #3c763d; } +.forum_answer .oe_answer_true:hover { + color: #4D964E; +} + .oe_answer_false { color: #bbbbbb; } +.oe_answer_false:hover { + color: #9E9C9C; +} + .favourite_question { color: #bbbbbb !important; } @@ -100,4 +108,6 @@ a.no-decoration { z-index: 5; } button.btn-link.text-muted { - color: #999999; } + color: #999999; +} + diff --git a/addons/website_forum/static/src/css/website_forum.sass b/addons/website_forum/static/src/css/website_forum.sass index 8ade74975ea..1313516a084 100644 --- a/addons/website_forum/static/src/css/website_forum.sass +++ b/addons/website_forum/static/src/css/website_forum.sass @@ -51,9 +51,15 @@ img.img-avatar .oe_answer_true color: #3c763d + &:hover { + color: #4D964E; + } .oe_answer_false color: #bbbbbb + &:hover { + color: #9E9C9C; + } .favourite_question color: #bbbbbb !important diff --git a/addons/website_forum/static/src/js/website_forum.editor.js b/addons/website_forum/static/src/js/website_forum.editor.js index 6687ed5e3f2..b14191b3557 100644 --- a/addons/website_forum/static/src/js/website_forum.editor.js +++ b/addons/website_forum/static/src/js/website_forum.editor.js @@ -9,10 +9,24 @@ website.prompt({ id: "editor_new_forum", window_title: _t("New Forum"), - input: "Forum Name", - }).then(function (forum_name) { + input: "Forum Name",init: function () { + var $group = this.$dialog.find("div.form-group"); + $group.removeClass("mb0"); + + var $add = $( + '
'+ + ''+ + '
'); + $add.find('label').append(_t("Add page in menu")); + $group.after($add); + } + }).then(function (forum_name, field, $dialog) { + var add_menu = ($dialog.find('input[type="checkbox"]').is(':checked')); website.form('/forum/new', 'POST', { - forum_name: forum_name + forum_name: forum_name, + add_menu: add_menu || "" }); }); }, diff --git a/addons/website_forum/static/src/js/website_forum.js b/addons/website_forum/static/src/js/website_forum.js index 3d7ec8c8559..6abe4b97ffc 100644 --- a/addons/website_forum/static/src/js/website_forum.js +++ b/addons/website_forum/static/src/js/website_forum.js @@ -1,4 +1,6 @@ + openerp.website.if_dom_contains('.website_forum', function () { + var _t = openerp._t; $("[data-toggle='popover']").popover(); $('.karma_required').on('click', function (ev) { var karma = $(ev.currentTarget).data('karma'); @@ -6,8 +8,8 @@ ev.preventDefault(); var $warning = $('
'+ ''+ - karma + ' karma is required to perform this action. You can earn karma by having '+ - 'your answers upvoted by the community.
'); + karma + _t(' karma is required to perform this action. You can earn karma by having your answers upvoted by the community.')+ + ''); var vote_alert = $(ev.currentTarget).parent().find("#vote_alert"); if (vote_alert.length == 0) { $(ev.currentTarget).parent().append($warning); @@ -24,12 +26,12 @@ if (data['error'] == 'own_post'){ var $warning = $('
'+ ''+ - 'Sorry, you cannot vote for your own posts'+ + _t('Sorry, you cannot vote for your own posts')+ '
'); } else if (data['error'] == 'anonymous_user'){ var $warning = $('
'+ ''+ - 'Sorry you must be logged to vote'+ + _t('Sorry you must be logged to vote')+ '
'); } vote_alert = $link.parent().find("#vote_alert"); @@ -37,7 +39,7 @@ $link.parent().append($warning); } } else { - $link.parent().find("#vote_count").html(data['vote_count']); + $link.parent().find(".vote_count").html(data['vote_count']); if (data['user_vote'] == 0) { $link.parent().find(".text-success").removeClass("text-success"); $link.parent().find(".text-warning").removeClass("text-warning"); @@ -60,7 +62,7 @@ if (data['error'] == 'anonymous_user') { var $warning = $('
'+ ''+ - 'Sorry, anonymous users cannot choose correct answer.'+ + _t('Sorry, anonymous users cannot choose correct answer.')+ '
'); } correct_answer_alert = $link.parent().find("#correct_answer_alert"); @@ -69,6 +71,7 @@ } } else { if (data) { + $(".oe_answer_true").addClass('oe_answer_false').removeClass("oe_answer_true"); $link.addClass("oe_answer_true").removeClass('oe_answer_false'); } else { $link.removeClass("oe_answer_true").addClass('oe_answer_false'); @@ -120,15 +123,22 @@ openerp.jsonRpc("/forum/validate_email/close", 'call', {}); }); + // welcome message action button + var forum_login = _.string.sprintf('%s/web?redirect=%s', + window.location.origin, escape(window.location.href)); + $('.forum_register_url').attr('href',forum_login); $('.js_close_intro').on('click', function (ev) { ev.preventDefault(); - document.cookie = "no_introduction_message = false"; + document.cookie = "forum_welcome_message = false"; + $('.forum_intro').slideUp(); return true; }); + $('.link_url').on('change', function (ev) { ev.preventDefault(); + var $link = $(ev.currentTarget); var display_error = function(){ var $warning = $('
'+ ''+ @@ -137,11 +147,13 @@ $link.parent().append($warning); $("button#btn_post_your_article")[0].disabled = true; }; - var $link = $(ev.currentTarget); - if ($link.val().search("^http(s?)://.*")) { - display_error(); - } else { - openerp.jsonRpc("/forum/get_url_title", 'call', {'url': $link.val()}).then(function (data) { + var url = $link.val(); + if (url.search("^http(s?)://.*")) { + url = 'http://'+url; + } + var regex = new RegExp("(http(s)?://.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)"); + if(regex.test(url)){ + openerp.jsonRpc("/forum/get_url_title", 'call', {'url': url}).then(function (data) { if(data){ $("input[name='post_name']")[0].value = data; $('button#btn_post_your_article').prop('disabled', false); @@ -149,6 +161,8 @@ display_error(); } }); + }else{ + display_error(); } }); diff --git a/addons/website_forum/views/forum.xml b/addons/website_forum/views/forum.xml index d9cbde28bd2..fd90550dd9d 100644 --- a/addons/website_forum/views/forum.xml +++ b/addons/website_forum/views/forum.xml @@ -32,27 +32,19 @@ - - - - - - - -
- - - - - - - -
-
+ + + + + + + + +
@@ -158,6 +150,16 @@ + + + + + + + + + +
@@ -176,13 +178,14 @@ - + + @@ -206,6 +209,7 @@ tree,form,graph + {'search_default_questions':1} diff --git a/addons/website_forum/views/website_forum.xml b/addons/website_forum/views/website_forum.xml index 0ef3bb3d71c..b5c0615a2e1 100644 --- a/addons/website_forum/views/website_forum.xml +++ b/addons/website_forum/views/website_forum.xml @@ -45,15 +45,10 @@ + + +