diff --git a/.gitignore b/.gitignore index 49c59d0..fe0c4e7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ /out-tsc # dependencies -/node_modules +node_modules # IDEs and editors /.idea diff --git a/apps/blueprints/prisma/migrations/20210422130800_add_comments/migration.sql b/apps/blueprints/prisma/migrations/20210422130800_add_comments/migration.sql new file mode 100644 index 0000000..94c41e2 --- /dev/null +++ b/apps/blueprints/prisma/migrations/20210422130800_add_comments/migration.sql @@ -0,0 +1,21 @@ +-- CreateTable +CREATE TABLE "comment" ( + "id" UUID NOT NULL, + "blueprint_page_id" UUID NOT NULL, + "user_id" UUID NOT NULL, + "body" TEXT NOT NULL, + "reply_comment_id" UUID, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "comment" ADD FOREIGN KEY ("blueprint_page_id") REFERENCES "blueprint_page"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "comment" ADD FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "comment" ADD FOREIGN KEY ("reply_comment_id") REFERENCES "comment"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/apps/blueprints/prisma/schema.prisma b/apps/blueprints/prisma/schema.prisma index e39a899..f1a9901 100644 --- a/apps/blueprints/prisma/schema.prisma +++ b/apps/blueprints/prisma/schema.prisma @@ -16,7 +16,7 @@ enum enum_user_role { model blueprint { id String @id @default(uuid()) @db.Uuid label String? @db.VarChar(255) - description String? + description String? @db.Text game_version String? @db.VarChar(255) blueprint_hash String @unique @db.VarChar(40) image_hash String @db.VarChar(40) @@ -32,7 +32,7 @@ model blueprint { model blueprint_book { id String @id @default(uuid()) @db.Uuid label String? @db.VarChar(255) - description String? + description String? @db.Text child_tree Json @db.JsonB blueprint_hash String @unique @db.VarChar(40) is_modded Boolean @@ -51,7 +51,7 @@ model blueprint_page { blueprint_book_id String? @unique @db.Uuid blueprint_ids String[] @db.Uuid title String @db.VarChar(255) - description_markdown String? + description_markdown String? @db.Text tags String[] @db.VarChar(255) image_hash String @db.VarChar(40) factorioprints_id String? @unique @db.VarChar(255) @@ -61,6 +61,7 @@ model blueprint_page { blueprint blueprint? @relation(fields: [blueprint_id], references: [id]) user_favorites user_favorites[] user user? @relation(fields: [user_id], references: [id]) + comments comment[] } model session { @@ -94,6 +95,7 @@ model user { session session[] user_favorites user_favorites[] blueprint_pages blueprint_page[] + comment comment[] } model user_favorites { @@ -107,6 +109,20 @@ model user_favorites { @@id([user_id, blueprint_page_id]) } +model comment { + id String @id @default(uuid()) @db.Uuid + blueprint_page_id String @db.Uuid + user_id String @db.Uuid + body String @db.Text + reply_comment_id String? @db.Uuid + created_at DateTime @default(now()) + updated_at DateTime @updatedAt + blueprint_page blueprint_page @relation(fields: [blueprint_page_id], references: [id]) + user user @relation(fields: [user_id], references: [id]) + reply_to comment? @relation("commentToComment", fields: [reply_comment_id], references: [id]) + replies comment[] @relation("commentToComment") +} + model blueprint_entities { entity String @unique } diff --git a/apps/blueprints/src/components/Comments.tsx b/apps/blueprints/src/components/Comments.tsx new file mode 100644 index 0000000..19954e6 --- /dev/null +++ b/apps/blueprints/src/components/Comments.tsx @@ -0,0 +1,114 @@ +import { FormEventHandler, useEffect, useState } from "react"; +import { CommentWithUsername } from "@factorio-sites/types"; +import { useAuth } from "../providers/auth"; +import { Button } from "./Button"; +import styled from "@emotion/styled"; +import { format } from "date-fns"; +import { getLocaleDateFormat } from "@factorio-sites/web-utils"; + +interface CommentsProps { + blueprint_page_id: string; +} + +const AddCommentDiv = styled.div` + border-bottom: 1px solid #ccc; + padding-bottom: 1rem; + margin-bottom: 1rem; + + textarea { + color: #fff; + display: block; + margin-top: 0.5rem; + background: #414040; + border: 1px solid #ddd; + border-radius: 4px; + width: 400px; + min-height: 80px; + } + + button { + margin-top: 0.5rem; + } + .close { + margin-left: 1rem; + } +`; + +const CommentDiv = styled.div` + background: #4e4c4c; + margin: 0.5rem 0; +`; + +export const Comments: React.FC = ({ blueprint_page_id }) => { + const auth = useAuth(); + const [addCommentOpen, setAddCommentOpen] = useState(false); + const [comments, setComments] = useState([]); + const [commentBody, setCommentBody] = useState(""); + + const fetchTopLevelComments = async () => { + const result = await fetch(`/api/blueprint/comments?blueprint_page_id=${blueprint_page_id}`); + const body = await result.json(); + setComments(body.comments); + }; + + useEffect(() => { + fetchTopLevelComments(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + console.log({ comments }); + + const onSubmitComment: FormEventHandler = async (event) => { + event.preventDefault(); + const result = await fetch("/api/blueprint/comment", { + method: "POST", + body: JSON.stringify({ blueprint_page_id, body: commentBody }), + headers: { + "Content-Type": "application/json", + }, + }); + setCommentBody(""); + setAddCommentOpen(false); + console.log("result", await result.json()); + fetchTopLevelComments(); + }; + + return ( +
+ {auth && ( + + {addCommentOpen ? ( +
+
Add a new comment
+