This commit is contained in:
amirhouieh 2023-05-13 12:23:52 +02:00 committed by Jinho Jang
parent 428a66638f
commit 3e5e136be5
6 changed files with 106 additions and 62 deletions

View File

@ -1,11 +1,13 @@
import Link from 'next/link' import Link from 'next/link'
import { useState } from 'react' import { useEffect, useState } from 'react'
import { Grid, GridItem } from '../Grid/Grid' import { Grid, GridItem } from '../Grid/Grid'
import styled from '@emotion/styled' import styled from '@emotion/styled'
import Post, { PostDataProps } from '../Post/Post' import Post, { PostDataProps } from '../Post/Post'
import { Button, Typography } from '@acid-info/lsd-react'
type Props = { type Props = {
posts: PostDataProps[] posts: PostDataProps[]
pageSize?: number
} }
const getGridItemWidth = (index: number) => { const getGridItemWidth = (index: number) => {
@ -21,20 +23,46 @@ const getGridItemWidth = (index: number) => {
} }
export const PostsList = (props: Props) => { export const PostsList = (props: Props) => {
const { pageSize = 6 } = props
const [posts, setPosts] = useState<PostDataProps[]>(props.posts) const [posts, setPosts] = useState<PostDataProps[]>(props.posts)
const [page, setPage] = useState(1)
useEffect(() => {
setPosts(props.posts)
}, [props.posts])
const handleMoreOrLess = () => {
const dir = page * pageSize < posts.length ? 1 : -1
setPage(
Math.max(1, Math.min(page + dir, Math.ceil(posts.length / pageSize))),
)
}
const postsToShow = posts.slice(0, page * pageSize)
return ( return (
<Grid> <div>
{posts.map((post, index) => ( <Grid style={{ minHeight: '500px' }}>
<GridItem className="w-4" key={index}> {postsToShow.length > 0 ? (
<PostLink href={`/article/${post.slug}`}> postsToShow.map((post, index) => (
<PostWrapper> <GridItem className="w-4" key={index}>
<Post data={post} /> <PostLink href={`/article/${post.slug}`}>
</PostWrapper> <PostWrapper>
</PostLink> <Post data={post} />
</GridItem> </PostWrapper>
))} </PostLink>
</Grid> </GridItem>
))
) : (
<GridItem className="w-12">
<Typography variant="body1">No related articles found.</Typography>
</GridItem>
)}
</Grid>
<Button onClick={() => handleMoreOrLess()}>
{page * pageSize < posts.length ? 'Load More' : 'Show Less'}
</Button>
</div>
) )
} }

View File

@ -3,28 +3,40 @@ import { Typography } from '@acid-info/lsd-react'
import styled from '@emotion/styled' import styled from '@emotion/styled'
import { PostsList } from '../PostList/PostList' import { PostsList } from '../PostList/PostList'
import { Section } from '../Section/Section' import { Section } from '../Section/Section'
import { SearchResultItem } from '@/types/data.types' import { SearchHook, SearchResultItem } from '@/types/data.types'
import { UnbodyGoogleDoc } from '@/lib/unbody/unbody.types' import { UnbodyGoogleDoc } from '@/lib/unbody/unbody.types'
type Props = { type Props = {
articles: SearchResultItem<UnbodyGoogleDoc>[] data: SearchHook<UnbodyGoogleDoc>
} }
export default function RelatedArticles({ articles }: Props) { export default function RelatedArticles({ data }: Props) {
if (!data.loading && !data.data) return null
return ( return (
<Container> <Container>
<Section title={'Related Articles'} matches={articles?.length}> <Section
<PostsList title={data.loading ? 'Loading...' : 'Related Articles'}
posts={articles.map((article) => ({ matches={data.loading ? undefined : data.data.length}
slug: article.doc.slug, >
date: article.doc.modifiedAt, {
title: article.doc.title, <PostsList
description: article.doc.subtitle, // TODO: summary is not available posts={
mentions: article.doc.mentions, data.loading
tags: article.doc.tags, ? []
coverImage: getArticleCover(article.doc.blocks), : data.data.map((article) => ({
}))} slug: article.doc.slug,
/> date: article.doc.modifiedAt,
title: article.doc.title,
description: article.doc.subtitle, // TODO: summary is not available
mentions: article.doc.mentions,
tags: article.doc.tags,
coverImage: getArticleCover(article.doc.blocks),
}))
}
pageSize={4}
/>
}
</Section> </Section>
</Container> </Container>
) )

View File

@ -4,7 +4,7 @@ import { PropsWithChildren } from 'react'
type Props = PropsWithChildren<{ type Props = PropsWithChildren<{
title: string title: string
matches?: number matches?: number | string
}> }>
export const Section = ({ title, matches, children, ...props }: Props) => { export const Section = ({ title, matches, children, ...props }: Props) => {

View File

@ -72,16 +72,8 @@ export default function SearchPage({
return ( return (
<div> <div>
{articles.data?.length ? ( <RelatedArticles data={articles} />
<RelatedArticles articles={articles.data} /> {blocks.data?.length && <RelatedContent blocks={blocks.data} />}
) : (
<Section title={'No Related Articles'} />
)}
{blocks.data?.length ? (
<RelatedContent blocks={blocks.data} />
) : (
<Section title={'No Related Content'} />
)}
</div> </div>
) )
} }

View File

@ -22,5 +22,6 @@ export const getSearchArticlesQuery = (args: UnbodyGetFilters = defaultArgs) =>
} }
_additional{ _additional{
certainty certainty
score
} }
`) `)

View File

@ -146,6 +146,13 @@ const enhanceGoogleDoc = (doc: UnbodyGoogleDoc): GoogleDocEnhanced => ({
: [], : [],
}) })
const resolveScore = (_additional: any): number => {
if (!_additional) {
return 0
}
return _additional.certainty || parseFloat(_additional.score)
}
const enhanceTextBlock = (block: UnbodyTextBlock): TextBlockEnhanced => ({ const enhanceTextBlock = (block: UnbodyTextBlock): TextBlockEnhanced => ({
...block, ...block,
footnotes: footnotes:
@ -357,8 +364,6 @@ class UnbodyService extends UnbodyClient {
): Promise< ): Promise<
ApiResponse<SearchResultItem<UnbodyImageBlock | UnbodyTextBlock>[]> ApiResponse<SearchResultItem<UnbodyImageBlock | UnbodyTextBlock>[]>
> => { > => {
let whereFilters: any = []
const query = getSearchBlocksQuery({ const query = getSearchBlocksQuery({
...(q.trim().length > 0 ...(q.trim().length > 0
? { ? {
@ -401,6 +406,8 @@ class UnbodyService extends UnbodyClient {
published: boolean = true, published: boolean = true,
): Promise<ApiResponse<SearchResultItem<GoogleDocEnhanced>[]>> => { ): Promise<ApiResponse<SearchResultItem<GoogleDocEnhanced>[]>> => {
let queryFilters = {} let queryFilters = {}
let whereFilters: any = []
if (q.trim().length > 0) { if (q.trim().length > 0) {
queryFilters = { queryFilters = {
nearText: { nearText: {
@ -409,28 +416,32 @@ class UnbodyService extends UnbodyClient {
} }
} }
if (tags.length > 0) { // if publushed is true, we add the published filter
queryFilters = { // if published is false, we don't add the published filter
...queryFilters, // if tags empty, we don't add the tags filter
where: { // if tags not empty, we add the tags filter
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.And,
operands: tags.map((tag) => ({
path: ['tags'],
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.Like,
valueString: tag,
})),
},
}
}
if (published) { if (published) {
queryFilters = { whereFilters.push(Operands.WHERE_PUBLISHED())
...queryFilters, }
where: {
...((queryFilters as any).where || {}), if (tags.length > 0) {
...Operands.WHERE_PUBLISHED(), whereFilters.push({
}, operator: UnbodyGraphQl.Filters.WhereOperatorEnum.And,
} operands: tags.map((tag) => ({
path: ['tags'],
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.Like,
valueString: tag.toLowerCase(),
})),
})
}
queryFilters = {
...queryFilters,
where: {
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.And,
operands: whereFilters,
},
} }
const query = getSearchArticlesQuery(queryFilters) const query = getSearchArticlesQuery(queryFilters)
@ -439,11 +450,11 @@ class UnbodyService extends UnbodyClient {
.then(({ data }) => { .then(({ data }) => {
if (!data || !data.Get.GoogleDoc) if (!data || !data.Get.GoogleDoc)
return this.handleResponse([], 'No data') return this.handleResponse([], 'No data')
return this.handleResponse( return this.handleResponse(
data.Get.GoogleDoc.map((item) => ({ data.Get.GoogleDoc.map((item) => ({
doc: enhanceGoogleDoc(item), doc: enhanceGoogleDoc(item),
score: score: resolveScore(item._additional),
q.length > 0 || tags.length > 0 ? item._additional.certainty : 0,
})), })),
) )
}) })