From 78462c0dd9d15516e8a7d8236aa8d2ca469491a2 Mon Sep 17 00:00:00 2001 From: A-AllaaEddine Date: Mon, 16 Oct 2023 11:37:34 +0100 Subject: [PATCH] added mention features to sparks --- package-lock.json | 79 +++++++-- package.json | 1 + src/components/common/cards/PostCard.js | 6 +- .../common/elements/MarkdownContent.js | 40 ++++- .../common/elements/MentionInput.js | 163 +++++++++++++++++ .../common/elements/MentionsSpan.js | 34 ++++ src/components/common/modals/ModalAlert.js | 8 +- .../modules/comments/EditComment.js | 12 +- src/components/modules/comments/NewComment.js | 167 +++++++++--------- .../modules/comments/ReplyToComment.js | 25 +-- src/components/modules/hangout/CreatePost.js | 39 ++-- src/components/modules/post/Content.js | 4 + 12 files changed, 434 insertions(+), 144 deletions(-) create mode 100644 src/components/common/elements/MentionInput.js create mode 100644 src/components/common/elements/MentionsSpan.js diff --git a/package-lock.json b/package-lock.json index ba19ff1..37856cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,6 +53,7 @@ "next-share": "^0.6.0", "next-themes": "^0.0.15", "nookies": "^2.5.2", + "primereact": "^10.0.3", "react": "^17.0.2", "react-3d-earth": "^1.0.5", "react-awesome-reveal": "^4.2.3", @@ -424,11 +425,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", - "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", + "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -447,6 +448,11 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "node_modules/@babel/template": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", @@ -2247,6 +2253,14 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.7.tgz", + "integrity": "sha512-ICCyBl5mvyqYp8Qeq9B5G/fyBSRC0zx3XM3sCC6KkcMsNeAHqXBKkmat4GqdJET5jtYUpZXrxI5flve5qhi2Eg==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", @@ -9721,6 +9735,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/primereact": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/primereact/-/primereact-10.0.3.tgz", + "integrity": "sha512-a+mC5I1gyOYZM0tf2c+7y0Pd9o6pref7fVeEXXXPk0lBORaSepMvuHqTUXCMRcN9buJ3aEfhhIDwX83K3TU5ow==", + "dependencies": { + "@types/react-transition-group": "^4.4.1", + "react-transition-group": "^4.4.1" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/prismjs": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", @@ -10516,7 +10549,8 @@ "node_modules/regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true }, "node_modules/regex-escape": { "version": "3.4.10", @@ -13235,11 +13269,18 @@ } }, "@babel/runtime": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", - "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", + "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.14.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + } } }, "@babel/runtime-corejs3": { @@ -14705,6 +14746,14 @@ "csstype": "^3.0.2" } }, + "@types/react-transition-group": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.7.tgz", + "integrity": "sha512-ICCyBl5mvyqYp8Qeq9B5G/fyBSRC0zx3XM3sCC6KkcMsNeAHqXBKkmat4GqdJET5jtYUpZXrxI5flve5qhi2Eg==", + "requires": { + "@types/react": "*" + } + }, "@types/responselike": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", @@ -19985,6 +20034,15 @@ "parse-ms": "^2.1.0" } }, + "primereact": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/primereact/-/primereact-10.0.3.tgz", + "integrity": "sha512-a+mC5I1gyOYZM0tf2c+7y0Pd9o6pref7fVeEXXXPk0lBORaSepMvuHqTUXCMRcN9buJ3aEfhhIDwX83K3TU5ow==", + "requires": { + "@types/react-transition-group": "^4.4.1", + "react-transition-group": "^4.4.1" + } + }, "prismjs": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", @@ -20549,7 +20607,8 @@ "regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true }, "regex-escape": { "version": "3.4.10", diff --git a/package.json b/package.json index ea675c0..bffb1da 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "next-share": "^0.6.0", "next-themes": "^0.0.15", "nookies": "^2.5.2", + "primereact": "^10.0.3", "react": "^17.0.2", "react-3d-earth": "^1.0.5", "react-awesome-reveal": "^4.2.3", diff --git a/src/components/common/cards/PostCard.js b/src/components/common/cards/PostCard.js index 783c7bd..6873de7 100644 --- a/src/components/common/cards/PostCard.js +++ b/src/components/common/cards/PostCard.js @@ -13,6 +13,7 @@ import extractUrls from 'extract-urls'; import TagPostType from 'components/common/tags/TagPostType'; import Icon from '../elements/Icon'; import PollCard from './PollCard'; +import MentionsSpan from '../elements/MentionsSpan'; const sparkCharCount = 250; @@ -112,6 +113,9 @@ const Post = (props) => { className: 'text-sm sm:text-base font-normal', }, }, + span: { + component: MentionsSpan, + }, }, }} > @@ -229,7 +233,7 @@ const Post = (props) => {
diff --git a/src/components/common/elements/MarkdownContent.js b/src/components/common/elements/MarkdownContent.js index dcd2350..d259e6b 100644 --- a/src/components/common/elements/MarkdownContent.js +++ b/src/components/common/elements/MarkdownContent.js @@ -6,19 +6,43 @@ const MarkdownPreview = dynamic( ); import rehypeHighlight from 'rehype-highlight'; import { useTheme } from 'next-themes'; +import Markdown from 'markdown-to-jsx'; +import MentionsSpan from './MentionsSpan'; +import CodeBlock from './CodeBlock'; const MarkdownContent = ({ content }) => { - const { systemTheme, theme } = useTheme(); - const currentTheme = theme === 'system' ? systemTheme : theme; + // const { systemTheme, theme } = useTheme(); + // const currentTheme = theme === 'system' ? systemTheme : theme; return ( - + + > + {content} + ); }; diff --git a/src/components/common/elements/MentionInput.js b/src/components/common/elements/MentionInput.js new file mode 100644 index 0000000..4faeb10 --- /dev/null +++ b/src/components/common/elements/MentionInput.js @@ -0,0 +1,163 @@ +import Image from 'next/image'; +import { useEffect, useState } from 'react'; +import useSWR from 'swr'; +import fetcher from 'utils/fetcher'; + +import { Mention } from 'primereact/mention'; + +const MentionInput = ({ userId, value, onChange, placeholder, name }) => { + const [suggestions, setSuggestions] = useState([]); + + const connectionsURL = `${process.env.BASEURL}/api/connections/get?userId=${userId}`; + const { data: userFollowings, isLoading } = useSWR(connectionsURL, fetcher); + + const mock = { + received_pending: [], + requested_pending: [ + { + _id: '64e81f26151476289a6d9312', + user_id: '3sIelWKe1jgoOIurh7y6hZSLB5r1', + username: 'StefanFMeyer', + picture: + 'https://terrabyte.fra1.digitaloceanspaces.com/avatars/3sIelWKe1jgoOIurh7y6hZSLB5r1/profile-3sIelWKe1jgoOIurh7y6hZSLB5r1-profilepic.jpg', + title: 'Full Stack Developer', + }, + { + _id: '60af58b59ee6390fb10c78ea', + user_id: 'github|70280594', + username: 'PhilipBannonCTO', + picture: 'https://avatars.githubusercontent.com/u/70280594?v=4', + title: 'CTO & Co Founder @ thefullstack', + }, + ], + connections: [ + { + _id: '64c5295b84e21538840497f1', + user_id: 'IS8mj9rvP2ULOQSzErQG2VCnYIP2', + username: 'leighbriody', + picture: + 'https://lh3.googleusercontent.com/a/AGNmyxaVTH2scWGhsWT2DwMHDGB8Ixp66MkFyd6OD18tqQ=s96-c', + title: 'Software Engineer', + }, + { + _id: '6102646565a5b419677b5a0c', + user_id: 'google-oauth2|106215588282051825334', + username: 'henrique', + picture: + 'https://terrabyte.fra1.digitaloceanspaces.com/avatars/google-oauth2%7C106215588282051825334/profile-google-oauth2%7C106215588282051825334-HenriqueProfilePic.jpeg', + title: 'Engineering @thefullstack', + }, + { + _id: '60a79b596e2983725e44a01d', + user_id: 'google-oauth2|110889799112459409416', + username: 'danoely', + picture: + 'https://terrabyte.fra1.digitaloceanspaces.com/avatars/google-oauth2%7C110889799112459409416/profile-google-oauth2%7C110889799112459409416-noel.jpeg', + title: 'Founder, builder, guitarist', + }, + { + _id: '60f5e181259f9c271e7e26ad', + user_id: 'google-oauth2|113946506972373293584', + username: 'jamie', + picture: + 'https://terrabyte.fra1.digitaloceanspaces.com/avatars/google-oauth2%7C113946506972373293584/profile-google-oauth2%7C113946506972373293584-jamwe.png', + title: 'Code Wrangler ', + }, + ], + }.connections.map((con) => { + return { username: con.username, picture: con.picture, title: con.title }; + }); + + const followings = userFollowings?.connections?.map((con) => { + return { username: con.username, picture: con.picture, title: con.title }; + }); + + const onSearch = (event) => { + //in a real application, make a request to a remote url with the query and return suggestions, for demo we filter at client side + setTimeout(() => { + const query = event.query; + let suggestions; + if (!mock) return; + + if (!query.trim().length) { + suggestions = [...mock]; + } else { + suggestions = mock?.filter((user) => { + return user.username.toLowerCase().startsWith(query.toLowerCase()); + }); + } + + setSuggestions(suggestions); + }, 250); + }; + + const itemTemplate = (suggestion) => { + return ( + <> + {isLoading ? ( +
+ Loading... +
+ ) : ( +
+ atr +
+

+ @{suggestion.username} +

+

+ {suggestion?.title} +

+
+
+ )} + + ); + }; + + return ( + onChange(e.target.value)} + suggestions={isLoading ? [1] : suggestions} + onSearch={onSearch} + field="username" + rows={5} + cols={40} + unstyled + itemTemplate={itemTemplate} + /> + //
+ //
+ //
+ //
+ ); +}; + +export default MentionInput; diff --git a/src/components/common/elements/MentionsSpan.js b/src/components/common/elements/MentionsSpan.js new file mode 100644 index 0000000..1c40a1a --- /dev/null +++ b/src/components/common/elements/MentionsSpan.js @@ -0,0 +1,34 @@ +const MentionsSpan = ({ children }) => { + const usernameRegex = /@([^[\]]+)/g; + const parts = children.split(' '); + + const modifiedText = children.replace(usernameRegex, (match, username) => { + // console.log('username: ', match); + // Here, you can construct the element wit the link to '/username' + return {username}; + }); + + const elements = parts.map((part, index) => { + if (part.match(usernameRegex)) { + // This part contains a username, wrap it in an element + const username = part.replace(/\@|\[|\]/g, ''); + return ( + + {part.replace(/\[|\]/g, '')} + + ); + } else { + // This part does not contain a username, return it as is + return <>{part}; + } + }); + + return ( + + {elements.map((ele) => { + return <>{ele} ; + })} + + ); +}; +export default MentionsSpan; diff --git a/src/components/common/modals/ModalAlert.js b/src/components/common/modals/ModalAlert.js index a71ce19..4ffa74c 100644 --- a/src/components/common/modals/ModalAlert.js +++ b/src/components/common/modals/ModalAlert.js @@ -2,7 +2,13 @@ import { Dialog, Transition } from '@headlessui/react'; import { useRef } from 'react'; import Icon from '../elements/Icon'; -const ModalAlert = ({ children, title = false, show, setShow, dimensions }) => { +const ModalAlert = ({ + children, + title = false, + show, + setShow, + dimensions, +}) => { const cancelButtonRef = useRef(null); let modalSize = 'sm:max-w-lg'; if (dimensions) modalSize = dimensions; diff --git a/src/components/modules/comments/EditComment.js b/src/components/modules/comments/EditComment.js index c9906cb..2bc52cc 100644 --- a/src/components/modules/comments/EditComment.js +++ b/src/components/modules/comments/EditComment.js @@ -8,6 +8,7 @@ import { IoLogoMarkdown } from 'react-icons/io5'; import ModalAlert from 'components/common/modals/ModalAlert'; import Icon from 'components/common/elements/Icon'; import SelectEmoji from 'components/common/elements/SelectEmoji'; +import MentionInput from 'components/common/elements/MentionInput'; const EditComment = ({ commentToUpdate, @@ -125,7 +126,14 @@ const EditComment = ({
-
+ + {/*
-
+
*/}
diff --git a/src/components/modules/comments/NewComment.js b/src/components/modules/comments/NewComment.js index da4dda0..7ff6763 100644 --- a/src/components/modules/comments/NewComment.js +++ b/src/components/modules/comments/NewComment.js @@ -1,14 +1,16 @@ import axios from 'axios'; -import { useState } from 'react'; -import dynamic from 'next/dynamic'; -const ReactMde = dynamic(() => import('react-mde'), { ssr: false }); -import * as ga from 'lib/ga'; import Avatar from 'components/common/elements/Avatar'; -import { sendSlackMessage } from 'utils/slack/sendMessageSlack'; -import { IoLogoMarkdown } from 'react-icons/io5'; -import ModalAlert from 'components/common/modals/ModalAlert'; -import SelectEmoji from 'components/common/elements/SelectEmoji'; import Icon from 'components/common/elements/Icon'; +import SelectEmoji from 'components/common/elements/SelectEmoji'; +import ModalAlert from 'components/common/modals/ModalAlert'; +import * as ga from 'lib/ga'; +import dynamic from 'next/dynamic'; +import { useState } from 'react'; +import { IoLogoMarkdown } from 'react-icons/io5'; +import { sendSlackMessage } from 'utils/slack/sendMessageSlack'; +const ReactMde = dynamic(() => import('react-mde'), { ssr: false }); + +import MentionInput from 'components/common/elements/MentionInput'; const NewComment = ({ user, show, setShow, project }) => { const [comment, setComment] = useState(''); @@ -18,72 +20,77 @@ const NewComment = ({ user, show, setShow, project }) => { { preview: 'Type name', value: 'Type name' }, ]); - const MentionListItem = ({ - profilePicUrl, - profileName, - profileCurrentTitle, - }) => { - return ( -
- -
- {profileName} - - {profileCurrentTitle} - -
-
- ); - }; + // .push({ + // id: project.projectCreator.userId, + // display: project.projectCreator.displayName, + // }); - const searchUsers = (term) => { - if (term.length > 1) { - axios - .post( - `${process.env.BASEURL}/api/profile/search`, - JSON.stringify(term), - { - headers: { - 'Content-Type': 'application/json', - }, - } - ) - .then((response) => { - if (response.data.content.length > 0) { - const results = []; - var i; - for (i = 0; i < response.data.content.length; i++) { - results.push({ - preview: ( - - ), - value: `[@${response.data.content[i].displayName}](/${response.data.content[i].displayName})`, - }); - } - setMentionList(results); - } - }); - } - }; + // const MentionListItem = ({ + // profilePicUrl, + // profileName, + // profileCurrentTitle, + // }) => { + // return ( + //
+ // + //
+ // {profileName} + // + // {profileCurrentTitle} + // + //
+ //
+ // ); + // }; - const loadSuggestions = (text) => { - return new Promise((accept, reject) => { - setTimeout(() => { - searchUsers(text); + // const searchUsers = (term) => { + // if (term.length > 1) { + // axios + // .post( + // `${process.env.BASEURL}/api/profile/search`, + // JSON.stringify(term), + // { + // headers: { + // 'Content-Type': 'application/json', + // }, + // } + // ) + // .then((response) => { + // if (response.data.content.length > 0) { + // const results = []; + // var i; + // for (i = 0; i < response.data.content.length; i++) { + // results.push({ + // preview: ( + // + // ), + // value: `[@${response.data.content[i].displayName}](/${response.data.content[i].displayName})`, + // }); + // } + // setMentionList(results); + // } + // }); + // } + // }; - mentionList.filter((i) => - i.value.toLowerCase().includes(text.toLowerCase()) - ); + // const loadSuggestions = (text) => { + // return new Promise((accept, reject) => { + // setTimeout(() => { + // searchUsers(text); - accept(mentionList); - reject(mentionList); - }, 100); - }); - }; + // mentionList.filter((i) => + // i.value.toLowerCase().includes(text.toLowerCase()) + // ); + + // accept(mentionList); + // reject(mentionList); + // }, 100); + // }); + // }; const handlePostComment = async () => { if (!comment?.trim().length) { @@ -123,23 +130,13 @@ const NewComment = ({ user, show, setShow, project }) => {
-
- +
diff --git a/src/components/modules/comments/ReplyToComment.js b/src/components/modules/comments/ReplyToComment.js index 568497c..4f1b7de 100644 --- a/src/components/modules/comments/ReplyToComment.js +++ b/src/components/modules/comments/ReplyToComment.js @@ -11,6 +11,7 @@ import { IoLogoMarkdown } from 'react-icons/io5'; import ModalAlert from 'components/common/modals/ModalAlert'; import Icon from 'components/common/elements/Icon'; import SelectEmoji from 'components/common/elements/SelectEmoji'; +import MentionInput from 'components/common/elements/MentionInput'; const ReplyToComment = ({ commentReplyTo, @@ -176,23 +177,13 @@ const ReplyToComment = ({
-
- -
+
diff --git a/src/components/modules/hangout/CreatePost.js b/src/components/modules/hangout/CreatePost.js index 9f0b153..f0094f6 100644 --- a/src/components/modules/hangout/CreatePost.js +++ b/src/components/modules/hangout/CreatePost.js @@ -1,20 +1,22 @@ -import React, { useEffect, useState } from 'react'; import axios from 'axios'; -import { useRouter } from 'next/router'; -import { sendSlackMessage } from 'utils/slack/sendMessageSlack'; -import TextareaAutosize from 'react-textarea-autosize'; -import Loader from 'components/common/elements/Loader'; -import { CgSpinner } from 'react-icons/cg'; -import { FiSend } from 'react-icons/fi'; -import { IoTrashOutline } from 'react-icons/io5'; -import TagStack from 'components/common/tags/TagStack'; import Avatar from 'components/common/elements/Avatar'; import Icon from 'components/common/elements/Icon'; +import Loader from 'components/common/elements/Loader'; import ToolTip from 'components/common/elements/ToolTip'; -import TagPostType from 'components/common/tags/TagPostType'; -import { topics } from './constants'; import ModalAlert from 'components/common/modals/ModalAlert'; +import TagPostType from 'components/common/tags/TagPostType'; +import TagStack from 'components/common/tags/TagStack'; +import { useRouter } from 'next/router'; +import { useEffect, useRef, useState } from 'react'; +import { CgSpinner } from 'react-icons/cg'; +import { FiSend } from 'react-icons/fi'; +import { IoTrashOutline } from 'react-icons/io5'; +import TextareaAutosize from 'react-textarea-autosize'; +import { sendSlackMessage } from 'utils/slack/sendMessageSlack'; import TagTechStack from './TagTechStack'; +import { topics } from './constants'; + +import MentionInput from 'components/common/elements/MentionInput'; const sparkCharCount = 300; const initialPollOptions = ['', '']; @@ -168,7 +170,7 @@ const CreatePost = ({ user }) => { dimensions={'w-10 h-10 mt-2'} />
-
+
{postType !== 'SPARK' && (
)} - { - setPostBody(e.target.value); - }} />
diff --git a/src/components/modules/post/Content.js b/src/components/modules/post/Content.js index 1eb3b81..f67e8e5 100644 --- a/src/components/modules/post/Content.js +++ b/src/components/modules/post/Content.js @@ -11,6 +11,7 @@ import OpenGraphPreview from 'components/modules/post/OpenGraphPreview'; import Avatar from 'components/common/elements/Avatar'; import TagPostType from 'components/common/tags/TagPostType'; import Poll from './Poll'; +import MentionsSpan from 'components/common/elements/MentionsSpan'; const sparkCharCount = 300; @@ -102,6 +103,9 @@ const Content = ({ pre: { component: CodeBlock, }, + span: { + component: MentionsSpan, + }, a: { props: { className: 'break-all text-left',