From 280537b9fed04feda2470aa99f56b7602ce1996a Mon Sep 17 00:00:00 2001 From: "Lopes Marc (loma)" Date: Wed, 14 Jun 2023 13:24:04 +0000 Subject: [PATCH] [IMP] website_forum: replace bump with last activity Purpose ======= 1. The post "activity" date shown on a forum's list of posts is not a great user experience as it is seems to be updated for writes on the original post and not, e.g., when a reply is added. 2. Remove bumping on social sharing. As we are not in 2015 anymore, sharing is not a relevant "activity" for the post. This is illustrated by the fact that `allow_bump` could not be updated with the client, and the "default" "target_type" is not found in the codebase anymore. We clean that here. Specifications ============== - Drop bump_date and use last_activity_date instead of write date to log activity - Update post last_activity_date whenever a reply or a comment is added to the original post or one of its replies - Sort posts lists by `last_activity_date desc` by default - Use luxon.js library to render the bump_date field as a `relative datetime`(e.g.: 2 days ago, 1 hour ago...) Task-3349374 Task-3316555 Part-of: odoo/odoo#123709 Co-authored-by: Florian Charlier --- addons/website_forum/__manifest__.py | 2 +- .../controllers/website_forum.py | 14 +++------ addons/website_forum/models/forum_forum.py | 8 ++--- addons/website_forum/models/forum_post.py | 24 +++++++-------- .../static/src/js/website_forum.js | 6 ++++ .../static/src/js/website_forum.share.js | 23 --------------- .../static/src/xml/public_templates.xml | 4 +-- .../views/forum_forum_templates.xml | 4 +-- .../views/forum_forum_templates_post.xml | 29 ++++++++----------- 9 files changed, 39 insertions(+), 75 deletions(-) diff --git a/addons/website_forum/__manifest__.py b/addons/website_forum/__manifest__.py index 25c5828edd0..e1a6ce0565f 100644 --- a/addons/website_forum/__manifest__.py +++ b/addons/website_forum/__manifest__.py @@ -7,7 +7,7 @@ 'category': 'Website/Website', 'sequence': 265, 'summary': 'Manage a forum with FAQ and Q&A', - 'version': '1.1', + 'version': '1.2', 'description': """ Ask questions, get answers, no distractions """, diff --git a/addons/website_forum/controllers/website_forum.py b/addons/website_forum/controllers/website_forum.py index 3715aee917e..39288285fc0 100644 --- a/addons/website_forum/controllers/website_forum.py +++ b/addons/website_forum/controllers/website_forum.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import json import logging -from datetime import datetime import lxml import requests @@ -281,7 +280,6 @@ class WebsiteForum(WebsiteProfile): 'main_object': question, 'edit_in_backend': True, 'question': question, - 'can_bump': (question.forum_id.allow_bump and not question.child_count and (datetime.today() - question.write_date).days > 9), 'header': {'question_data': True}, 'filters': filters, 'reversed': reversed, @@ -378,11 +376,13 @@ class WebsiteForum(WebsiteProfile): 'parent_id': post_parent and post_parent.id or False, 'tag_ids': post_tag_ids }) + if post_parent: + post_parent._update_last_activity() return request.redirect("/forum/%s/%s" % (slug(forum), post_parent and slug(post_parent) or new_question.id)) @http.route('/forum//post//comment', type='http', auth="user", methods=['POST'], website=True) def post_comment(self, forum, post, **kwargs): - question = post.parent_id if post.parent_id else post + question = post.parent_id or post 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 body = tools.mail.plaintext2html(kwargs['comment']) @@ -390,6 +390,7 @@ class WebsiteForum(WebsiteProfile): body=body, message_type='comment', subtype_xmlid='mail.mt_comment') + question._update_last_activity() return request.redirect("/forum/%s/%s" % (slug(forum), slug(question))) @http.route('/forum//post//toggle_correct', type='json', auth="public", website=True) @@ -467,13 +468,6 @@ class WebsiteForum(WebsiteProfile): upvote = True if post.user_vote < 0 else False return post.vote(upvote=upvote) - @http.route('/forum/post/bump', type='json', auth="public", website=True) - def post_bump(self, post_id, **kwarg): - post = request.env['forum.post'].browse(int(post_id)) - if not post.exists() or post.parent_id: - return False - return post.bump() - # Moderation Tools # -------------------------------------------------- diff --git a/addons/website_forum/models/forum_forum.py b/addons/website_forum/models/forum_forum.py index d65f27a2732..c39a4d6034d 100644 --- a/addons/website_forum/models/forum_forum.py +++ b/addons/website_forum/models/forum_forum.py @@ -76,17 +76,13 @@ class Forum(models.Model): sanitize_attributes=False, sanitize_form=False) default_order = fields.Selection([ ('create_date desc', 'Newest'), - ('write_date desc', 'Last Updated'), + ('last_activity_date desc', 'Last Updated'), ('vote_count desc', 'Most Voted'), ('relevancy desc', 'Relevance'), ('child_count desc', 'Answered')], - string='Default', required=True, default='write_date desc') + string='Default', required=True, default='last_activity_date desc') relevancy_post_vote = fields.Float('First Relevance Parameter', default=0.8, help="This formula is used in order to sort by relevance. 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 Relevance Parameter', default=1.8) - allow_bump = fields.Boolean('Allow Bump', default=True, - help='Check this box to display a popup for posts older than 10 days ' - 'without any given answer. The popup will offer to share it on social ' - 'networks. When shared, a question is bumped at the top of the forum.') allow_share = fields.Boolean('Sharing Options', default=True, help='After posting the user will be proposed to share its question ' 'or answer on social networks, enabling social network propagation ' diff --git a/addons/website_forum/models/forum_post.py b/addons/website_forum/models/forum_post.py index 5e514c89a5a..0fe442b1564 100644 --- a/addons/website_forum/models/forum_post.py +++ b/addons/website_forum/models/forum_post.py @@ -23,7 +23,7 @@ class Post(models.Model): 'website.seo.metadata', 'website.searchable.mixin', ] - _order = "is_correct DESC, vote_count DESC, write_date DESC" + _order = "is_correct DESC, vote_count DESC, last_activity_date DESC" name = fields.Char('Title') forum_id = fields.Many2one('forum.forum', string='Forum', required=True) @@ -48,10 +48,11 @@ class Post(models.Model): create_date = fields.Datetime('Asked on', index=True, readonly=True) create_uid = fields.Many2one('res.users', string='Created by', index=True, readonly=True) write_date = fields.Datetime('Updated on', index=True, readonly=True) - bump_date = fields.Datetime('Bumped on', readonly=True, - help="Technical field allowing to bump a question. Writing on this field will trigger " - "a write on write_date and therefore bump the post. Directly writing on write_date " - "is currently not supported and this field is a workaround.") + last_activity_date = fields.Datetime( + 'Last activity on', readonly=True, required=True, default=fields.Datetime.now, + help="Field to keep track of a post's last activity. Updated whenever it is replied to, " + "or when a comment is added on the post or one of its replies." + ) write_uid = fields.Many2one('res.users', string='Updated by', index=True, readonly=True) relevancy = fields.Float('Relevance', compute="_compute_relevancy", store=True) @@ -602,15 +603,6 @@ class Post(models.Model): _logger.info('User %s marked as spams (in batch): %s' % (self.env.uid, spams)) return spams.mark_as_offensive(reason_id) - def bump(self): - """ Bump a question: trigger a write_date by writing on a dummy bump_date - field. One cannot bump a question more than once every 10 days. """ - self.ensure_one() - if self.forum_id.allow_bump and not self.child_ids and (datetime.today() - datetime.strptime(self.write_date, tools.DEFAULT_SERVER_DATETIME_FORMAT)).days > 9: - # write through super to bypass karma; sudo to allow public user to bump any post - return self.sudo().write({'bump_date': fields.Datetime.now()}) - return False - def vote(self, upvote=True): self.ensure_one() Vote = self.env['forum.post.vote'] @@ -724,6 +716,10 @@ class Post(models.Model): self.ensure_one() return sql.increment_fields_skiplock(self, 'views') + def _update_last_activity(self): + self.ensure_one() + return self.sudo().write({'last_activity_date': fields.Datetime.now()}) + # ---------------------------------------------------------------------- # MESSAGING # ---------------------------------------------------------------------- diff --git a/addons/website_forum/static/src/js/website_forum.js b/addons/website_forum/static/src/js/website_forum.js index e78f3f0f86c..73da9c0a575 100644 --- a/addons/website_forum/static/src/js/website_forum.js +++ b/addons/website_forum/static/src/js/website_forum.js @@ -164,6 +164,12 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({ }); }); + this.$('.o_wforum_question, .o_wforum_answer, .o_wforum_post_comment, .o_wforum_last_activity').toArray() + .forEach((post) => { + const relativeDateTime = luxon.DateTime.fromSQL($(post).data('lastActivity'), { zone: 'utc'}).toRelative(); + $(post).find('.o_wforum_relative_datetime').first().text(relativeDateTime); + }); + return this._super.apply(this, arguments); }, diff --git a/addons/website_forum/static/src/js/website_forum.share.js b/addons/website_forum/static/src/js/website_forum.share.js index 6b52c29dd54..33aa5e7a19d 100644 --- a/addons/website_forum/static/src/js/website_forum.share.js +++ b/addons/website_forum/static/src/js/website_forum.share.js @@ -34,13 +34,6 @@ var ForumShare = publicWidget.registry.socialShare.extend({ // Private //-------------------------------------------------------------------------- - /** - * @private - */ - _bindSocialEvent: function () { - this._super.apply(this, arguments); - $('.oe_share_bump').click($.proxy(this._postBump, this)); - }, /** * @private */ @@ -59,17 +52,6 @@ var ForumShare = publicWidget.registry.socialShare.extend({ $('#oe_social_share_modal').modal('show'); } }, - /** - * @private - */ - _postBump: function () { - this._rpc({ // FIXME - route: '/forum/post/bump', - params: { - post_id: this.element.data('id'), - }, - }); - }, }); publicWidget.registry.websiteForumShare = publicWidget.Widget.extend({ @@ -85,11 +67,6 @@ publicWidget.registry.websiteForumShare = publicWidget.Widget.extend({ (new ForumShare(this, false, socialData.targetType)).attachTo($(document.body)); sessionStorage.removeItem('social_share'); } - // Display an alert if post has no reply and is older than 10 days - var $questionContainer = $('.oe_js_bump'); - if ($questionContainer.length) { - new ForumShare(this, false, 'social-alert').attachTo($questionContainer); - } return this._super.apply(this, arguments); }, diff --git a/addons/website_forum/static/src/xml/public_templates.xml b/addons/website_forum/static/src/xml/public_templates.xml index 31843da2ffa..4eb4b62508b 100644 --- a/addons/website_forum/static/src/xml/public_templates.xml +++ b/addons/website_forum/static/src/xml/public_templates.xml @@ -57,10 +57,10 @@
-

