Markdown support in forums
This commit is contained in:
@@ -22,10 +22,13 @@
|
||||
"react-chartjs-2": "^5.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"yup": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.14",
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
||||
|
||||
@@ -30,7 +30,8 @@ import {
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { retrieveUserInformationById } from "../security/usersbyid";
|
||||
import { retrieveUserInformation } from "../security/users";
|
||||
// import UserPostImage from "../components/UserPostImage";
|
||||
import Markdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
|
||||
interface Post {
|
||||
title: string;
|
||||
@@ -58,8 +59,12 @@ export default function CommunityPage() {
|
||||
const [selectedPost, setSelectedPost] = useState<Post | null>(null);
|
||||
const [communityList, setCommunityList] = useState<Post[]>([]);
|
||||
const [search, setSearch] = useState(""); // Search Function
|
||||
const [userInformation, setUserInformation] = useState<Record<string, User>>({});
|
||||
const [imageErrorFlags, setImageErrorFlags] = useState<Record<string, boolean>>({});
|
||||
const [userInformation, setUserInformation] = useState<Record<string, User>>(
|
||||
{}
|
||||
);
|
||||
const [imageErrorFlags, setImageErrorFlags] = useState<
|
||||
Record<string, boolean>
|
||||
>({});
|
||||
const [tags, setTags] = useState<Tag[]>([]);
|
||||
const [selectedTag, setSelectedTag] = useState<string | null>(null);
|
||||
const [currentUserId, setCurrentUserId] = useState<string | null>(null);
|
||||
@@ -147,7 +152,7 @@ export default function CommunityPage() {
|
||||
const getCurrentUserInformation = async () => {
|
||||
try {
|
||||
const user = await retrieveUserInformation(); // Get the user information
|
||||
console.log(user)
|
||||
console.log(user);
|
||||
setCurrentUserId(user.id); // Store user ID
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@@ -291,14 +296,17 @@ export default function CommunityPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p>{post.content}</p>
|
||||
<Markdown className="prose" remarkPlugins={[remarkGfm]}>
|
||||
{post.content}
|
||||
</Markdown>
|
||||
</div>
|
||||
{imageErrorFlags[post.id] ? null : (
|
||||
<div>
|
||||
<img
|
||||
src={`${config.serverAddress}/post/post-image/${post.id}`}
|
||||
className="w-[300px] h-auto rounded-lg object-cover"
|
||||
onError={() => handleImageError(post.id)} />
|
||||
onError={() => handleImageError(post.id)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -362,7 +370,9 @@ export default function CommunityPage() {
|
||||
<Chip
|
||||
key={tag.id}
|
||||
onClick={() => handleTagClick(tag.tag)}
|
||||
className={selectedTag === tag.tag ? "bg-primary-500 text-white" : ""}
|
||||
className={
|
||||
selectedTag === tag.tag ? "bg-primary-500 text-white" : ""
|
||||
}
|
||||
>
|
||||
{tag.tag}
|
||||
</Chip>
|
||||
@@ -370,10 +380,7 @@ export default function CommunityPage() {
|
||||
</div>
|
||||
<div>
|
||||
{selectedTag && (
|
||||
<Button
|
||||
className="mt-2"
|
||||
onPress={handleClearFilter}
|
||||
>
|
||||
<Button className="mt-2" onPress={handleClearFilter}>
|
||||
Clear Filter
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -28,6 +28,8 @@ import { retrieveUserInformationById } from "../security/usersbyid";
|
||||
import CommentInputModule from "../components/CommentInputModule";
|
||||
import CommentsModule from "../components/CommentsModule";
|
||||
import { retrieveUserInformation } from "../security/users";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import Markdown from "react-markdown";
|
||||
|
||||
interface Post {
|
||||
title: string;
|
||||
@@ -55,14 +57,19 @@ const PostPage: React.FC = () => {
|
||||
const [post, setPost] = useState<Post | null>(null);
|
||||
const { isOpen, onOpen, onOpenChange } = useDisclosure();
|
||||
const [selectedPost, setSelectedPost] = useState<Post | null>(null);
|
||||
const [userInformation, setUserInformation] = useState<Record<string, User>>({});
|
||||
const [imageErrorFlags, setImageErrorFlags] = useState<Record<string, boolean>>({});
|
||||
const [userInformation, setUserInformation] = useState<Record<string, User>>(
|
||||
{}
|
||||
);
|
||||
const [imageErrorFlags, setImageErrorFlags] = useState<
|
||||
Record<string, boolean>
|
||||
>({});
|
||||
const [currentUserId, setCurrentUserId] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
console.log("useEffect for fetching post called, id:", id);
|
||||
instance.get(`${config.serverAddress}/post/${id}`)
|
||||
instance
|
||||
.get(`${config.serverAddress}/post/${id}`)
|
||||
.then((res) => {
|
||||
setPost(res.data);
|
||||
console.log("Post fetch successfully");
|
||||
@@ -97,7 +104,7 @@ const PostPage: React.FC = () => {
|
||||
const getCurrentUserInformation = async () => {
|
||||
try {
|
||||
const user = await retrieveUserInformation(); // Get the user information
|
||||
console.log(user)
|
||||
console.log(user);
|
||||
setCurrentUserId(user.id); // Store user ID
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@@ -169,23 +176,22 @@ const PostPage: React.FC = () => {
|
||||
key={post.id}
|
||||
>
|
||||
<div>
|
||||
<Avatar
|
||||
src={profilePictureUrl}
|
||||
size="lg"
|
||||
/>
|
||||
<Avatar src={profilePictureUrl} size="lg" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-8 w-full">
|
||||
<div className="h-full flex flex-col gap-4">
|
||||
<div className="flex flex-row justify-between">
|
||||
<div className="flex flex-col">
|
||||
<p className="text-xl font-bold">{post.title}</p>
|
||||
<p className="text-md text-neutral-500">{userInformation[post.userId]?.firstName} {userInformation[post.userId]?.lastName}</p>
|
||||
<p className="text-md text-neutral-500">
|
||||
{userInformation[post.userId]?.firstName}{" "}
|
||||
{userInformation[post.userId]?.lastName}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-row-reverse justify-center items-center">
|
||||
{currentUserId === post.userId && ( // Check if the current user is the post author
|
||||
<Dropdown>
|
||||
<DropdownTrigger
|
||||
className="justify-center items-center">
|
||||
<DropdownTrigger className="justify-center items-center">
|
||||
<Button isIconOnly variant="light">
|
||||
<EllipsisHorizontalIcon />
|
||||
</Button>
|
||||
@@ -215,17 +221,22 @@ const PostPage: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p>{post.content}</p>
|
||||
<Markdown className="prose" remarkPlugins={[remarkGfm]}>
|
||||
{post.content}
|
||||
</Markdown>
|
||||
</div>
|
||||
{!imageErrorFlags[post.id] && post.postImage && post.postImage !== null && (
|
||||
<div>
|
||||
<img
|
||||
src={`${config.serverAddress}/post/post-image/${post.id}`}
|
||||
alt="PostImage"
|
||||
className="w-[300px] h-auto rounded-lg object-cover"
|
||||
onError={() => handleImageError(post.id)} />
|
||||
</div>
|
||||
)}
|
||||
{!imageErrorFlags[post.id] &&
|
||||
post.postImage &&
|
||||
post.postImage !== null && (
|
||||
<div>
|
||||
<img
|
||||
src={`${config.serverAddress}/post/post-image/${post.id}`}
|
||||
alt="PostImage"
|
||||
className="w-[300px] h-auto rounded-lg object-cover"
|
||||
onError={() => handleImageError(post.id)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex flex-row gap-2">
|
||||
|
||||
@@ -9,6 +9,7 @@ export default {
|
||||
],
|
||||
darkMode: "class",
|
||||
plugins: [
|
||||
require("@tailwindcss/typography"),
|
||||
nextui({
|
||||
themes: {
|
||||
"red-dark": {
|
||||
|
||||
Reference in New Issue
Block a user