fix nested comment sorting

This commit is contained in:
keyan 2023-07-25 19:45:35 -05:00
parent 19835aef5f
commit 8ab018af88
12 changed files with 44 additions and 136 deletions

View File

@ -482,9 +482,6 @@ export default {
LIMIT 3` LIMIT 3`
}, similar) }, similar)
}, },
comments: async (parent, { id, sort }, { me, models }) => {
return comments(me, models, id, sort)
},
auctionPosition: async (parent, { id, sub, bid }, { models, me }) => { auctionPosition: async (parent, { id, sub, bid }, { models, me }) => {
const createdAt = id ? (await getItem(parent, { id }, { models, me })).createdAt : new Date() const createdAt = id ? (await getItem(parent, { id }, { models, me })).createdAt : new Date()
let where let where
@ -848,12 +845,11 @@ export default {
} }
return await models.user.findUnique({ where: { id: item.fwdUserId } }) return await models.user.findUnique({ where: { id: item.fwdUserId } })
}, },
comments: async (item, args, { me, models }) => { comments: async (item, { sort }, { me, models }) => {
if (item.comments) { if (item.comments) return item.comments
return item.comments if (item.ncomments === 0) return []
}
return comments(me, models, item.id, defaultCommentSort(item.pinId, item.bioId, item.createdAt)) return comments(me, models, item.id, sort || defaultCommentSort(item.pinId, item.bioId, item.createdAt))
}, },
wvotes: async (item) => { wvotes: async (item) => {
return item.weightedVotes - item.weightedDownVotes return item.weightedVotes - item.weightedDownVotes

View File

@ -4,7 +4,6 @@ export default gql`
extend type Query { extend type Query {
items(sub: String, sort: String, type: String, cursor: String, name: String, when: String, by: String, limit: Int): Items items(sub: String, sort: String, type: String, cursor: String, name: String, when: String, by: String, limit: Int): Items
item(id: ID!): Item item(id: ID!): Item
comments(id: ID!, sort: String): [Item!]!
pageTitleAndUnshorted(url: String!): TitleUnshorted pageTitleAndUnshorted(url: String!): TitleUnshorted
dupes(url: String!): [Item!] dupes(url: String!): [Item!]
related(cursor: String, title: String, id: ID, minMatch: String, limit: Int): Items related(cursor: String, title: String, id: ID, minMatch: String, limit: Int): Items
@ -99,7 +98,7 @@ export default gql`
freebie: Boolean! freebie: Boolean!
paidImgLink: Boolean paidImgLink: Boolean
ncomments: Int! ncomments: Int!
comments: [Item!]! comments(sort: String): [Item!]!
path: String path: String
position: Int position: Int
prior: Int prior: Int

View File

@ -1,20 +1,17 @@
import { gql, useApolloClient, useLazyQuery } from '@apollo/client'
import { useState } from 'react'
import Comment, { CommentSkeleton } from './comment' import Comment, { CommentSkeleton } from './comment'
import styles from './header.module.css' import styles from './header.module.css'
import Nav from 'react-bootstrap/Nav' import Nav from 'react-bootstrap/Nav'
import Navbar from 'react-bootstrap/Navbar' import Navbar from 'react-bootstrap/Navbar'
import { COMMENTS_QUERY } from '../fragments/items'
import { COMMENTS } from '../fragments/comments'
import { abbrNum } from '../lib/format' import { abbrNum } from '../lib/format'
import { defaultCommentSort } from '../lib/item' import { defaultCommentSort } from '../lib/item'
import { useRouter } from 'next/router'
export function CommentsHeader ({ handleSort, pinned, bio, parentCreatedAt, commentSats }) { export function CommentsHeader ({ handleSort, pinned, bio, parentCreatedAt, commentSats }) {
const [sort, setSort] = useState(defaultCommentSort(pinned, bio, parentCreatedAt)) const router = useRouter()
const sort = router.query.sort || defaultCommentSort(pinned, bio, parentCreatedAt)
const getHandleClick = sort => { const getHandleClick = sort => {
return () => { return () => {
setSort(sort)
handleSort(sort) handleSort(sort)
} }
} }
@ -63,45 +60,24 @@ export function CommentsHeader ({ handleSort, pinned, bio, parentCreatedAt, comm
} }
export default function Comments ({ parentId, pinned, bio, parentCreatedAt, commentSats, comments, ...props }) { export default function Comments ({ parentId, pinned, bio, parentCreatedAt, commentSats, comments, ...props }) {
const client = useApolloClient() const router = useRouter()
const [loading, setLoading] = useState()
const [getComments] = useLazyQuery(COMMENTS_QUERY, {
fetchPolicy: 'cache-first',
onCompleted: data => {
client.writeFragment({
id: `Item:${parentId}`,
fragment: gql`
${COMMENTS}
fragment Comments on Item {
comments {
...CommentsRecursive
}
}
`,
fragmentName: 'Comments',
data: {
comments: data.comments
}
})
setLoading(false)
}
})
return ( return (
<> <>
{comments.length {comments?.length > 0
? <CommentsHeader ? <CommentsHeader
commentSats={commentSats} parentCreatedAt={parentCreatedAt} commentSats={commentSats} parentCreatedAt={parentCreatedAt}
pinned={pinned} bio={bio} handleSort={sort => { pinned={pinned} bio={bio} handleSort={sort => {
setLoading(true) const query = router.query
getComments({ variables: { id: parentId, sort } }) delete query.nodata
router.push({
pathname: router.pathname,
query: { ...router.query, sort }
}, router.asPath, { scroll: false })
}} }}
/> />
: null} : null}
{loading {comments.map(item => (
? <CommentsSkeleton />
: comments.map(item => (
<Comment depth={1} key={item.id} item={item} {...props} /> <Comment depth={1} key={item.id} item={item} {...props} />
))} ))}
</> </>

View File

@ -178,11 +178,9 @@ export default function ItemFull ({ item, bio, rank, ...props }) {
{item.parentId {item.parentId
? <Comment topLevel item={item} replyOpen includeParent noComments {...props} /> ? <Comment topLevel item={item} replyOpen includeParent noComments {...props} />
: ( : (
<div className='mt-1'>{ <div>{bio
bio
? <BioItem item={item} {...props} /> ? <BioItem item={item} {...props} />
: <TopLevelItem item={item} {...props} /> : <TopLevelItem item={item} {...props} />}
}
</div>)} </div>)}
{item.comments && {item.comments &&
<div className={styles.comments}> <div className={styles.comments}>

View File

@ -19,8 +19,8 @@ export default function TopHeader ({ sub, cat }) {
if (typeof query.by !== 'undefined') { if (typeof query.by !== 'undefined') {
if (query.by === '' || if (query.by === '' ||
(what === 'stackers' && !USER_SORTS.includes(query.by)) || (what === 'stackers' && (query.by === 'stacked' || !USER_SORTS.includes(query.by))) ||
(what !== 'stackers' && !ITEM_SORTS.includes(query.by))) { (what !== 'stackers' && (query.by === 'votes' || !ITEM_SORTS.includes(query.by)))) {
delete query.by delete query.by
} }
} }

View File

@ -49,6 +49,7 @@ export const COMMENTS_ITEM_EXT_FIELDS = gql`
} }
}` }`
// we only get the first COMMENT_DEPTH_LIMIT comments
export const COMMENTS = gql` export const COMMENTS = gql`
${COMMENT_FIELDS} ${COMMENT_FIELDS}
@ -72,54 +73,6 @@ export const COMMENTS = gql`
...CommentFields ...CommentFields
comments { comments {
...CommentFields ...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
comments {
...CommentFields
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
} }
} }
} }

View File

@ -116,41 +116,21 @@ 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_FULL_FIELDS} ${ITEM_FULL_FIELDS}
${POLL_FIELDS} ${POLL_FIELDS}
${COMMENTS} ${COMMENTS}
query Item($id: ID!) { query Item($id: ID!, $sort: String) {
item(id: $id) { item(id: $id) {
...ItemFullFields ...ItemFullFields
prior prior
...PollFields ...PollFields
comments { comments(sort: $sort) {
...CommentsRecursive ...CommentsRecursive
} }
} }
}` }`
export const ITEM_WITH_COMMENTS = gql`
${ITEM_FULL_FIELDS}
${COMMENTS}
fragment ItemWithComments on Item {
...ItemFullFields
comments {
...CommentsRecursive
}
}`
export const RELATED_ITEMS = gql` export const RELATED_ITEMS = gql`
${ITEM_FIELDS} ${ITEM_FIELDS}
query Related($title: String, $id: ID, $cursor: String, $limit: Int) { query Related($title: String, $id: ID, $cursor: String, $limit: Int) {

View File

@ -1,6 +1,6 @@
import { gql } from '@apollo/client' import { gql } from '@apollo/client'
import { COMMENTS_ITEM_EXT_FIELDS } from './comments' import { COMMENTS, COMMENTS_ITEM_EXT_FIELDS } from './comments'
import { ITEM_FIELDS, ITEM_WITH_COMMENTS } from './items' import { ITEM_FIELDS, ITEM_FULL_FIELDS } from './items'
export const ME = gql` export const ME = gql`
{ {
@ -174,12 +174,16 @@ export const TOP_COWBOYS = gql`
export const USER_FULL = gql` export const USER_FULL = gql`
${USER_FIELDS} ${USER_FIELDS}
${ITEM_WITH_COMMENTS} ${ITEM_FULL_FIELDS}
query User($name: String!) { ${COMMENTS}
query User($name: String!, $sort: String) {
user(name: $name) { user(name: $name) {
...UserFields ...UserFields
bio { bio {
...ItemWithComments ...ItemFullFields
comments(sort: $sort) {
...CommentsRecursive
}
} }
} }
}` }`

View File

@ -3,9 +3,9 @@ import { dayPivot } from './time'
export const defaultCommentSort = (pinned, bio, createdAt) => { export const defaultCommentSort = (pinned, bio, createdAt) => {
// pins sort by recent // pins sort by recent
if (pinned || bio) return 'recent' if (pinned) return 'recent'
// old items sort by top // old items (that aren't bios) sort by top
if (new Date(createdAt) < dayPivot(new Date(), -OLD_ITEM_DAYS)) return 'top' if (!bio && new Date(createdAt) < dayPivot(new Date(), -OLD_ITEM_DAYS)) return 'top'
// everything else sorts by hot // everything else sorts by hot
return 'hot' return 'hot'
} }

View File

@ -97,7 +97,7 @@ export default function User ({ ssrData }) {
const router = useRouter() const router = useRouter()
const me = useMe() const me = useMe()
const { data } = useQuery(USER_FULL, { variables: { name: router.query.name } }) const { data } = useQuery(USER_FULL, { variables: { ...router.query } })
if (!data && !ssrData) return <PageLoading /> if (!data && !ssrData) return <PageLoading />
const { user } = data || ssrData const { user } = data || ssrData

View File

@ -39,6 +39,8 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
// this nodata var will get passed to the server on back/foward and // this nodata var will get passed to the server on back/foward and
// 1. prevent data from reloading and 2. perserve scroll // 1. prevent data from reloading and 2. perserve scroll
// (2) is not possible while intercepting nav with beforePopState // (2) is not possible while intercepting nav with beforePopState
if (router.query.nodata) return
router.replace({ router.replace({
pathname: router.pathname, pathname: router.pathname,
query: { ...router.query, nodata: true } query: { ...router.query, nodata: true }
@ -48,7 +50,7 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
throw e throw e
} }
}) })
}, [router.asPath]) }, [router.pathname, router.query])
/* /*
If we are on the client, we populate the apollo cache with the If we are on the client, we populate the apollo cache with the

View File

@ -12,7 +12,7 @@ export const getServerSideProps = getGetServerSideProps(ITEM_FULL, null,
export default function Item ({ ssrData }) { export default function Item ({ ssrData }) {
const router = useRouter() const router = useRouter()
const { data } = useQuery(ITEM_FULL, { variables: { id: router.query.id } }) const { data } = useQuery(ITEM_FULL, { variables: { ...router.query } })
if (!data && !ssrData) return <PageLoading /> if (!data && !ssrData) return <PageLoading />
const { item } = data || ssrData const { item } = data || ssrData