From 8e5327022dd2a3f7512562cb481feb1a7020b8ed Mon Sep 17 00:00:00 2001 From: keyan Date: Thu, 16 Dec 2021 17:05:31 -0600 Subject: [PATCH] WIP top comments and users --- api/resolvers/item.js | 92 ++++++++++++++++---------- api/typeDefs/item.js | 4 +- components/top-header.js | 116 +++++++++++++++++++++++++++++++++ fragments/comments.js | 4 +- fragments/items.js | 2 +- fragments/users.js | 2 +- lib/apollo.js | 2 +- pages/top/[[...within]].js | 76 --------------------- pages/top/comments/[within].js | 23 +++++++ pages/top/posts/[within].js | 23 +++++++ 10 files changed, 228 insertions(+), 116 deletions(-) create mode 100644 components/top-header.js delete mode 100644 pages/top/[[...within]].js create mode 100644 pages/top/comments/[within].js create mode 100644 pages/top/posts/[within].js diff --git a/api/resolvers/item.js b/api/resolvers/item.js index b8f9e197..35328bf8 100644 --- a/api/resolvers/item.js +++ b/api/resolvers/item.js @@ -32,11 +32,33 @@ export async function getItem (parent, { id }, { models }) { return item } +function topClause (within) { + let interval = ' AND created_at >= $1 - INTERVAL ' + switch (within) { + case 'day': + interval += "'1 day'" + break + case 'week': + interval += "'7 days'" + break + case 'month': + interval += "'1 month'" + break + case 'year': + interval += "'1 year'" + break + default: + interval = '' + break + } + return interval +} + export default { Query: { moreItems: async (parent, { sort, cursor, name, within }, { me, models }) => { const decodedCursor = decodeCursor(cursor) - let items; let user; let interval = 'INTERVAL ' + let items; let user switch (sort) { case 'user': @@ -88,27 +110,12 @@ export default { } break case 'top': - switch (within?.pop()) { - case 'day': - interval += "'1 day'" - break - case 'week': - interval += "'7 days'" - break - case 'month': - interval += "'1 month'" - break - case 'year': - interval += "'1 year'" - break - } - items = await models.$queryRaw(` ${SELECT} FROM "Item" ${timedLeftJoinSats(1)} WHERE "parentId" IS NULL AND created_at <= $1 - ${within ? ` AND created_at >= $1 - ${interval}` : ''} + ${topClause(within)} ORDER BY x.sats DESC NULLS LAST, created_at DESC OFFSET $2 LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset) @@ -128,26 +135,45 @@ export default { items } }, - moreFlatComments: async (parent, { cursor, name }, { me, models }) => { + moreFlatComments: async (parent, { cursor, name, sort, within }, { me, models }) => { const decodedCursor = decodeCursor(cursor) - if (!name) { - throw new UserInputError('must supply name', { argumentName: 'name' }) - } + let comments, user + switch (sort) { + case 'user': + if (!name) { + throw new UserInputError('must supply name', { argumentName: 'name' }) + } - const user = await models.user.findUnique({ where: { name } }) - if (!user) { - throw new UserInputError('no user has that name', { argumentName: 'name' }) - } + user = await models.user.findUnique({ where: { name } }) + if (!user) { + throw new UserInputError('no user has that name', { argumentName: 'name' }) + } - const comments = await models.$queryRaw(` - ${SELECT} - FROM "Item" - WHERE "userId" = $1 AND "parentId" IS NOT NULL - AND created_at <= $2 - ORDER BY created_at DESC - OFFSET $3 - LIMIT ${LIMIT}`, user.id, decodedCursor.time, decodedCursor.offset) + comments = await models.$queryRaw(` + ${SELECT} + FROM "Item" + WHERE "userId" = $1 AND "parentId" IS NOT NULL + AND created_at <= $2 + ORDER BY created_at DESC + OFFSET $3 + LIMIT ${LIMIT}`, user.id, decodedCursor.time, decodedCursor.offset) + break + case 'top': + comments = await models.$queryRaw(` + ${SELECT} + FROM "Item" + ${timedLeftJoinSats(1)} + WHERE "parentId" IS NOT NULL + AND created_at <= $1 + ${topClause(within)} + ORDER BY x.sats DESC NULLS LAST, created_at DESC + OFFSET $2 + LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset) + break + default: + throw new UserInputError('invalid sort type', { argumentName: 'sort' }) + } return { cursor: comments.length === LIMIT ? nextCursorEncoded(decodedCursor) : null, diff --git a/api/typeDefs/item.js b/api/typeDefs/item.js index 54692fe0..4e402339 100644 --- a/api/typeDefs/item.js +++ b/api/typeDefs/item.js @@ -2,8 +2,8 @@ import { gql } from 'apollo-server-micro' export default gql` extend type Query { - moreItems(sort: String!, cursor: String, name: String, within: [String]): Items - moreFlatComments(cursor: String, name: String!): Comments + moreItems(sort: String!, cursor: String, name: String, within: String): Items + moreFlatComments(sort: String!, cursor: String, name: String, within: String): Comments item(id: ID!): Item pageTitle(url: String!): String dupes(url: String!): [Item!] diff --git a/components/top-header.js b/components/top-header.js new file mode 100644 index 00000000..19a5c200 --- /dev/null +++ b/components/top-header.js @@ -0,0 +1,116 @@ +import { Nav, Navbar } from 'react-bootstrap' +import styles from './header.module.css' +import Link from 'next/link' +import { useRouter } from 'next/router' + +export default function TopHeader ({ cat }) { + const router = useRouter() + const within = router.query.within + + return ( + <> + + + + + + + + ) +} diff --git a/fragments/comments.js b/fragments/comments.js index 82e69ebe..0eda0037 100644 --- a/fragments/comments.js +++ b/fragments/comments.js @@ -32,8 +32,8 @@ export const COMMENT_FIELDS = gql` export const MORE_FLAT_COMMENTS = gql` ${COMMENT_FIELDS} - query MoreFlatComments($cursor: String, $name: String!) { - moreFlatComments(cursor: $cursor, name: $name) { + query MoreFlatComments($sort: String!, $cursor: String, $name: String, $within: String) { + moreFlatComments(sort: $sort, cursor: $cursor, name: $name, within: $within) { cursor comments { ...CommentFields diff --git a/fragments/items.js b/fragments/items.js index 9a9b9d5b..751f8fcd 100644 --- a/fragments/items.js +++ b/fragments/items.js @@ -33,7 +33,7 @@ export const ITEM_FIELDS = gql` export const MORE_ITEMS = gql` ${ITEM_FIELDS} - query MoreItems($sort: String!, $cursor: String, $name: String, $within: [String]) { + query MoreItems($sort: String!, $cursor: String, $name: String, $within: String) { moreItems(sort: $sort, cursor: $cursor, name: $name, within: $within) { cursor items { diff --git a/fragments/users.js b/fragments/users.js index 23a7956c..7f778d50 100644 --- a/fragments/users.js +++ b/fragments/users.js @@ -62,7 +62,7 @@ export const USER_WITH_COMMENTS = gql` ...ItemWithComments } } - moreFlatComments(name: $name) { + moreFlatComments(sort: "user", name: $name) { cursor comments { ...CommentFields diff --git a/lib/apollo.js b/lib/apollo.js index 0447dfea..855668eb 100644 --- a/lib/apollo.js +++ b/lib/apollo.js @@ -39,7 +39,7 @@ export default function getApolloClient () { } }, moreFlatComments: { - keyArgs: ['name'], + keyArgs: ['name', 'sort', 'within'], merge (existing, incoming) { if (isFirstPage(incoming.cursor, existing?.comments)) { return incoming diff --git a/pages/top/[[...within]].js b/pages/top/[[...within]].js deleted file mode 100644 index 6b90ac53..00000000 --- a/pages/top/[[...within]].js +++ /dev/null @@ -1,76 +0,0 @@ -import Layout from '../../components/layout' -import Items from '../../components/items' -import { useRouter } from 'next/router' -import { getGetServerSideProps } from '../../api/ssrApollo' -import { MORE_ITEMS } from '../../fragments/items' -import { Nav, Navbar } from 'react-bootstrap' -import styles from '../../components/header.module.css' -import Link from 'next/link' - -export const getServerSideProps = getGetServerSideProps(MORE_ITEMS, { sort: 'top'}) - -export default function Index ({ data: { moreItems: { items, cursor } } }) { - const router = useRouter() - const path = router.asPath.split('?')[0] - - return ( - - - - - - - ) -} \ No newline at end of file diff --git a/pages/top/comments/[within].js b/pages/top/comments/[within].js new file mode 100644 index 00000000..9099b527 --- /dev/null +++ b/pages/top/comments/[within].js @@ -0,0 +1,23 @@ +import Layout from '../../../components/layout' +import { useRouter } from 'next/router' +import { getGetServerSideProps } from '../../../api/ssrApollo' +import TopHeader from '../../../components/top-header' +import { MORE_FLAT_COMMENTS } from '../../../fragments/comments' +import CommentsFlat from '../../../components/comments-flat' + +export const getServerSideProps = getGetServerSideProps(MORE_FLAT_COMMENTS, { sort: 'top' }) + +export default function Index ({ data: { moreFlatComments: { comments, cursor } } }) { + const router = useRouter() + + return ( + + + + + ) +} diff --git a/pages/top/posts/[within].js b/pages/top/posts/[within].js new file mode 100644 index 00000000..8cbab1e8 --- /dev/null +++ b/pages/top/posts/[within].js @@ -0,0 +1,23 @@ +import Layout from '../../../components/layout' +import Items from '../../../components/items' +import { useRouter } from 'next/router' +import { getGetServerSideProps } from '../../../api/ssrApollo' +import { MORE_ITEMS } from '../../../fragments/items' + +import TopHeader from '../../../components/top-header' + +export const getServerSideProps = getGetServerSideProps(MORE_ITEMS, { sort: 'top' }) + +export default function Index ({ data: { moreItems: { items, cursor } } }) { + const router = useRouter() + + return ( + + + + + ) +}