Markdown support in forums

This commit is contained in:
2024-08-13 14:16:02 +08:00
parent de3343e120
commit 9f5a6a94e8
4 changed files with 54 additions and 32 deletions

View File

@@ -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",

View File

@@ -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>
)}

View File

@@ -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">

View File

@@ -9,6 +9,7 @@ export default {
],
darkMode: "class",
plugins: [
require("@tailwindcss/typography"),
nextui({
themes: {
"red-dark": {