From f6a78dd0b4882ba85988fdfdb978272886d86a62 Mon Sep 17 00:00:00 2001 From: MrPercheul Date: Wed, 1 Jun 2022 13:23:21 +0200 Subject: [PATCH] Mention users in comments (#429) Mention users in comments (#429) --- cms/settings.py | 1 + docs/images/Mention1.png | Bin 0 -> 9132 bytes docs/images/Mention2.png | Bin 0 -> 7180 bytes docs/images/Mention3.png | Bin 0 -> 7346 bytes docs/images/Mention4.png | Bin 0 -> 15507 bytes docs/user_docs.md | 16 ++- files/context_processors.py | 1 + files/methods.py | 52 ++++++++- files/views.py | 4 + frontend/package.json | 1 + .../src/static/css/config/_dark_theme.scss | 1 + .../src/static/css/config/_light_theme.scss | 1 + .../js/components/comments/Comments.jsx | 104 +++++++++++++++--- .../js/components/comments/Comments.scss | 15 ++- .../src/static/js/utils/settings/member.js | 3 + .../static/js/utils/stores/MediaPageStore.js | 18 +++ templates/config/installation/features.html | 1 + 17 files changed, 194 insertions(+), 24 deletions(-) create mode 100644 docs/images/Mention1.png create mode 100644 docs/images/Mention2.png create mode 100644 docs/images/Mention3.png create mode 100644 docs/images/Mention4.png diff --git a/cms/settings.py b/cms/settings.py index e0c0b52..4d26517 100644 --- a/cms/settings.py +++ b/cms/settings.py @@ -86,6 +86,7 @@ MAX_MEDIA_PER_PLAYLIST = 70 UPLOAD_MAX_SIZE = 800 * 1024 * 1000 * 5 MAX_CHARS_FOR_COMMENT = 10000 # so that it doesn't end up huge +ALLOW_MENTION_IN_COMMENTS = False # allowing to mention other users with @ in the comments # valid options: content, author RELATED_MEDIA_STRATEGY = "content" diff --git a/docs/images/Mention1.png b/docs/images/Mention1.png new file mode 100644 index 0000000000000000000000000000000000000000..ee653318cf5e6b7a07da819dba3657b9835ec2cc GIT binary patch literal 9132 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

FFu49|)b8 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 K74ol|1^gEiLvV-y literal 0 HcmV?d00001 diff --git a/docs/images/Mention2.png b/docs/images/Mention2.png new file mode 100644 index 0000000000000000000000000000000000000000..19f3a57965056748b2b44fe4bebd78c973ff0c4b GIT binary patch literal 7180 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 literal 0 HcmV?d00001 diff --git a/docs/images/Mention3.png b/docs/images/Mention3.png new file mode 100644 index 0000000000000000000000000000000000000000..c37c54ffb4837d53216d4c4c729b377a5a0d7cf7 GIT binary patch literal 7346 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 literal 0 HcmV?d00001 diff --git a/docs/images/Mention4.png b/docs/images/Mention4.png new file mode 100644 index 0000000000000000000000000000000000000000..c6cb6b53e2ae840a5275ff849aa9eca1f74c4feb GIT binary patch literal 15507 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

+## Mentionning users in comments + +Comments can also mention other users by tagging with '@'. This will open suggestion box showing usernames, and the selection will refine as the user continues typing. + +Comments send with mentions will contain a link to the user page, and can be setup to send a mail to the mentionned user. + +

+ + + + +

