added comment functionality
This commit is contained in:
parent
86b9427bd6
commit
389771d33f
7 changed files with 1211 additions and 18 deletions
1096
task_management_app/package-lock.json
generated
1096
task_management_app/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -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",
|
||||
|
|
24
task_management_app/src/app/api/users/route.ts
Normal file
24
task_management_app/src/app/api/users/route.ts
Normal 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
|
||||
})));
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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 you’re 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
|
||||
|
||||
|
||||
|
||||
*/
|
||||
});
|
|
@ -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>
|
||||
|
|
21
task_management_app/src/models/User.ts
Normal file
21
task_management_app/src/models/User.ts
Normal 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);
|
Loading…
Add table
Reference in a new issue