Move this question to the top of the list by sharing it on social networks.


+

Share this post on social networks.


- + diff --git a/addons/website_forum/views/forum_forum_templates.xml b/addons/website_forum/views/forum_forum_templates.xml index 910ad23d7fb..10d4ad64f23 100644 --- a/addons/website_forum/views/forum_forum_templates.xml +++ b/addons/website_forum/views/forum_forum_templates.xml @@ -33,8 +33,8 @@ - - Activity + + Activity diff --git a/addons/website_forum/views/forum_forum_templates_post.xml b/addons/website_forum/views/forum_forum_templates_post.xml index 60050d8fa94..da69fdb7ea9 100644 --- a/addons/website_forum/views/forum_forum_templates_post.xml +++ b/addons/website_forum/views/forum_forum_templates_post.xml @@ -111,9 +111,8 @@ - - - + + @@ -297,13 +296,14 @@ -
+ t-att-data-type="post_type" + t-att-data-last-activity="post_id.create_date" + t-att-data-last-update="post_id.write_date" + t-attf-data-id="#{post_type}-#{post_id.id}" + t-attf-id="#{post_type}-#{post_id.id}" + t-att-data-state="post_id.state">
@@ -318,12 +318,7 @@ - - - - 2d ago + @@ -532,7 +527,7 @@
-
+
@@ -542,7 +537,7 @@ - Just now + Author