ssr everything
This commit is contained in:
parent
4ba0bcd416
commit
ca1a95094c
@ -1,9 +1,7 @@
|
|||||||
import { PrismaClient } from '@prisma/client'
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
|
||||||
const prisma = global.prisma || new PrismaClient({
|
global.prisma ||= new PrismaClient({
|
||||||
log: ['warn', 'error']
|
log: ['warn', 'error']
|
||||||
})
|
})
|
||||||
|
|
||||||
global.prisma = prisma
|
export default global.prisma
|
||||||
|
|
||||||
export default prisma
|
|
||||||
|
@ -6,11 +6,10 @@ import resolvers from './resolvers'
|
|||||||
import typeDefs from './typeDefs'
|
import typeDefs from './typeDefs'
|
||||||
import models from './models'
|
import models from './models'
|
||||||
|
|
||||||
export default async function serverSideClient (req) {
|
export default async function getSSRApolloClient (req) {
|
||||||
const session = req && await getSession({ req })
|
const session = req && await getSession({ req })
|
||||||
return new ApolloClient({
|
return new ApolloClient({
|
||||||
ssrMode: true,
|
ssrMode: true,
|
||||||
// Instead of "createHttpLink" use SchemaLink here
|
|
||||||
link: new SchemaLink({
|
link: new SchemaLink({
|
||||||
schema: mergeSchemas({
|
schema: mergeSchemas({
|
||||||
schemas: typeDefs,
|
schemas: typeDefs,
|
@ -1,22 +1,25 @@
|
|||||||
import { useQuery } from '@apollo/client'
|
import { useQuery } from '@apollo/client'
|
||||||
import Button from 'react-bootstrap/Button'
|
|
||||||
import { MORE_FLAT_COMMENTS } from '../fragments/comments'
|
import { MORE_FLAT_COMMENTS } from '../fragments/comments'
|
||||||
import { useState } from 'react'
|
|
||||||
import Comment, { CommentSkeleton } from './comment'
|
import Comment, { CommentSkeleton } from './comment'
|
||||||
import styles from './notifications.module.css'
|
import styles from './notifications.module.css'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import MoreFooter from './more-footer'
|
||||||
|
|
||||||
export default function CommentsFlat ({ variables, ...props }) {
|
export default function CommentsFlat ({ variables, comments, cursor, ...props }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { error, data, fetchMore } = useQuery(MORE_FLAT_COMMENTS, {
|
const { data, fetchMore } = useQuery(MORE_FLAT_COMMENTS, {
|
||||||
variables,
|
variables,
|
||||||
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
||||||
})
|
})
|
||||||
if (error) return <div>Failed to load!</div>
|
|
||||||
if (!data) {
|
if (!data && !comments) {
|
||||||
return <CommentsFlatSkeleton />
|
return <CommentsFlatSkeleton />
|
||||||
}
|
}
|
||||||
const { moreFlatComments: { comments, cursor } } = data
|
|
||||||
|
if (data) {
|
||||||
|
({ moreFlatComments: { comments, cursor } } = data)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{comments.map(item => (
|
{comments.map(item => (
|
||||||
@ -33,7 +36,7 @@ export default function CommentsFlat ({ variables, ...props }) {
|
|||||||
<Comment item={item} {...props} />
|
<Comment item={item} {...props} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<MoreFooter cursor={cursor} fetchMore={fetchMore} />
|
<MoreFooter cursor={cursor} fetchMore={fetchMore} Skeleton={CommentsFlatSkeleton} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -48,37 +51,3 @@ function CommentsFlatSkeleton () {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function MoreFooter ({ cursor, fetchMore }) {
|
|
||||||
const [loading, setLoading] = useState(false)
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <div><CommentsFlatSkeleton /></div>
|
|
||||||
}
|
|
||||||
|
|
||||||
let Footer
|
|
||||||
if (cursor) {
|
|
||||||
Footer = () => (
|
|
||||||
<Button
|
|
||||||
variant='primary'
|
|
||||||
size='md'
|
|
||||||
onClick={async () => {
|
|
||||||
setLoading(true)
|
|
||||||
await fetchMore({
|
|
||||||
variables: {
|
|
||||||
cursor
|
|
||||||
}
|
|
||||||
})
|
|
||||||
setLoading(false)
|
|
||||||
}}
|
|
||||||
>more
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Footer = () => (
|
|
||||||
<div className='text-muted' style={{ fontFamily: 'lightning', fontSize: '2rem', opacity: '0.6' }}>GENISIS</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className='d-flex justify-content-center mt-4 mb-2'><Footer /></div>
|
|
||||||
}
|
|
||||||
|
@ -47,32 +47,6 @@ function ItemText ({ item }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function ItemFull ({ item, bio, ...props }) {
|
export default function ItemFull ({ item, bio, ...props }) {
|
||||||
const query = gql`
|
|
||||||
${ITEM_FIELDS}
|
|
||||||
${COMMENTS}
|
|
||||||
{
|
|
||||||
item(id: ${item.id}) {
|
|
||||||
...ItemFields
|
|
||||||
text
|
|
||||||
comments {
|
|
||||||
...CommentsRecursive
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const { error, data } = useQuery(query, {
|
|
||||||
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
|
||||||
})
|
|
||||||
if (error) {
|
|
||||||
return <div>Failed to load!</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX replace item with cache version
|
|
||||||
if (data) {
|
|
||||||
({ item } = data)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{item.parentId
|
{item.parentId
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
import { useQuery } from '@apollo/client'
|
import { useQuery } from '@apollo/client'
|
||||||
import Button from 'react-bootstrap/Button'
|
|
||||||
import Item, { ItemSkeleton } from './item'
|
import Item, { ItemSkeleton } from './item'
|
||||||
import styles from './items.module.css'
|
import styles from './items.module.css'
|
||||||
import { MORE_ITEMS } from '../fragments/items'
|
import { MORE_ITEMS } from '../fragments/items'
|
||||||
import { useState } from 'react'
|
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import MoreFooter from './more-footer'
|
||||||
|
|
||||||
export default function Items ({ variables, rank }) {
|
export default function Items ({ variables, rank, items, cursor }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { error, data, fetchMore } = useQuery(MORE_ITEMS, {
|
const { data, fetchMore } = useQuery(MORE_ITEMS, {
|
||||||
variables,
|
variables,
|
||||||
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
||||||
})
|
})
|
||||||
if (error) return <div>Failed to load!</div>
|
|
||||||
if (!data) {
|
if (!data && !items) {
|
||||||
return <ItemsSkeleton rank={rank} />
|
return <ItemsSkeleton rank={rank} />
|
||||||
}
|
}
|
||||||
|
|
||||||
const { moreItems: { items, cursor } } = data
|
if (data) {
|
||||||
|
({ moreItems: { items, cursor } } = data)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.grid}>
|
<div className={styles.grid}>
|
||||||
@ -25,7 +27,10 @@ export default function Items ({ variables, rank }) {
|
|||||||
<Item item={item} rank={rank && i + 1} key={item.id} />
|
<Item item={item} rank={rank && i + 1} key={item.id} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<MoreFooter cursor={cursor} fetchMore={fetchMore} offset={items.length} rank={rank} />
|
<MoreFooter
|
||||||
|
cursor={cursor} fetchMore={fetchMore}
|
||||||
|
Skeleton={() => <ItemsSkeleton rank={rank} startRank={items.length} />}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -41,37 +46,3 @@ function ItemsSkeleton ({ rank, startRank = 0 }) {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function MoreFooter ({ cursor, fetchMore, rank, offset }) {
|
|
||||||
const [loading, setLoading] = useState(false)
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <ItemsSkeleton rank={rank} startRank={offset} />
|
|
||||||
}
|
|
||||||
|
|
||||||
let Footer
|
|
||||||
if (cursor) {
|
|
||||||
Footer = () => (
|
|
||||||
<Button
|
|
||||||
variant='primary'
|
|
||||||
size='md'
|
|
||||||
onClick={async () => {
|
|
||||||
setLoading(true)
|
|
||||||
await fetchMore({
|
|
||||||
variables: {
|
|
||||||
cursor
|
|
||||||
}
|
|
||||||
})
|
|
||||||
setLoading(false)
|
|
||||||
}}
|
|
||||||
>more
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Footer = () => (
|
|
||||||
<div className='text-muted' style={{ fontFamily: 'lightning', fontSize: '2rem', opacity: '0.6' }}>GENISIS</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className='d-flex justify-content-center mt-4 mb-2'><Footer /></div>
|
|
||||||
}
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
import { HeaderPreview } from './header'
|
|
||||||
import Head from 'next/head'
|
|
||||||
import Container from 'react-bootstrap/Container'
|
|
||||||
|
|
||||||
export default function LayoutPreview ({ children }) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Head>
|
|
||||||
<meta name='viewport' content='initial-scale=1.0, width=device-width' />
|
|
||||||
</Head>
|
|
||||||
<HeaderPreview />
|
|
||||||
|
|
||||||
<Container className='mt-1 px-sm-0'>
|
|
||||||
{children}
|
|
||||||
</Container>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
36
components/more-footer.js
Normal file
36
components/more-footer.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { Button } from 'react-bootstrap'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
export default function MoreFooter ({ cursor, fetchMore, Skeleton }) {
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <div><Skeleton /></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
let Footer
|
||||||
|
if (cursor) {
|
||||||
|
Footer = () => (
|
||||||
|
<Button
|
||||||
|
variant='primary'
|
||||||
|
size='md'
|
||||||
|
onClick={async () => {
|
||||||
|
setLoading(true)
|
||||||
|
await fetchMore({
|
||||||
|
variables: {
|
||||||
|
cursor
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setLoading(false)
|
||||||
|
}}
|
||||||
|
>more
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Footer = () => (
|
||||||
|
<div className='text-muted' style={{ fontFamily: 'lightning', fontSize: '2rem', opacity: '0.6' }}>GENISIS</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className='d-flex justify-content-center mt-4 mb-2'><Footer /></div>
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
import { useQuery } from '@apollo/client'
|
import { useQuery } from '@apollo/client'
|
||||||
import Button from 'react-bootstrap/Button'
|
|
||||||
import { useState } from 'react'
|
|
||||||
import Comment, { CommentSkeleton } from './comment'
|
import Comment, { CommentSkeleton } from './comment'
|
||||||
import Item from './item'
|
import Item from './item'
|
||||||
import { NOTIFICATIONS } from '../fragments/notifications'
|
import { NOTIFICATIONS } from '../fragments/notifications'
|
||||||
import styles from './notifications.module.css'
|
import styles from './notifications.module.css'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import MoreFooter from './more-footer'
|
||||||
|
|
||||||
function Notification ({ n }) {
|
function Notification ({ n }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@ -44,18 +43,16 @@ function Notification ({ n }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Notifications ({ variables }) {
|
export default function Notifications ({ notifications, cursor, lastChecked, variables }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { error, data, fetchMore } = useQuery(NOTIFICATIONS, {
|
const { data, fetchMore } = useQuery(NOTIFICATIONS, {
|
||||||
variables,
|
variables,
|
||||||
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
||||||
})
|
})
|
||||||
if (error) return <div>Failed to load!</div>
|
|
||||||
if (!data) {
|
|
||||||
return <CommentsFlatSkeleton />
|
|
||||||
}
|
|
||||||
|
|
||||||
const { notifications: { notifications, cursor, lastChecked } } = data
|
if (data) {
|
||||||
|
({ notifications: { notifications, cursor } } = data)
|
||||||
|
}
|
||||||
|
|
||||||
const [fresh, old] =
|
const [fresh, old] =
|
||||||
notifications.reduce((result, n) => {
|
notifications.reduce((result, n) => {
|
||||||
@ -75,7 +72,7 @@ export default function Notifications ({ variables }) {
|
|||||||
{old.map((n, i) => (
|
{old.map((n, i) => (
|
||||||
<Notification n={n} key={i} />
|
<Notification n={n} key={i} />
|
||||||
))}
|
))}
|
||||||
<MoreFooter cursor={cursor} fetchMore={fetchMore} />
|
<MoreFooter cursor={cursor} fetchMore={fetchMore} Skeleton={CommentsFlatSkeleton} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -90,37 +87,3 @@ function CommentsFlatSkeleton () {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function MoreFooter ({ cursor, fetchMore }) {
|
|
||||||
const [loading, setLoading] = useState(false)
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <div><CommentsFlatSkeleton /></div>
|
|
||||||
}
|
|
||||||
|
|
||||||
let Footer
|
|
||||||
if (cursor) {
|
|
||||||
Footer = () => (
|
|
||||||
<Button
|
|
||||||
variant='primary'
|
|
||||||
size='md'
|
|
||||||
onClick={async () => {
|
|
||||||
setLoading(true)
|
|
||||||
await fetchMore({
|
|
||||||
variables: {
|
|
||||||
cursor
|
|
||||||
}
|
|
||||||
})
|
|
||||||
setLoading(false)
|
|
||||||
}}
|
|
||||||
>more
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Footer = () => (
|
|
||||||
<div className='text-muted' style={{ fontFamily: 'lightning', fontSize: '2rem', opacity: '0.6' }}>GENISIS</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className='d-flex justify-content-center mt-4 mb-2'><Footer /></div>
|
|
||||||
}
|
|
||||||
|
@ -42,7 +42,7 @@ export default function UserHeader ({ user }) {
|
|||||||
name: 'name',
|
name: 'name',
|
||||||
test: async name => {
|
test: async name => {
|
||||||
if (!name || !name.length) return false
|
if (!name || !name.length) return false
|
||||||
const { data } = await client.query({ query: NAME_QUERY, variables: { name } })
|
const { data } = await client.query({ query: NAME_QUERY, variables: { name }, fetchPolicy: 'network-only' })
|
||||||
return data.nameAvailable
|
return data.nameAvailable
|
||||||
},
|
},
|
||||||
message: 'taken'
|
message: 'taken'
|
||||||
@ -69,7 +69,10 @@ export default function UserHeader ({ user }) {
|
|||||||
if (error) {
|
if (error) {
|
||||||
throw new Error({ message: error.toString() })
|
throw new Error({ message: error.toString() })
|
||||||
}
|
}
|
||||||
router.replace(`/${name}`)
|
router.replace({
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: { ...router.query, username: name }
|
||||||
|
})
|
||||||
|
|
||||||
client.writeFragment({
|
client.writeFragment({
|
||||||
id: `User:${user.id}`,
|
id: `User:${user.id}`,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { gql } from '@apollo/client'
|
import { gql } from '@apollo/client'
|
||||||
|
import { COMMENTS } from './comments'
|
||||||
|
|
||||||
export const ITEM_FIELDS = gql`
|
export const ITEM_FIELDS = gql`
|
||||||
fragment ItemFields on Item {
|
fragment ItemFields on Item {
|
||||||
@ -36,20 +37,26 @@ export const MORE_ITEMS = gql`
|
|||||||
}
|
}
|
||||||
} `
|
} `
|
||||||
|
|
||||||
export const ITEMS_FEED = gql`
|
export const ITEM_FULL = id => gql`
|
||||||
${ITEM_FIELDS}
|
${ITEM_FIELDS}
|
||||||
|
${COMMENTS}
|
||||||
{
|
{
|
||||||
items {
|
item(id: ${id}) {
|
||||||
...ItemFields
|
...ItemFields
|
||||||
|
text
|
||||||
|
comments {
|
||||||
|
...CommentsRecursive
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
export const ITEMS_RECENT = gql`
|
export const ITEM_WITH_COMMENTS = gql`
|
||||||
${ITEM_FIELDS}
|
${ITEM_FIELDS}
|
||||||
|
${COMMENTS}
|
||||||
{
|
fragment ItemWithComments on Item {
|
||||||
items: recent {
|
|
||||||
...ItemFields
|
...ItemFields
|
||||||
|
text
|
||||||
|
comments {
|
||||||
|
...CommentsRecursive
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { gql } from '@apollo/client'
|
import { gql } from '@apollo/client'
|
||||||
import { ITEM_FIELDS } from './items'
|
import { ITEM_FIELDS, ITEM_WITH_COMMENTS } from './items'
|
||||||
|
|
||||||
export const USER_FIELDS = gql`
|
export const USER_FIELDS = gql`
|
||||||
${ITEM_FIELDS}
|
${ITEM_FIELDS}
|
||||||
@ -16,3 +16,15 @@ export const USER_FIELDS = gql`
|
|||||||
text
|
text
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
|
export const USER_FULL = name => gql`
|
||||||
|
${USER_FIELDS}
|
||||||
|
${ITEM_WITH_COMMENTS}
|
||||||
|
{
|
||||||
|
user(name: "${name}") {
|
||||||
|
...UserFields
|
||||||
|
bio {
|
||||||
|
...ItemWithComments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
@ -13,13 +13,13 @@ function isFirstPage (cursor, existing) {
|
|||||||
return decursor.offset === LIMIT
|
return decursor.offset === LIMIT
|
||||||
} else {
|
} else {
|
||||||
// we don't have anything cached, or our existing items are less than
|
// we don't have anything cached, or our existing items are less than
|
||||||
// or equal to a full page TODO test for off by one
|
// or equal to a full page
|
||||||
return !existing || !existing.items || existing.items.length < LIMIT
|
return !existing || !existing.items || existing.items.length < LIMIT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new ApolloClient({
|
export default function getApolloClient () {
|
||||||
uri: '/api/graphql',
|
global.apolloClient ||= new ApolloClient({
|
||||||
link: additiveLink,
|
link: additiveLink,
|
||||||
cache: new InMemoryCache({
|
cache: new InMemoryCache({
|
||||||
typePolicies: {
|
typePolicies: {
|
||||||
@ -74,6 +74,13 @@ export default new ApolloClient({
|
|||||||
watchQuery: {
|
watchQuery: {
|
||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
nextFetchPolicy: 'cache-first'
|
nextFetchPolicy: 'cache-first'
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
|
nextFetchPolicy: 'cache-first'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return global.apolloClient
|
||||||
|
}
|
||||||
|
5240
package-lock.json
generated
5240
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -9,7 +9,7 @@
|
|||||||
"start": "NODE_OPTIONS='--trace-warnings' next start -p $PORT"
|
"start": "NODE_OPTIONS='--trace-warnings' next start -p $PORT"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.3.13",
|
"@apollo/client": "^3.4.15",
|
||||||
"@prisma/client": "^2.23.0",
|
"@prisma/client": "^2.23.0",
|
||||||
"apollo-server-micro": "^2.21.2",
|
"apollo-server-micro": "^2.21.2",
|
||||||
"async-retry": "^1.3.1",
|
"async-retry": "^1.3.1",
|
||||||
@ -20,20 +20,20 @@
|
|||||||
"domino": "^2.1.6",
|
"domino": "^2.1.6",
|
||||||
"formik": "^2.2.6",
|
"formik": "^2.2.6",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"ln-service": "^51.7.0",
|
"ln-service": "^52.8.0",
|
||||||
"mdast-util-find-and-replace": "^1.1.1",
|
"mdast-util-find-and-replace": "^1.1.1",
|
||||||
"next": "^10.2.3",
|
"next": "^11.1.2",
|
||||||
"next-auth": "^3.13.3",
|
"next-auth": "^3.13.3",
|
||||||
"next-plausible": "^2.0.0",
|
"next-plausible": "^2.1.3",
|
||||||
"next-seo": "^4.24.0",
|
"next-seo": "^4.24.0",
|
||||||
"page-metadata-parser": "^1.1.4",
|
"page-metadata-parser": "^1.1.4",
|
||||||
"pageres": "^6.2.3",
|
"pageres": "^6.2.3",
|
||||||
"prisma": "^2.25.0",
|
"prisma": "^2.25.0",
|
||||||
"qrcode.react": "^1.0.1",
|
"qrcode.react": "^1.0.1",
|
||||||
"react": "17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-bootstrap": "^1.5.2",
|
"react-bootstrap": "^1.5.2",
|
||||||
"react-countdown": "^2.3.2",
|
"react-countdown": "^2.3.2",
|
||||||
"react-dom": "17.0.1",
|
"react-dom": "^17.0.2",
|
||||||
"react-markdown": "^6.0.2",
|
"react-markdown": "^6.0.2",
|
||||||
"react-syntax-highlighter": "^15.4.3",
|
"react-syntax-highlighter": "^15.4.3",
|
||||||
"react-textarea-autosize": "^8.3.3",
|
"react-textarea-autosize": "^8.3.3",
|
||||||
|
@ -1,45 +1,64 @@
|
|||||||
import Layout from '../../components/layout'
|
import Layout from '../../components/layout'
|
||||||
import { gql } from '@apollo/client'
|
import { useQuery } from '@apollo/client'
|
||||||
import ApolloClient from '../../api/client'
|
|
||||||
import UserHeader from '../../components/user-header'
|
import UserHeader from '../../components/user-header'
|
||||||
import CommentsFlat from '../../components/comments-flat'
|
import CommentsFlat from '../../components/comments-flat'
|
||||||
import Seo from '../../components/seo'
|
import Seo from '../../components/seo'
|
||||||
|
import { USER_FULL } from '../../fragments/users'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { MORE_FLAT_COMMENTS } from '../../fragments/comments'
|
||||||
|
import { getServerSideProps as headerProps } from './index'
|
||||||
|
import getSSRApolloClient from '../../api/ssrApollo'
|
||||||
|
|
||||||
export async function getServerSideProps ({ req, params }) {
|
export async function getServerSideProps ({ req, params: { username } }) {
|
||||||
const { error, data: { user } } = await (await ApolloClient(req)).query({
|
const { notFound, props } = await headerProps({ req, params: { username } })
|
||||||
query:
|
|
||||||
gql`{
|
if (notFound) {
|
||||||
user(name: "${params.username}") {
|
return {
|
||||||
id
|
notFound
|
||||||
createdAt
|
|
||||||
name
|
|
||||||
nitems
|
|
||||||
ncomments
|
|
||||||
stacked
|
|
||||||
sats
|
|
||||||
}
|
}
|
||||||
}`
|
}
|
||||||
|
|
||||||
|
const { user } = props
|
||||||
|
const client = await getSSRApolloClient(req)
|
||||||
|
const { data } = await client.query({
|
||||||
|
query: MORE_FLAT_COMMENTS,
|
||||||
|
variables: { userId: user.id }
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!user || error) {
|
let comments, cursor
|
||||||
return {
|
if (data) {
|
||||||
notFound: true
|
({ moreFlatComments: { comments, cursor } } = data)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
user
|
...props,
|
||||||
|
comments,
|
||||||
|
cursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function UserComments ({ user }) {
|
export default function UserComments ({ user, comments, cursor }) {
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const { data } = useQuery(
|
||||||
|
USER_FULL(user.name), {
|
||||||
|
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
({ user } = data)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout noSeo>
|
<Layout noSeo>
|
||||||
<Seo user={user} />
|
<Seo user={user} />
|
||||||
<UserHeader user={user} />
|
<UserHeader user={user} />
|
||||||
<CommentsFlat variables={{ userId: user.id }} includeParent noReply />
|
<CommentsFlat
|
||||||
|
comments={comments} cursor={cursor}
|
||||||
|
variables={{ userId: user.id }} includeParent noReply
|
||||||
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,28 @@
|
|||||||
import Layout from '../components/layout'
|
import Layout from '../../components/layout'
|
||||||
import { gql, useMutation, useQuery } from '@apollo/client'
|
import { gql, useMutation, useQuery } from '@apollo/client'
|
||||||
import ApolloClient from '../api/client'
|
import UserHeader from '../../components/user-header'
|
||||||
import UserHeader from '../components/user-header'
|
import Seo from '../../components/seo'
|
||||||
import Seo from '../components/seo'
|
|
||||||
import { Button } from 'react-bootstrap'
|
import { Button } from 'react-bootstrap'
|
||||||
import styles from '../styles/user.module.css'
|
import styles from '../../styles/user.module.css'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import ItemFull from '../components/item-full'
|
import ItemFull from '../../components/item-full'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { Form, MarkdownInput, SubmitButton } from '../components/form'
|
import { Form, MarkdownInput, SubmitButton } from '../../components/form'
|
||||||
import ActionTooltip from '../components/action-tooltip'
|
import ActionTooltip from '../../components/action-tooltip'
|
||||||
import TextareaAutosize from 'react-textarea-autosize'
|
import TextareaAutosize from 'react-textarea-autosize'
|
||||||
import { useMe } from '../components/me'
|
import { useMe } from '../../components/me'
|
||||||
import { USER_FIELDS } from '../fragments/users'
|
import { USER_FULL } from '../../fragments/users'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { ITEM_FIELDS } from '../fragments/items'
|
import { ITEM_FIELDS } from '../../fragments/items'
|
||||||
|
import getSSRApolloClient from '../../api/ssrApollo'
|
||||||
|
|
||||||
export async function getServerSideProps ({ req, params }) {
|
export async function getServerSideProps ({ req, params: { username } }) {
|
||||||
const { error, data: { user } } = await (await ApolloClient(req)).query({
|
const client = await getSSRApolloClient(req)
|
||||||
query:
|
const { error, data } = await client.query({
|
||||||
gql`
|
query: USER_FULL(username)
|
||||||
${USER_FIELDS}
|
|
||||||
{
|
|
||||||
user(name: "${params.username}") {
|
|
||||||
...UserFields
|
|
||||||
}
|
|
||||||
}`
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!user || error) {
|
if (error || !data?.user) {
|
||||||
return {
|
return {
|
||||||
notFound: true
|
notFound: true
|
||||||
}
|
}
|
||||||
@ -36,7 +30,7 @@ export async function getServerSideProps ({ req, params }) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
user
|
user: data.user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,24 +97,12 @@ export default function User ({ user }) {
|
|||||||
const [create, setCreate] = useState(false)
|
const [create, setCreate] = useState(false)
|
||||||
const [edit, setEdit] = useState(false)
|
const [edit, setEdit] = useState(false)
|
||||||
const me = useMe()
|
const me = useMe()
|
||||||
|
|
||||||
const query = gql`
|
|
||||||
${USER_FIELDS}
|
|
||||||
{
|
|
||||||
user(name: "${user.name}") {
|
|
||||||
...UserFields
|
|
||||||
}
|
|
||||||
}`
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { error, data } = useQuery(query, {
|
|
||||||
|
const { data } = useQuery(USER_FULL(user.name), {
|
||||||
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
||||||
})
|
})
|
||||||
if (error) {
|
|
||||||
return <div>Failed to load!</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX replace item with cache version
|
|
||||||
if (data) {
|
if (data) {
|
||||||
({ user } = data)
|
({ user } = data)
|
||||||
}
|
}
|
@ -1,45 +1,64 @@
|
|||||||
import Layout from '../../components/layout'
|
import Layout from '../../components/layout'
|
||||||
import { gql } from '@apollo/client'
|
import { useQuery } from '@apollo/client'
|
||||||
import ApolloClient from '../../api/client'
|
|
||||||
import UserHeader from '../../components/user-header'
|
import UserHeader from '../../components/user-header'
|
||||||
import Seo from '../../components/seo'
|
import Seo from '../../components/seo'
|
||||||
import Items from '../../components/items'
|
import Items from '../../components/items'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { USER_FULL } from '../../fragments/users'
|
||||||
|
import { getServerSideProps as headerProps } from './index'
|
||||||
|
import getSSRApolloClient from '../../api/ssrApollo'
|
||||||
|
import { MORE_ITEMS } from '../../fragments/items'
|
||||||
|
|
||||||
export async function getServerSideProps ({ req, params }) {
|
export async function getServerSideProps ({ req, params: { username } }) {
|
||||||
const { error, data: { user } } = await (await ApolloClient(req)).query({
|
const { notFound, props } = await headerProps({ req, params: { username } })
|
||||||
query:
|
|
||||||
gql`{
|
if (notFound) {
|
||||||
user(name: "${params.username}") {
|
return {
|
||||||
id
|
notFound
|
||||||
createdAt
|
|
||||||
name
|
|
||||||
nitems
|
|
||||||
ncomments
|
|
||||||
stacked
|
|
||||||
sats
|
|
||||||
}
|
}
|
||||||
}`
|
}
|
||||||
|
|
||||||
|
const { user } = props
|
||||||
|
const client = await getSSRApolloClient(req)
|
||||||
|
const { data } = await client.query({
|
||||||
|
query: MORE_ITEMS,
|
||||||
|
variables: { sort: 'user', userId: user.id }
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!user || error) {
|
let items, cursor
|
||||||
return {
|
if (data) {
|
||||||
notFound: true
|
({ moreItems: { items, cursor } } = data)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
user
|
...props,
|
||||||
|
items,
|
||||||
|
cursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function UserPosts ({ user }) {
|
export default function UserPosts ({ user, items, cursor }) {
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const { data } = useQuery(
|
||||||
|
USER_FULL(user.name), {
|
||||||
|
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
({ user } = data)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout noSeo>
|
<Layout noSeo>
|
||||||
<Seo user={user} />
|
<Seo user={user} />
|
||||||
<UserHeader user={user} />
|
<UserHeader user={user} />
|
||||||
<Items variables={{ sort: 'user', userId: user.id }} />
|
<Items
|
||||||
|
items={items} cursor={cursor}
|
||||||
|
variables={{ sort: 'user', userId: user.id }}
|
||||||
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,14 @@ import { FundErrorModal, FundErrorProvider } from '../components/fund-error'
|
|||||||
import { MeProvider } from '../components/me'
|
import { MeProvider } from '../components/me'
|
||||||
import PlausibleProvider from 'next-plausible'
|
import PlausibleProvider from 'next-plausible'
|
||||||
import { LightningProvider } from '../components/lightning'
|
import { LightningProvider } from '../components/lightning'
|
||||||
import apolloClient from '../lib/apollo'
|
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { ItemActModal, ItemActProvider } from '../components/item-act'
|
import { ItemActModal, ItemActProvider } from '../components/item-act'
|
||||||
|
import getApolloClient from '../lib/apollo'
|
||||||
|
|
||||||
function MyApp ({ Component, pageProps }) {
|
function MyApp ({ Component, pageProps: { session, ...props } }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
router.beforePopState(({ url, as, options }) => {
|
router.beforePopState(({ url, as, options }) => {
|
||||||
// we need to tell the next page to use a cache-first fetch policy ...
|
// we need to tell the next page to use a cache-first fetch policy ...
|
||||||
@ -25,15 +26,15 @@ function MyApp ({ Component, pageProps }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PlausibleProvider domain='stacker.news' trackOutboundLinks>
|
<PlausibleProvider domain='stacker.news' trackOutboundLinks>
|
||||||
<Provider session={pageProps.session}>
|
<Provider session={session}>
|
||||||
<ApolloProvider client={apolloClient}>
|
<ApolloProvider client={getApolloClient()}>
|
||||||
<MeProvider>
|
<MeProvider>
|
||||||
<LightningProvider>
|
<LightningProvider>
|
||||||
<FundErrorProvider>
|
<FundErrorProvider>
|
||||||
<FundErrorModal />
|
<FundErrorModal />
|
||||||
<ItemActProvider>
|
<ItemActProvider>
|
||||||
<ItemActModal />
|
<ItemActModal />
|
||||||
<Component {...pageProps} />
|
<Component {...props} />
|
||||||
</ItemActProvider>
|
</ItemActProvider>
|
||||||
</FundErrorProvider>
|
</FundErrorProvider>
|
||||||
</LightningProvider>
|
</LightningProvider>
|
||||||
|
@ -6,7 +6,7 @@ export default async function handler (req, res) {
|
|||||||
res.setHeader('Content-Type', 'image/png')
|
res.setHeader('Content-Type', 'image/png')
|
||||||
try {
|
try {
|
||||||
const streams = await new Pageres({ crop: true })
|
const streams = await new Pageres({ crop: true })
|
||||||
.src(url, ['600x300'])
|
.src(url, ['600x314'])
|
||||||
.run()
|
.run()
|
||||||
res.status(200).end(streams[0])
|
res.status(200).end(streams[0])
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
@ -5,7 +5,7 @@ import lnd from '../../api/lnd'
|
|||||||
import typeDefs from '../../api/typeDefs'
|
import typeDefs from '../../api/typeDefs'
|
||||||
import { getSession } from 'next-auth/client'
|
import { getSession } from 'next-auth/client'
|
||||||
|
|
||||||
const apolloServer = new ApolloServer({
|
global.apolloServer ||= new ApolloServer({
|
||||||
typeDefs,
|
typeDefs,
|
||||||
resolvers,
|
resolvers,
|
||||||
tracing: true,
|
tracing: true,
|
||||||
@ -25,4 +25,4 @@ export const config = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default apolloServer.createHandler({ path: '/api/graphql' })
|
export default global.apolloServer.createHandler({ path: '/api/graphql' })
|
||||||
|
@ -1,12 +1,37 @@
|
|||||||
import Layout from '../components/layout'
|
import Layout from '../components/layout'
|
||||||
import Items from '../components/items'
|
import Items from '../components/items'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import getSSRApolloClient from '../api/ssrApollo'
|
||||||
|
import { MORE_ITEMS } from '../fragments/items'
|
||||||
|
|
||||||
export default function Index () {
|
export async function getServerSideProps ({ req }) {
|
||||||
|
const client = await getSSRApolloClient(req)
|
||||||
|
const { data } = await client.query({
|
||||||
|
query: MORE_ITEMS,
|
||||||
|
variables: { sort: 'hot' }
|
||||||
|
})
|
||||||
|
|
||||||
|
let items, cursor
|
||||||
|
if (data) {
|
||||||
|
({ moreItems: { items, cursor } } = data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
items,
|
||||||
|
cursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Index ({ items, cursor }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<Items variables={{ sort: 'hot' }} rank key={router.query.key} />
|
<Items
|
||||||
|
items={items} cursor={cursor}
|
||||||
|
variables={{ sort: 'hot' }} rank key={router.query.key}
|
||||||
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
import Layout from '../../components/layout'
|
|
||||||
import { ITEM_FIELDS } from '../../fragments/items'
|
|
||||||
import { gql } from '@apollo/client'
|
|
||||||
import Seo from '../../components/seo'
|
|
||||||
import ApolloClient from '../../api/client'
|
|
||||||
import ItemFull from '../../components/item-full'
|
|
||||||
|
|
||||||
// ssr the item without comments so that we can populate metatags
|
|
||||||
export async function getServerSideProps ({ req, params: { id } }) {
|
|
||||||
if (isNaN(id)) {
|
|
||||||
return {
|
|
||||||
notFound: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { error, data: { item } } = await (await ApolloClient(req)).query({
|
|
||||||
query:
|
|
||||||
gql`
|
|
||||||
${ITEM_FIELDS}
|
|
||||||
{
|
|
||||||
item(id: ${id}) {
|
|
||||||
...ItemFields
|
|
||||||
text
|
|
||||||
}
|
|
||||||
}`
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!item || error) {
|
|
||||||
return {
|
|
||||||
notFound: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function AnItem ({ item }) {
|
|
||||||
return (
|
|
||||||
<Layout noSeo>
|
|
||||||
<Seo item={item} />
|
|
||||||
<ItemFull item={item} />
|
|
||||||
</Layout>
|
|
||||||
)
|
|
||||||
}
|
|
@ -18,7 +18,7 @@ export async function getServerSideProps ({ req, params: { id } }) {
|
|||||||
}`
|
}`
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!item || error) {
|
if (error || !item) {
|
||||||
return {
|
return {
|
||||||
notFound: true
|
notFound: true
|
||||||
}
|
}
|
||||||
|
49
pages/items/[id]/index.js
Normal file
49
pages/items/[id]/index.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import Layout from '../../../components/layout'
|
||||||
|
import { ITEM_FULL } from '../../../fragments/items'
|
||||||
|
import Seo from '../../../components/seo'
|
||||||
|
import ItemFull from '../../../components/item-full'
|
||||||
|
import getSSRApolloClient from '../../../api/ssrApollo'
|
||||||
|
import { useQuery } from '@apollo/client'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
|
export async function getServerSideProps ({ req, params: { id } }) {
|
||||||
|
if (isNaN(id)) {
|
||||||
|
return {
|
||||||
|
notFound: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = await getSSRApolloClient(req)
|
||||||
|
const { error, data } = await client.query({
|
||||||
|
query: ITEM_FULL(id)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (error || !data?.item) {
|
||||||
|
return {
|
||||||
|
notFound: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
item: data.item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AnItem ({ item }) {
|
||||||
|
const router = useRouter()
|
||||||
|
const { data } = useQuery(ITEM_FULL(item.id), {
|
||||||
|
fetchPolicy: router.query.cache ? 'cache-first' : undefined
|
||||||
|
})
|
||||||
|
if (data) {
|
||||||
|
({ item } = data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout noSeo>
|
||||||
|
<Seo item={item} />
|
||||||
|
<ItemFull item={item} />
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
@ -1,12 +1,37 @@
|
|||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import getSSRApolloClient from '../api/ssrApollo'
|
||||||
import Layout from '../components/layout'
|
import Layout from '../components/layout'
|
||||||
import Notifications from '../components/notifications'
|
import Notifications from '../components/notifications'
|
||||||
|
import { NOTIFICATIONS } from '../fragments/notifications'
|
||||||
|
|
||||||
export default function NotificationPage () {
|
export async function getServerSideProps ({ req }) {
|
||||||
|
const client = await getSSRApolloClient(req)
|
||||||
|
const { data } = await client.query({
|
||||||
|
query: NOTIFICATIONS
|
||||||
|
})
|
||||||
|
|
||||||
|
let notifications, cursor, lastChecked
|
||||||
|
if (data) {
|
||||||
|
({ notifications: { notifications, cursor, lastChecked } } = data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
notifications,
|
||||||
|
cursor,
|
||||||
|
lastChecked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function NotificationPage ({ notifications, cursor, lastChecked }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<Notifications key={router.query.key} />
|
<Notifications
|
||||||
|
notifications={notifications} cursor={cursor}
|
||||||
|
lastChecked={lastChecked} key={router.query.key}
|
||||||
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,13 @@ import { useMe } from '../components/me'
|
|||||||
import { DiscussionForm } from '../components/discussion-form'
|
import { DiscussionForm } from '../components/discussion-form'
|
||||||
import { LinkForm } from '../components/link-form'
|
import { LinkForm } from '../components/link-form'
|
||||||
|
|
||||||
|
export async function getServerSideProps () {
|
||||||
|
return {
|
||||||
|
props: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function PostForm () {
|
export function PostForm () {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const me = useMe()
|
const me = useMe()
|
||||||
|
@ -1,12 +1,37 @@
|
|||||||
import Layout from '../components/layout'
|
import Layout from '../components/layout'
|
||||||
import Items from '../components/items'
|
import Items from '../components/items'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import getSSRApolloClient from '../api/ssrApollo'
|
||||||
|
import { MORE_ITEMS } from '../fragments/items'
|
||||||
|
|
||||||
export default function Index () {
|
export async function getServerSideProps ({ req }) {
|
||||||
|
const client = await getSSRApolloClient(req)
|
||||||
|
const { data } = await client.query({
|
||||||
|
query: MORE_ITEMS,
|
||||||
|
variables: { sort: 'recent' }
|
||||||
|
})
|
||||||
|
|
||||||
|
let items, cursor
|
||||||
|
if (data) {
|
||||||
|
({ moreItems: { items, cursor } } = data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
items,
|
||||||
|
cursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Index ({ items, cursor }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<Items variables={{ sort: 'recent' }} rank key={router.query.key} />
|
<Items
|
||||||
|
items={items} cursor={cursor}
|
||||||
|
variables={{ sort: 'recent' }} rank key={router.query.key}
|
||||||
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,12 @@ import { useMe } from '../components/me'
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { requestProvider } from 'webln'
|
import { requestProvider } from 'webln'
|
||||||
|
|
||||||
|
export async function getServerSideProps () {
|
||||||
|
return {
|
||||||
|
props: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function Wallet () {
|
export default function Wallet () {
|
||||||
return (
|
return (
|
||||||
<LayoutCenter>
|
<LayoutCenter>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user