From 6792d1d5ffb043572feca51124fe0163bde1a599 Mon Sep 17 00:00:00 2001 From: keyan Date: Sat, 17 Apr 2021 13:15:18 -0500 Subject: [PATCH] working comments with cache updates --- .vscode/launch.json | 15 +++++++ api/resolvers/item.js | 81 ++++++++++++++++++++++++++++++++++- api/typeDefs/item.js | 2 + components/comment.js | 14 +++--- components/comment.module.css | 5 +++ components/comments.js | 23 ++++------ components/reply.js | 28 ++++++++++-- fragments/index.js | 55 ++++++++++++++++++++++++ package.json | 2 +- pages/items/[id].js | 5 +-- 10 files changed, 200 insertions(+), 30 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 fragments/index.js diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..0dbddc5e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "pwa-node", + "request": "attach", + "name": "Launch Program", + "skipFiles": [ + "/**" + ], + "port": 9229, + "outputCapture": "std" + } + ] +} \ No newline at end of file diff --git a/api/resolvers/item.js b/api/resolvers/item.js index 760f3839..611e6eec 100644 --- a/api/resolvers/item.js +++ b/api/resolvers/item.js @@ -24,7 +24,75 @@ const createItem = async (parent, { title, text, url, parentId }, { me, models } } } - return await models.item.create({ data }) + const item = await models.item.create({ data }) + item.comments = [] + console.log(item) + return item +} + +// function nestComments (flat, parentId) { +// const result = [] +// for (let i = 0; i < flat.length; i++) { +// if (Number(flat[i].parentId) === Number(parentId)) { +// result.push(flat[i]) +// } else if (result.length > 0) { +// // this comment is a child of the last one pushed +// const last = result[result.length - 1] +// last.comments = nestComments(flat.slice(i), last.id) + +// // we consumed this many comments +// i += last.comments.length +// } +// } + +// return result +// } + +// function nestComments (flat, parentId) { +// const result = [] +// let last +// for (let i = 0; i < flat.length; i++) { +// // initialize all comments +// if (!flat[i].comments) flat[i].comments = [] + +// if (Number(flat[i].parentId) === Number(parentId)) { +// result.push(flat[i]) +// last = flat[i] +// } else if (last && Number(last.id) === flat[i].parentId) { +// const nested = nestComments(flat.slice(i), last.id) +// if (nested.length > 0) { +// last.comments.push(...nested) +// i += nested.length - 1 +// } +// } +// } + +// return result +// } + +function nestComments (flat, parentId) { + const result = [] + let added = 0 + for (let i = 0; i < flat.length;) { + if (!flat[i].comments) flat[i].comments = [] + if (Number(flat[i].parentId) === Number(parentId)) { + result.push(flat[i]) + added++ + i++ + } else if (result.length > 0) { + const item = result[result.length - 1] + const [nested, newAdded] = nestComments(flat.slice(i), item.id) + if (newAdded === 0) { + break + } + item.comments.push(...nested) + i += newAdded + added += newAdded + } else { + break + } + } + return [result, added] } export default { @@ -44,7 +112,7 @@ export default { WHERE id = ${id}`) return res.length ? res[0] : null }, - comments: async (parent, { parentId }, { models }) => { + flatcomments: async (parent, { parentId }, { models }) => { return await models.$queryRaw(` SELECT id, "created_at" as "createdAt", text, "parentId", "userId", nlevel(path)-1 AS depth, ltree2text("path") AS "path" @@ -52,6 +120,15 @@ export default { WHERE path <@ (SELECT path FROM "Item" where id = ${parentId}) AND id != ${parentId} ORDER BY "path"`) }, + comments: async (parent, { parentId }, { models }) => { + const flat = await models.$queryRaw(` + SELECT id, "created_at" as "createdAt", text, "parentId", + "userId", nlevel(path)-1 AS depth, ltree2text("path") AS "path" + FROM "Item" + WHERE path <@ (SELECT path FROM "Item" where id = ${parentId}) AND id != ${parentId} + ORDER BY "path"`) + return nestComments(flat, parentId)[0] + }, root: async (parent, { id }, { models }) => { const res = await models.$queryRaw(` SELECT id, title diff --git a/api/typeDefs/item.js b/api/typeDefs/item.js index 9124f731..ec8d3bd5 100644 --- a/api/typeDefs/item.js +++ b/api/typeDefs/item.js @@ -5,6 +5,7 @@ export default gql` items: [Item!]! item(id: ID!): Item comments(parentId: ID!): [Item!]! + flatcomments(parentId: ID!): [Item!]! root(id: ID!): Item } @@ -25,5 +26,6 @@ export default gql` depth: Int! sats: Int! ncomments: Int! + comments: [Item!]! } ` diff --git a/components/comment.js b/components/comment.js index a587442d..84c33295 100644 --- a/components/comment.js +++ b/components/comment.js @@ -95,13 +95,15 @@ export default function Comment ({ item, children, replyOpen, includeParent }) { > {reply ? 'cancel' : 'reply'} - {reply && } + {reply && } {children} - {item.comments - ? item.comments.map((item) => ( - - )) - : null} +
+ {item.comments + ? item.comments.map((item) => ( + + )) + : null} +
) diff --git a/components/comment.module.css b/components/comment.module.css index 9064d16d..6672de8a 100644 --- a/components/comment.module.css +++ b/components/comment.module.css @@ -18,4 +18,9 @@ .children { margin-top: .4rem; +} + +.comments { + margin-left: 16px; + margin-top: .5rem; } \ No newline at end of file diff --git a/components/comments.js b/components/comments.js index b60a1753..ee0b54ed 100644 --- a/components/comments.js +++ b/components/comments.js @@ -1,19 +1,15 @@ import { useQuery, gql } from '@apollo/client' import Comment from './comment' +import { COMMENTS } from '../fragments' -export default function Comments ({ parentId, baseDepth }) { +export default function Comments ({ parentId }) { const { data } = useQuery( - gql`{ + gql` + ${COMMENTS} + + { comments(parentId: ${parentId}) { - id - createdAt - text - user { - name - } - depth - sats - ncomments + ...CommentsRecursive } }` ) @@ -23,10 +19,7 @@ export default function Comments ({ parentId, baseDepth }) { return (
{data.comments.map(item => ( -
+
))} diff --git a/components/reply.js b/components/reply.js index 2e572296..a98bb22a 100644 --- a/components/reply.js +++ b/components/reply.js @@ -2,19 +2,41 @@ import { Form, Input, SubmitButton } from '../components/form' import * as Yup from 'yup' import { gql, useMutation } from '@apollo/client' import styles from './reply.module.css' +import { COMMENTS } from '../fragments' export const CommentSchema = Yup.object({ text: Yup.string().required('required').trim() }) -export default function Reply ({ parentId }) { +export default function Reply ({ item }) { + const parentId = item.id const [createComment] = useMutation( gql` + ${COMMENTS} mutation createComment($text: String!, $parentId: ID!) { createComment(text: $text, parentId: $parentId) { - id + ...CommentFields + comments { + ...CommentsRecursive + } } - }` + }`, { + update (cache, { data: { createComment } }) { + cache.modify({ + id: `Item:${item.id}`, + fields: { + comments (existingCommentRefs = [], { readField }) { + const newCommentRef = cache.writeFragment({ + data: createComment, + fragment: COMMENTS, + fragmentName: 'CommentsRecursive' + }) + return [newCommentRef, ...existingCommentRefs] + } + } + }) + } + } ) return ( diff --git a/fragments/index.js b/fragments/index.js new file mode 100644 index 00000000..d6c0deb0 --- /dev/null +++ b/fragments/index.js @@ -0,0 +1,55 @@ +import { gql } from '@apollo/client' + +export const COMMENT_FIELDS = gql` + fragment CommentFields on Item { + id + parentId + createdAt + text + user { + name + } + sats + ncomments + } +` + +export const COMMENTS = gql` + ${COMMENT_FIELDS} + + fragment CommentsRecursive on Item { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + comments { + ...CommentFields + } + } + } + } + } + } + } + } + } + } + } + }` diff --git a/package.json b/package.json index d7bccc1e..f6137c35 100644 --- a/package.json +++ b/package.json @@ -43,4 +43,4 @@ "prisma": "2.19.0", "standard": "^16.0.3" } -} +} \ No newline at end of file diff --git a/pages/items/[id].js b/pages/items/[id].js index 91f1da21..618a7904 100644 --- a/pages/items/[id].js +++ b/pages/items/[id].js @@ -21,7 +21,6 @@ export async function getServerSideProps ({ params }) { user { name } - depth sats ncomments } @@ -50,11 +49,11 @@ export default function FullItem ({ item }) { <> {item.text && {item.text}} - + )} - + ) }