added comment functionality

This commit is contained in:
Juthatip McDevitt 2024-03-30 14:50:38 -05:00
parent 86b9427bd6
commit 389771d33f
7 changed files with 1211 additions and 18 deletions

File diff suppressed because it is too large Load diff

View file

@ -13,6 +13,7 @@
"@liveblocks/client": "^1.11.0",
"@liveblocks/node": "^1.11.0",
"@liveblocks/react": "^1.11.0",
"@liveblocks/react-comments": "^1.11.0",
"@liveblocks/yjs": "^1.11.0",
"@tailwindcss/forms": "^0.5.7",
"@tiptap/extension-collaboration": "^2.2.4",
@ -23,6 +24,7 @@
"@tiptap/react": "^2.2.4",
"@tiptap/starter-kit": "^2.2.4",
"mongodb": "^6.5.0",
"mongoose": "^8.2.4",
"next": "14.1.4",
"next-auth": "^4.24.7",
"react": "^18",

View file

@ -0,0 +1,24 @@
import { User, UserType } from "@/models/User";
import mongoose from "mongoose";
import { NextRequest } from "next/server";
export async function GET(req: NextRequest){
const url = new URL(req.url);
const connectionString = process.env.MONGODB_URI
if(!connectionString){
return new Response('No db connection string', {status:500});
}
if(!url.searchParams.has('ids')){
return Response.json([])
}
const emails = url.searchParams.getAll('ids');
await mongoose.connect(connectionString)
const users = await User.find({email: emails});
return Response.json(users.map((u:UserType) => ({
id:u.email,
name:u.name,
image:u.image
})));
}

View file

@ -3,9 +3,8 @@
@tailwind utilities;
body{}
button[type="button"], button[type="submit"], button.primary{
@apply bg-[#164863] text-white p-2 text-sm font-semibold rounded-md
@apply bg-[#164863] text-white p-2 text-sm font-semibold rounded-md flex
}
button[type="submit"], button.primary{
@apply bg-[#427D9D] rounded-md

View file

@ -1,9 +1,15 @@
import { LiveList, LiveObject, createClient } from "@liveblocks/client";
import { LiveList, LiveObject, ThreadData, createClient } from "@liveblocks/client";
import { createRoomContext } from "@liveblocks/react";
const client = createClient({
authEndpoint: "/api/liveblocks-auth",
throttle: 100,
resolveUsers: async ({userIds}) => {
const params = new URLSearchParams(userIds.map(id => ['ids', id]));
const response = await fetch(`/api/users?` + params.toString());
return await response.json();
},
});
type Presence = {
@ -28,6 +34,23 @@ type Storage = {
cards: LiveList<LiveObject<Card>>;
};
type UserMeta = {
id: string;
info: {
name: string;
email: string;
image: string;
}
};
type RoomEvent = {};
type ThreadMetadata = {
cardId: string;
};
export const {
RoomProvider,
@ -37,9 +60,28 @@ export const {
useRoom,
useSelf,
useOthers,
useThreads,
/* ...all the other hooks youre using... */
} = createRoomContext<
Presence,
Storage
/* UserMeta, RoomEvent, ThreadMetadata */
>(client);
Storage,
UserMeta,
RoomEvent,
ThreadMetadata
>(client, {
/*resolveUsers: async ({userIds}) => {
const params = new URLSearchParams(userIds.map(id => ['ids', id]));
const response = await fetch(`/api/users?` + params.toString());
return await response.json();
},
Upgrading to 1.10 instead of putting this in createRoomContext --> move to createClient
*/
});

View file

@ -2,12 +2,15 @@
import { useParams, useRouter } from "next/navigation"
import { FormEvent, useContext, useEffect, useState } from "react";
import { BoardContext, BoardContextProps } from "../BoardContext";
import { Card, useMutation, useStorage } from "@/app/liveblocks.config";
import { Card, useMutation, useStorage, useThreads } from "@/app/liveblocks.config";
import { shallow } from "@liveblocks/client";
import { BsThreeDots } from "react-icons/bs";
import DeleteConfirmation from "../DeleteConfirmation";
import { IoDocumentTextOutline } from "react-icons/io5";
import { FaRegCommentDots } from "react-icons/fa6";
import CardDesc from "../CardDesc";
import { Composer, Thread } from "@liveblocks/react-comments";
import "@liveblocks/react-comments/styles.css";
@ -15,6 +18,14 @@ import CardDesc from "../CardDesc";
const CardModal = () => {
const router = useRouter();
const params = useParams();
const {threads} = useThreads({
query:{
metadata:{
cardId:params.cardId?.toString(),
}
}
});
const {setOpenCard} = useContext<BoardContextProps>(BoardContext);
const [editCard, setEditCard] = useState(false);
@ -69,7 +80,7 @@ const CardModal = () => {
return (
<div onClick={handleBackdrop} className='fixed inset-0 bg-black/80'>
<div onClick={ev => ev.stopPropagation()} className='bg-white p-4 mt-8 max-w-xs mx-auto'>
<div onClick={ev => ev.stopPropagation()} className='bg-white p-4 mt-8 max-w-sm mx-auto'>
{!editCard && (
<div className="flex justify-between">
<p className="mb-6 uppercase text-sm font-semibold">{card?.name}</p>
@ -80,7 +91,7 @@ const CardModal = () => {
<div>
<form onSubmit={handleCardNamechange} className="flex flex-col">
<input type="text" defaultValue={card?.name} className="mb-4 border p-2 rounded-md"/>
<button type="submit" className="uppercase">save</button>
<button type="submit" className="uppercase w-full flex text-center justify-center itemc">save</button>
</form>
<div>
<DeleteConfirmation onDelete={() => handleDelete()}/>
@ -88,9 +99,23 @@ const CardModal = () => {
</div>
)}
{!editCard && (
<div >
<div>
<h3 className="flex items-center"><IoDocumentTextOutline/> Description</h3>
<CardDesc/>
<h3 className="flex items-center mt-4"><FaRegCommentDots/> Comments</h3>
<div className="mt-4">
{threads && threads.map(thread => (
<div key={thread.id}>
<Thread thread={thread} id={thread.id}/>
</div>
))}
{threads?.length === 0 && (
<div>
<Composer metadata={{cardId:params.cardId.toString()}}/>
</div>
)}
</div>
</div>
)}
</div>

View file

@ -0,0 +1,21 @@
import {Schema, models, model} from 'mongoose'
type ModelType = {
User: any;
};
export type UserType = {
name: string;
email: string;
image: string;
}
const userSchema = new Schema({
name: String,
email: String,
image: String,
emailVerified: Date,
});
export const User = (models as ModelType)?.User || model('User', userSchema);