working comments with cache updates
This commit is contained in:
parent
95d6d789fa
commit
6792d1d5ff
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "attach",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"port": 9229,
|
||||
"outputCapture": "std"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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!]!
|
||||
}
|
||||
`
|
||||
|
|
|
@ -95,13 +95,15 @@ export default function Comment ({ item, children, replyOpen, includeParent }) {
|
|||
>
|
||||
{reply ? 'cancel' : 'reply'}
|
||||
</div>
|
||||
{reply && <Reply parentId={item.id} />}
|
||||
{reply && <Reply item={item} />}
|
||||
{children}
|
||||
{item.comments
|
||||
? item.comments.map((item) => (
|
||||
<Comment key={item.id} item={item} />
|
||||
))
|
||||
: null}
|
||||
<div className={styles.comments}>
|
||||
{item.comments
|
||||
? item.comments.map((item) => (
|
||||
<Comment key={item.id} item={item} />
|
||||
))
|
||||
: null}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -18,4 +18,9 @@
|
|||
|
||||
.children {
|
||||
margin-top: .4rem;
|
||||
}
|
||||
|
||||
.comments {
|
||||
margin-left: 16px;
|
||||
margin-top: .5rem;
|
||||
}
|
|
@ -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 (
|
||||
<div className='mt-5'>
|
||||
{data.comments.map(item => (
|
||||
<div
|
||||
key={item.id} className='mt-2'
|
||||
style={{ marginLeft: `${42 * (item.depth - baseDepth - 1)}px` }}
|
||||
>
|
||||
<div key={item.id} className='mt-2'>
|
||||
<Comment item={item} />
|
||||
</div>
|
||||
))}
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
|
@ -43,4 +43,4 @@
|
|||
"prisma": "2.19.0",
|
||||
"standard": "^16.0.3"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ export async function getServerSideProps ({ params }) {
|
|||
user {
|
||||
name
|
||||
}
|
||||
depth
|
||||
sats
|
||||
ncomments
|
||||
}
|
||||
|
@ -50,11 +49,11 @@ export default function FullItem ({ item }) {
|
|||
<>
|
||||
<Item item={item}>
|
||||
{item.text && <Text>{item.text}</Text>}
|
||||
<Reply parentId={item.id} />
|
||||
<Reply item={item} />
|
||||
</Item>
|
||||
</>
|
||||
)}
|
||||
<Comments parentId={item.id} baseDepth={item.depth} />
|
||||
<Comments parentId={item.id} />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue