close #35
This commit is contained in:
parent
428a66638f
commit
3e5e136be5
|
@ -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,11 +23,28 @@ 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' }}>
|
||||||
|
{postsToShow.length > 0 ? (
|
||||||
|
postsToShow.map((post, index) => (
|
||||||
<GridItem className="w-4" key={index}>
|
<GridItem className="w-4" key={index}>
|
||||||
<PostLink href={`/article/${post.slug}`}>
|
<PostLink href={`/article/${post.slug}`}>
|
||||||
<PostWrapper>
|
<PostWrapper>
|
||||||
|
@ -33,8 +52,17 @@ export const PostsList = (props: Props) => {
|
||||||
</PostWrapper>
|
</PostWrapper>
|
||||||
</PostLink>
|
</PostLink>
|
||||||
</GridItem>
|
</GridItem>
|
||||||
))}
|
))
|
||||||
|
) : (
|
||||||
|
<GridItem className="w-12">
|
||||||
|
<Typography variant="body1">No related articles found.</Typography>
|
||||||
|
</GridItem>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Button onClick={() => handleMoreOrLess()}>
|
||||||
|
{page * pageSize < posts.length ? 'Load More' : 'Show Less'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,19 +3,28 @@ 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
|
||||||
|
title={data.loading ? 'Loading...' : 'Related Articles'}
|
||||||
|
matches={data.loading ? undefined : data.data.length}
|
||||||
|
>
|
||||||
|
{
|
||||||
<PostsList
|
<PostsList
|
||||||
posts={articles.map((article) => ({
|
posts={
|
||||||
|
data.loading
|
||||||
|
? []
|
||||||
|
: data.data.map((article) => ({
|
||||||
slug: article.doc.slug,
|
slug: article.doc.slug,
|
||||||
date: article.doc.modifiedAt,
|
date: article.doc.modifiedAt,
|
||||||
title: article.doc.title,
|
title: article.doc.title,
|
||||||
|
@ -23,8 +32,11 @@ export default function RelatedArticles({ articles }: Props) {
|
||||||
mentions: article.doc.mentions,
|
mentions: article.doc.mentions,
|
||||||
tags: article.doc.tags,
|
tags: article.doc.tags,
|
||||||
coverImage: getArticleCover(article.doc.blocks),
|
coverImage: getArticleCover(article.doc.blocks),
|
||||||
}))}
|
}))
|
||||||
|
}
|
||||||
|
pageSize={4}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
</Section>
|
</Section>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,5 +22,6 @@ export const getSearchArticlesQuery = (args: UnbodyGetFilters = defaultArgs) =>
|
||||||
}
|
}
|
||||||
_additional{
|
_additional{
|
||||||
certainty
|
certainty
|
||||||
|
score
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
|
@ -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,29 +416,33 @@ class UnbodyService extends UnbodyClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if publushed is true, we add the published filter
|
||||||
|
// if published is false, we don't add the published filter
|
||||||
|
// if tags empty, we don't add the tags filter
|
||||||
|
// if tags not empty, we add the tags filter
|
||||||
|
|
||||||
|
if (published) {
|
||||||
|
whereFilters.push(Operands.WHERE_PUBLISHED())
|
||||||
|
}
|
||||||
|
|
||||||
if (tags.length > 0) {
|
if (tags.length > 0) {
|
||||||
queryFilters = {
|
whereFilters.push({
|
||||||
...queryFilters,
|
|
||||||
where: {
|
|
||||||
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.And,
|
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.And,
|
||||||
operands: tags.map((tag) => ({
|
operands: tags.map((tag) => ({
|
||||||
path: ['tags'],
|
path: ['tags'],
|
||||||
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.Like,
|
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.Like,
|
||||||
valueString: tag,
|
valueString: tag.toLowerCase(),
|
||||||
})),
|
})),
|
||||||
},
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (published) {
|
|
||||||
queryFilters = {
|
queryFilters = {
|
||||||
...queryFilters,
|
...queryFilters,
|
||||||
where: {
|
where: {
|
||||||
...((queryFilters as any).where || {}),
|
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.And,
|
||||||
...Operands.WHERE_PUBLISHED(),
|
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,
|
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue