comment sorting
This commit is contained in:
parent
f6b1da64f9
commit
0dfda596b0
@ -5,18 +5,35 @@ import { decodeCursor, LIMIT, nextCursorEncoded } from '../../lib/cursor'
|
|||||||
import { getMetadata, metadataRuleSets } from 'page-metadata-parser'
|
import { getMetadata, metadataRuleSets } from 'page-metadata-parser'
|
||||||
import domino from 'domino'
|
import domino from 'domino'
|
||||||
|
|
||||||
async function comments (models, id) {
|
async function comments (models, id, sort) {
|
||||||
|
let orderBy
|
||||||
|
let join
|
||||||
|
switch (sort) {
|
||||||
|
case 'top':
|
||||||
|
orderBy = 'ORDER BY x.sats DESC NULLS LAST'
|
||||||
|
join = LEFT_JOIN_SATS
|
||||||
|
break
|
||||||
|
case 'recent':
|
||||||
|
orderBy = 'ORDER BY "Item".created_at DESC'
|
||||||
|
join = ''
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
orderBy = ORDER_BY_SATS
|
||||||
|
join = LEFT_JOIN_SATS
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
const flat = await models.$queryRaw(`
|
const flat = await models.$queryRaw(`
|
||||||
WITH RECURSIVE base AS (
|
WITH RECURSIVE base AS (
|
||||||
${SELECT}, ARRAY[row_number() OVER (${ORDER_BY_SATS}, "Item".path)] AS sort_path
|
${SELECT}, ARRAY[row_number() OVER (${orderBy}, "Item".path)] AS sort_path
|
||||||
FROM "Item"
|
FROM "Item"
|
||||||
${LEFT_JOIN_SATS}
|
${join}
|
||||||
WHERE "parentId" = $1
|
WHERE "parentId" = $1
|
||||||
UNION ALL
|
UNION ALL
|
||||||
${SELECT}, p.sort_path || row_number() OVER (${ORDER_BY_SATS}, "Item".path)
|
${SELECT}, p.sort_path || row_number() OVER (${orderBy}, "Item".path)
|
||||||
FROM base p
|
FROM base p
|
||||||
JOIN "Item" ON ltree2text(subpath("Item"."path", 0, -1)) = p."path"
|
JOIN "Item" ON ltree2text(subpath("Item"."path", 0, -1)) = p."path"
|
||||||
${LEFT_JOIN_SATS})
|
${join})
|
||||||
SELECT * FROM base ORDER BY sort_path`, Number(id))
|
SELECT * FROM base ORDER BY sort_path`, Number(id))
|
||||||
return nestComments(flat, id)[0]
|
return nestComments(flat, id)[0]
|
||||||
}
|
}
|
||||||
@ -27,7 +44,7 @@ export async function getItem (parent, { id }, { models }) {
|
|||||||
FROM "Item"
|
FROM "Item"
|
||||||
WHERE id = $1`, Number(id))
|
WHERE id = $1`, Number(id))
|
||||||
if (item) {
|
if (item) {
|
||||||
item.comments = comments(models, id)
|
item.comments = comments(models, id, 'hot')
|
||||||
}
|
}
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
@ -211,6 +228,9 @@ export default {
|
|||||||
WHERE url SIMILAR TO $1
|
WHERE url SIMILAR TO $1
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 3`, similar)
|
LIMIT 3`, similar)
|
||||||
|
},
|
||||||
|
comments: async (parent, { id, sort }, { models }) => {
|
||||||
|
return comments(models, id, sort)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ export default gql`
|
|||||||
moreItems(sort: String!, cursor: String, name: String, within: String): Items
|
moreItems(sort: String!, cursor: String, name: String, within: String): Items
|
||||||
moreFlatComments(sort: String!, cursor: String, name: String, within: String): Comments
|
moreFlatComments(sort: String!, cursor: String, name: String, within: String): Comments
|
||||||
item(id: ID!): Item
|
item(id: ID!): Item
|
||||||
|
comments(id: ID!, sort: String): [Item!]!
|
||||||
pageTitle(url: String!): String
|
pageTitle(url: String!): String
|
||||||
dupes(url: String!): [Item!]
|
dupes(url: String!): [Item!]
|
||||||
}
|
}
|
||||||
|
@ -80,12 +80,12 @@
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment:not(:last-child) {
|
.comment:not(:last-of-type) {
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment:not(:first-child) {
|
.comment:not(:first-of-type) {
|
||||||
padding-top: .25rem;
|
padding-top: .25rem;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
|
@ -1,19 +1,98 @@
|
|||||||
import { useQuery } from '@apollo/client'
|
import { gql, useApolloClient, useLazyQuery, useQuery } from '@apollo/client'
|
||||||
import { useEffect } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import Comment, { CommentSkeleton } from './comment'
|
import Comment, { CommentSkeleton } from './comment'
|
||||||
|
import styles from './header.module.css'
|
||||||
|
import { Nav, Navbar } from 'react-bootstrap'
|
||||||
|
import { COMMENTS_QUERY } from '../fragments/items'
|
||||||
|
import { COMMENTS } from '../fragments/comments'
|
||||||
|
|
||||||
export default function Comments ({ comments, ...props }) {
|
export function CommentsHeader ({ handleSort }) {
|
||||||
|
const [sort, setSort] = useState('hot')
|
||||||
|
|
||||||
|
const getHandleClick = sort => {
|
||||||
|
return () => {
|
||||||
|
setSort(sort)
|
||||||
|
handleSort(sort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Navbar className='py-0'>
|
||||||
|
<Nav
|
||||||
|
className={styles.navbarNav}
|
||||||
|
activeKey={sort}
|
||||||
|
>
|
||||||
|
<Nav.Item>
|
||||||
|
<Nav.Link
|
||||||
|
eventKey='hot'
|
||||||
|
className={styles.navLink}
|
||||||
|
onClick={getHandleClick('hot')}
|
||||||
|
>
|
||||||
|
hot
|
||||||
|
</Nav.Link>
|
||||||
|
</Nav.Item>
|
||||||
|
<Nav.Item>
|
||||||
|
<Nav.Link
|
||||||
|
eventKey='recent'
|
||||||
|
className={styles.navLink}
|
||||||
|
onClick={getHandleClick('recent')}
|
||||||
|
>
|
||||||
|
recent
|
||||||
|
</Nav.Link>
|
||||||
|
</Nav.Item>
|
||||||
|
<Nav.Item>
|
||||||
|
<Nav.Link
|
||||||
|
eventKey='top'
|
||||||
|
className={styles.navLink}
|
||||||
|
onClick={getHandleClick('top')}
|
||||||
|
>
|
||||||
|
top
|
||||||
|
</Nav.Link>
|
||||||
|
</Nav.Item>
|
||||||
|
</Nav>
|
||||||
|
</Navbar>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Comments ({ parentId, comments, ...props }) {
|
||||||
|
const client = useApolloClient()
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Your code here
|
|
||||||
const hash = window.location.hash
|
const hash = window.location.hash
|
||||||
if (hash) {
|
if (hash) {
|
||||||
document.querySelector(hash).scrollIntoView({ behavior: 'smooth' })
|
document.querySelector(hash).scrollIntoView({ behavior: 'smooth' })
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
const [getComments, { loading }] = useLazyQuery(COMMENTS_QUERY, {
|
||||||
|
fetchPolicy: 'network-only',
|
||||||
|
onCompleted: data => {
|
||||||
|
client.writeFragment({
|
||||||
|
id: `Item:${parentId}`,
|
||||||
|
fragment: gql`
|
||||||
|
${COMMENTS}
|
||||||
|
fragment Comments on Item {
|
||||||
|
comments {
|
||||||
|
...CommentsRecursive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
fragmentName: 'Comments',
|
||||||
|
data: {
|
||||||
|
comments: data.comments
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return comments.map(item => (
|
return (
|
||||||
<Comment key={item.id} item={item} {...props} />
|
<>
|
||||||
))
|
{comments.length ? <CommentsHeader handleSort={sort => getComments({ variables: { id: parentId, sort } })} /> : null}
|
||||||
|
{loading
|
||||||
|
? <CommentsSkeleton />
|
||||||
|
: comments.map(item => (
|
||||||
|
<Comment key={item.id} item={item} {...props} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CommentsSkeleton () {
|
export function CommentsSkeleton () {
|
||||||
|
@ -57,7 +57,7 @@ export default function ItemFull ({ item, bio, ...props }) {
|
|||||||
</div>)}
|
</div>)}
|
||||||
{item.comments &&
|
{item.comments &&
|
||||||
<div className={styles.comments}>
|
<div className={styles.comments}>
|
||||||
<Comments comments={item.comments} />
|
<Comments parentId={item.id} comments={item.comments} />
|
||||||
</div>}
|
</div>}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -52,6 +52,16 @@ export const ITEM = gql`
|
|||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
|
export const COMMENTS_QUERY = gql`
|
||||||
|
${COMMENTS}
|
||||||
|
|
||||||
|
query Comments($id: ID!, $sort: String) {
|
||||||
|
comments(id: $id, sort: $sort) {
|
||||||
|
...CommentsRecursive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
export const ITEM_FULL = gql`
|
export const ITEM_FULL = gql`
|
||||||
${ITEM_FIELDS}
|
${ITEM_FIELDS}
|
||||||
${COMMENTS}
|
${COMMENTS}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user