+ ## Search media How search can be used diff --git a/files/context_processors.py b/files/context_processors.py index 997f979..19817ed 100644 --- a/files/context_processors.py +++ b/files/context_processors.py @@ -13,6 +13,7 @@ def stuff(request): ret["CAN_LOGIN"] = settings.LOGIN_ALLOWED ret["CAN_REGISTER"] = settings.REGISTER_ALLOWED ret["CAN_UPLOAD_MEDIA"] = settings.UPLOAD_MEDIA_ALLOWED + ret["CAN_MENTION_IN_COMMENTS"] = settings.ALLOW_MENTION_IN_COMMENTS ret["CAN_LIKE_MEDIA"] = settings.CAN_LIKE_MEDIA ret["CAN_DISLIKE_MEDIA"] = settings.CAN_DISLIKE_MEDIA ret["CAN_REPORT_MEDIA"] = settings.CAN_REPORT_MEDIA diff --git a/files/methods.py b/files/methods.py index 1cf796c..60c599d 100644 --- a/files/methods.py +++ b/files/methods.py @@ -4,6 +4,7 @@ import itertools import logging import random +import re from datetime import datetime from django.conf import settings @@ -324,8 +325,6 @@ def update_user_ratings(user, media, user_ratings): def notify_user_on_comment(friendly_token): """Notify users through email, for a set of actions""" - - media = None media = models.Media.objects.filter(friendly_token=friendly_token).first() if not media: return False @@ -347,6 +346,55 @@ View it on %s return True +def notify_user_on_mention(friendly_token, user_mentioned, cleaned_comment): + from users.models import User + + media = models.Media.objects.filter(friendly_token=friendly_token).first() + if not media: + return False + + user = User.objects.filter(username=user_mentioned).first() + media_url = settings.SSL_FRONTEND_HOST + media.get_absolute_url() + + if user.notification_on_comments: + title = "[{}] - You were mentioned in a comment".format(settings.PORTAL_NAME) + msg = """ +You were mentioned in a comment on %s . +View it on %s + +Comment : %s + """ % ( + media.title, + media_url, + cleaned_comment, + ) + email = EmailMessage(title, msg, settings.DEFAULT_FROM_EMAIL, [user.email]) + email.send(fail_silently=True) + return True + + +def check_comment_for_mention(friendly_token, comment_text): + """Check the comment for any mentions, and notify each mentioned users""" + cleaned_comment = '' + + matches = re.findall('@\\(_(.+?)_\\)', comment_text) + if matches: + cleaned_comment = clean_comment(comment_text) + + for match in list(dict.fromkeys(matches)): + notify_user_on_mention(friendly_token, match, cleaned_comment) + + +def clean_comment(raw_comment): + """Clean the comment fromn ID and username Mentions for preview purposes""" + + cleaned_comment = re.sub('@\\(_(.+?)_\\)', '', raw_comment) + cleaned_comment = cleaned_comment.replace("[_", '') + cleaned_comment = cleaned_comment.replace("_]", '') + + return cleaned_comment + + def list_tasks(): """Lists celery tasks To be used in an admin dashboard diff --git a/files/views.py b/files/views.py index b5a81b3..b3f2cc8 100644 --- a/files/views.py +++ b/files/views.py @@ -32,6 +32,7 @@ from users.models import User from .forms import ContactForm, MediaForm, SubtitleForm from .helpers import clean_query, produce_ffmpeg_commands from .methods import ( + check_comment_for_mention, get_user_or_session, is_mediacms_editor, is_mediacms_manager, @@ -1277,6 +1278,9 @@ class CommentDetail(APIView): serializer.save(user=request.user, media=media) if request.user != media.user: notify_user_on_comment(friendly_token=media.friendly_token) + # here forward the comment to check if a user was mentioned + if settings.ALLOW_MENTION_IN_COMMENTS: + check_comment_for_mention(friendly_token=media.friendly_token, comment_text=serializer.data['text']) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) diff --git a/frontend/package.json b/frontend/package.json index c8f7826..396bd6b 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -46,6 +46,7 @@ "normalize.css": "^8.0.1", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-mentions": "^4.3.1", "sortablejs": "^1.13.0", "timeago.js": "^4.0.2", "url-parse": "^1.5.1" diff --git a/frontend/src/static/css/config/_dark_theme.scss b/frontend/src/static/css/config/_dark_theme.scss index 2596bea..2cf8786 100755 --- a/frontend/src/static/css/config/_dark_theme.scss +++ b/frontend/src/static/css/config/_dark_theme.scss @@ -94,6 +94,7 @@ body.dark_theme { --comment-date-hover-text-color: #fff; --comment-text-color: rgba(255, 255, 255, 0.88); + --comment-text-mentions-background-color-highlight:#006622; --comment-actions-material-icon-text-color: rgba(255, 255, 255, 0.74); diff --git a/frontend/src/static/css/config/_light_theme.scss b/frontend/src/static/css/config/_light_theme.scss index 88c8e0d..3011401 100755 --- a/frontend/src/static/css/config/_light_theme.scss +++ b/frontend/src/static/css/config/_light_theme.scss @@ -94,6 +94,7 @@ body { --comment-date-hover-text-color: #0a0a0a; --comment-text-color: #111; + --comment-text-mentions-background-color-highlight:#00cc44; --comment-actions-material-icon-text-color: rgba(17, 17, 17, 0.8); diff --git a/frontend/src/static/js/components/comments/Comments.jsx b/frontend/src/static/js/components/comments/Comments.jsx index f59fff9..f5816db 100644 --- a/frontend/src/static/js/components/comments/Comments.jsx +++ b/frontend/src/static/js/components/comments/Comments.jsx @@ -1,4 +1,5 @@ import React, { useState, useRef, useEffect } from 'react'; +import { MentionsInput, Mention } from 'react-mentions'; import PropTypes from 'prop-types'; import { format } from 'timeago.js'; import { usePopup } from '../../utils/hooks/'; @@ -25,6 +26,7 @@ function CommentForm(props) { const [madeChanges, setMadeChanges] = useState(false); const [textareaFocused, setTextareaFocused] = useState(false); const [textareaLineHeight, setTextareaLineHeight] = useState(-1); + const [userList, setUsersList] = useState(''); const [loginUrl] = useState( !MemberContext._currentValue.is.anonymous @@ -42,6 +44,17 @@ function CommentForm(props) { setTextareaFocused(false); } + function onUsersLoad() + { + const userList =[...MediaPageStore.get('users')]; + const cleanList = [] + userList.forEach(user => { + cleanList.push({id : user.username, display : user.name}); + }); + + setUsersList(cleanList); + } + function onCommentSubmit() { textareaRef.current.style.height = ''; @@ -61,6 +74,21 @@ function CommentForm(props) { setMadeChanges(false); } + function onChangeWithMention(event, newValue, newPlainTextValue, mentions) { + textareaRef.current.style.height = ''; + + setValue(newValue); + setMadeChanges(true); + + const contentHeight = textareaRef.current.scrollHeight; + const contentLineHeight = + 0 < textareaLineHeight ? textareaLineHeight : parseFloat(window.getComputedStyle(textareaRef.current).lineHeight); + setTextareaLineHeight(contentLineHeight); + + textareaRef.current.style.height = + Math.max(20, textareaLineHeight * Math.ceil(contentHeight / contentLineHeight)) + 'px'; + } + function onChange(event) { textareaRef.current.style.height = ''; @@ -81,7 +109,7 @@ function CommentForm(props) { return; } - const val = textareaRef.current.value.trim(); + const val = value.trim(); if ('' !== val) { MediaPageActions.submitComment(val); @@ -91,10 +119,18 @@ function CommentForm(props) { useEffect(() => { MediaPageStore.on('comment_submit', onCommentSubmit); MediaPageStore.on('comment_submit_fail', onCommentSubmitFail); + if (MediaCMS.features.media.actions.comment_mention === true) + { + MediaPageStore.on('users_load', onUsersLoad); + } return () => { MediaPageStore.removeListener('comment_submit', onCommentSubmit); MediaPageStore.removeListener('comment_submit_fail', onCommentSubmitFail); + if (MediaCMS.features.media.actions.comment_mention === true) + { + MediaPageStore.removeListener('users_load', onUsersLoad); + } }; }); @@ -104,16 +140,33 @@ function CommentForm(props) {
- + { MediaCMS.features.media.actions.comment_mention ? + + + + : + + }