Skip to content
Snippets Groups Projects
Commit c0fb8e2b authored by Christos's avatar Christos
Browse files

Merge branch 'comments-mentions' into 'master'

Comments mentions

See merge request !619
parents 18981f5d 9dfaef88
No related branches found
No related tags found
1 merge request!619Comments mentions
Pipeline #62250 passed with stages
in 2 minutes and 16 seconds
......@@ -296,9 +296,18 @@ export default {
ImageService: { showAlt: true },
CommentsService: {
showTitle: true,
// showTitle: true,
getComments,
setComments,
getMentionedUsers: (users, text) => {
console.log(users, text);
},
userList: [
{ id: '1', displayName: 'test1' },
{ id: '2', displayName: 'test2' },
{ id: '3', displayName: 'test3' },
{ id: '4', displayName: 'test4' },
],
},
CustomTagService: {
......
......@@ -33,6 +33,7 @@
"prosemirror-view": "1.30.2",
"rc-switch": "^3.2.2",
"react-dropdown": "^1.6.2",
"rc-mentions": "^2.15.0",
"react-i18next": "^13.3.1",
"use-deep-compare-effect": "^1.3.1",
"uuid": "^7.0.3",
......
......@@ -55,6 +55,12 @@ export default ({
commentConfig && commentConfig.readOnly ? commentConfig.readOnly : false;
const showTitle =
commentConfig && commentConfig.showTitle ? commentConfig.showTitle : false;
const usersMentionList =
commentConfig && commentConfig.userList ? commentConfig.userList : [];
const getMentionedUsers =
commentConfig && commentConfig.getMentionedUsers
? commentConfig.getMentionedUsers
: () => true;
useEffect(() => {
recalculateTops();
......@@ -69,6 +75,7 @@ export default ({
}, [activeComment]);
const onClickPost = ({ commentValue, title }) => {
getUsersFromComment(commentValue);
setClickPost(true);
const currentUser = user || (users || []).find(u => u.currentUser === true);
......@@ -96,6 +103,18 @@ export default ({
recalculateTops();
};
const getUsersFromComment = commentText => {
if (usersMentionList.length === 0) return false;
const mentionedUsers = [];
usersMentionList.forEach(mentionUser => {
if (commentText.includes(mentionUser.displayName)) {
mentionedUsers.push(mentionUser);
}
});
if (mentionedUsers.length > 0)
getMentionedUsers(mentionedUsers, commentText);
};
const onClickBox = () => {
if (isActive) {
pmViews[viewId].focus();
......@@ -159,6 +178,7 @@ export default ({
showTitle={showTitle}
title={comment.data.title}
users={users}
usersMentionList={usersMentionList}
/>
</ConnectedCommentStyled>
),
......
......@@ -84,6 +84,7 @@ const CommentBox = props => {
title,
showTitle,
users,
usersMentionList,
} = props;
// send signal to make this comment active
......@@ -124,6 +125,7 @@ const CommentBox = props => {
onClickPost={onClickPost}
onTextAreaBlur={onTextAreaBlur}
showTitle={showTitle}
usersMentionList={usersMentionList}
/>
)}
</Wrapper>
......
/* eslint-disable react/prop-types */
import React, { useState, useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import styled, { css } from 'styled-components';
......@@ -5,6 +6,8 @@ import { isEmpty } from 'lodash';
import { useTranslation } from 'react-i18next';
import { grid, th, override } from '@pubsweet/ui-toolkit';
import { useOnClickOutside } from 'wax-prosemirror-core';
import Mentions from 'rc-mentions';
import './mentions.css';
const Wrapper = styled.div`
background: ${th('colorBackgroundHue')};
......@@ -30,20 +33,6 @@ const CommentTitle = styled.input`
${override('Wax.CommentTitle')}
`;
const ReplyTextArea = styled.textarea`
background: ${th('colorBackgroundHue')};
border: 3px solid ${th('colorBackgroundTabs')};
font-family: ${th('fontWriting')};
position: relative;
width: 100%;
&:focus {
outline: 1px solid ${th('colorPrimary')};
}
${override('Wax.CommentTextArea')}
`;
const ActionWrapper = styled.div`
display: flex;
justify-content: flex-start;
......@@ -75,6 +64,26 @@ const ButtonGroup = styled.div`
${override('Wax.CommentButtonGroup')}
`;
const StyledMentions = styled(Mentions)`
border: none;
> textarea {
font-size: 14px;
background: ${th('colorBackgroundHue')};
border: 3px solid ${th('colorBackgroundTabs')};
font-family: ${th('fontWriting')};
padding: 2px;
&:focus {
outline: 1px solid ${th('colorPrimary')};
}
&:focus {
outline: 1px solid ${th('colorPrimary')};
}
}
${override('Wax.CommentTextArea')}
`;
const CommentReply = props => {
const {
className,
......@@ -83,13 +92,13 @@ const CommentReply = props => {
isReadOnly,
onTextAreaBlur,
showTitle,
usersMentionList,
} = props;
const { t, i18n } = useTranslation();
const commentInput = useRef(null);
const commentTitle = useRef(null);
const [commentValue, setCommentValue] = useState('');
const [title, setTitle] = useState('');
const ref = useRef(null);
useOnClickOutside(ref, onTextAreaBlur);
......@@ -115,6 +124,8 @@ const CommentReply = props => {
setTitle('');
};
const { Option } = Mentions;
return (
<Wrapper className={className} ref={ref}>
<form onSubmit={handleSubmit}>
......@@ -135,11 +146,20 @@ const CommentReply = props => {
value={title}
/>
)}
<ReplyTextArea
cols="5"
onChange={() => setCommentValue(commentInput.current.value)}
onKeyDown={e => {
if (e.keyCode === 13 && !e.shiftKey) {
<StyledMentions
onChange={text => {
setCommentValue(text);
}}
onPressEnter={e => {
const mentionsOptionsEl = document.getElementsByClassName(
'rc-mentions-measure',
);
if (
e.keyCode === 13 &&
!e.shiftKey &&
mentionsOptionsEl.length === 0
) {
e.preventDefault();
if (commentValue) handleSubmit(e);
}
......@@ -158,9 +178,16 @@ const CommentReply = props => {
}...`
}
ref={commentInput}
rows="3"
rows="4"
value={commentValue}
/>
>
{usersMentionList &&
usersMentionList.map(item => (
<Option key={item.id} value={item.displayName}>
{item.displayName}
</Option>
))}
</StyledMentions>
</TextWrapper>
<ActionWrapper>
......
.rc-mentions {
display: inline-block;
position: relative;
white-space: pre-wrap;
}
.rc-mentions>textarea,
.rc-mentions-measure {
font-size: inherit;
font-size-adjust: inherit;
font-style: inherit;
font-variant: inherit;
font-stretch: inherit;
font-weight: inherit;
font-family: inherit;
padding: 0;
margin: 0;
line-height: inherit;
vertical-align: top;
overflow: inherit;
word-break: inherit;
white-space: inherit;
word-wrap: break-word;
overflow-x: initial;
overflow-y: auto;
text-align: inherit;
letter-spacing: inherit;
tab-size: inherit;
direction: inherit;
}
.rc-mentions>textarea {
border: none;
width: 100%;
}
.rc-mentions-measure {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
pointer-events: none;
color: transparent;
z-index: -1;
}
.rc-mentions-dropdown {
position: absolute;
}
.rc-mentions-dropdown-menu {
list-style: none;
margin: 0;
padding: 0;
}
.rc-mentions-dropdown-menu-item {
cursor: pointer;
}
.rc-mentions {
font-size: 20px;
border: 1px solid #999;
border-radius: 3px;
overflow: hidden;
}
.rc-mentions-dropdown {
border: 1px solid #999;
border-radius: 3px;
background: #FFF;
}
.rc-mentions-dropdown-menu-item {
padding: 4px 8px;
}
.rc-mentions-dropdown-menu-item-active {
background: #e6f7ff;
}
.rc-mentions-dropdown-menu-item-disabled {
opacity: 0.5;
}
\ No newline at end of file
......@@ -1099,6 +1099,13 @@
dependencies:
regenerator-runtime "^0.14.0"
 
"@babel/runtime@^7.11.1", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.23.2":
version "7.25.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb"
integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.10.4", "@babel/template@^7.14.5", "@babel/template@^7.4.0", "@babel/template@^7.8.6":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
......@@ -1617,6 +1624,27 @@
lodash "^4.17.4"
styled-components "^4.1.1"
 
"@rc-component/portal@^1.1.0":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@rc-component/portal/-/portal-1.1.2.tgz#55db1e51d784e034442e9700536faaa6ab63fc71"
integrity sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==
dependencies:
"@babel/runtime" "^7.18.0"
classnames "^2.3.2"
rc-util "^5.24.4"
"@rc-component/trigger@^2.0.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-2.2.0.tgz#503a48b0895a2cfddee0a5b7b11492c3df2a493d"
integrity sha512-QarBCji02YE9aRFhZgRZmOpXBj0IZutRippsVBv85sxvG4FGk/vRxwAlkn3MS9zK5mwbETd86mAVg2tKqTkdJA==
dependencies:
"@babel/runtime" "^7.23.2"
"@rc-component/portal" "^1.1.0"
classnames "^2.3.2"
rc-motion "^2.0.0"
rc-resize-observer "^1.3.1"
rc-util "^5.38.0"
"@rollup/plugin-babel@^6.0.4":
version "6.0.4"
resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz#bd698e351fa9aa9619fcae780aea2a603d98e4c4"
......@@ -3517,6 +3545,11 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
 
classnames@2.x, classnames@^2.2.6, classnames@^2.3.2:
version "2.5.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
classnames@^2.2.1, classnames@^2.2.3:
version "2.3.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
......@@ -12149,6 +12182,69 @@ raw-body@2.4.0:
iconv-lite "0.4.24"
unpipe "1.0.0"
 
rc-input@~1.6.0:
version "1.6.2"
resolved "https://registry.yarnpkg.com/rc-input/-/rc-input-1.6.2.tgz#bb356a3b8af421beb7ff26d54ebf054396dfe447"
integrity sha512-nJqsiIv8K88w8pvbUR5savKqBokdSR0zVGPntLApeOKFp8dp6s92l1CzD60yVActpCZAJwlCfRX5rno+QVYV7g==
dependencies:
"@babel/runtime" "^7.11.1"
classnames "^2.2.1"
rc-util "^5.18.1"
rc-mentions@^2.15.0:
version "2.15.0"
resolved "https://registry.yarnpkg.com/rc-mentions/-/rc-mentions-2.15.0.tgz#ada022b32e68fa067a859ee0024c3f2aa7a9c871"
integrity sha512-f5v5i7VdqvBDXbphoqcQWmXDif2Msd2arritVoWybrVDuHE6nQ7XCYsybHbV//WylooK52BFDouFvyaRDtXZEw==
dependencies:
"@babel/runtime" "^7.22.5"
"@rc-component/trigger" "^2.0.0"
classnames "^2.2.6"
rc-input "~1.6.0"
rc-menu "~9.14.0"
rc-textarea "~1.8.0"
rc-util "^5.34.1"
rc-menu@~9.14.0:
version "9.14.1"
resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-9.14.1.tgz#5c2aea72bdce421e9d50bf721ad8b76c154ae66f"
integrity sha512-5wlRb3M8S4yGlWhSoEYJ7ZVRElyScdcpUHxgiLxkeig1tEdyKrnED3B2fhpN0Rrpdp9jyhnmZR/Lwq2fH5VvDQ==
dependencies:
"@babel/runtime" "^7.10.1"
"@rc-component/trigger" "^2.0.0"
classnames "2.x"
rc-motion "^2.4.3"
rc-overflow "^1.3.1"
rc-util "^5.27.0"
rc-motion@^2.0.0, rc-motion@^2.4.3:
version "2.9.2"
resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.9.2.tgz#f7c6d480250df8a512d0cfdce07ff3da906958cf"
integrity sha512-fUAhHKLDdkAXIDLH0GYwof3raS58dtNUmzLF2MeiR8o6n4thNpSDQhOqQzWE4WfFZDCi9VEN8n7tiB7czREcyw==
dependencies:
"@babel/runtime" "^7.11.1"
classnames "^2.2.1"
rc-util "^5.43.0"
rc-overflow@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/rc-overflow/-/rc-overflow-1.3.2.tgz#72ee49e85a1308d8d4e3bd53285dc1f3e0bcce2c"
integrity sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==
dependencies:
"@babel/runtime" "^7.11.1"
classnames "^2.2.1"
rc-resize-observer "^1.0.0"
rc-util "^5.37.0"
rc-resize-observer@^1.0.0, rc-resize-observer@^1.3.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz#7bba61e6b3c604834980647cce6451914750d0cc"
integrity sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==
dependencies:
"@babel/runtime" "^7.20.7"
classnames "^2.2.1"
rc-util "^5.38.0"
resize-observer-polyfill "^1.5.1"
rc-switch@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/rc-switch/-/rc-switch-3.2.2.tgz#d001f77f12664d52595b4f6fb425dd9e66fba8e8"
......@@ -12158,6 +12254,17 @@ rc-switch@^3.2.2:
classnames "^2.2.1"
rc-util "^5.0.1"
 
rc-textarea@~1.8.0:
version "1.8.1"
resolved "https://registry.yarnpkg.com/rc-textarea/-/rc-textarea-1.8.1.tgz#0313ed2e7980269e1bd4f3c203a4e9a84cad8e2d"
integrity sha512-bm36N2ZqwZAP60ZQg2OY9mPdqWC+m6UTjHc+CqEZOxb3Ia29BGHazY/s5bI8M4113CkqTzhtFUDNA078ZiOx3Q==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "^2.2.1"
rc-input "~1.6.0"
rc-resize-observer "^1.0.0"
rc-util "^5.27.0"
rc-util@^5.0.1:
version "5.13.2"
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.13.2.tgz#a8a0bb77743351841ba8bed6393e03b8d2f685c8"
......@@ -12167,6 +12274,14 @@ rc-util@^5.0.1:
react-is "^16.12.0"
shallowequal "^1.1.0"
 
rc-util@^5.18.1, rc-util@^5.24.4, rc-util@^5.27.0, rc-util@^5.34.1, rc-util@^5.37.0, rc-util@^5.38.0, rc-util@^5.43.0:
version "5.43.0"
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.43.0.tgz#bba91fbef2c3e30ea2c236893746f3e9b05ecc4c"
integrity sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==
dependencies:
"@babel/runtime" "^7.18.3"
react-is "^18.2.0"
rc@^1.0.1, rc@^1.1.6:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
......@@ -12260,6 +12375,11 @@ react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
 
react-is@^18.2.0:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
react-panelgroup@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/react-panelgroup/-/react-panelgroup-1.0.10.tgz#53d2d8279a89dca0dabcf58ad5c4240e21b17486"
......@@ -12764,6 +12884,11 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
 
resize-observer-polyfill@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
resolve-cwd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment