..
This commit is contained in:
parent
4d9a563a02
commit
90ebaa0099
|
@ -87,12 +87,14 @@ export const ArticleCard = (props: ArticleCardProps) => {
|
||||||
const { t, lang, formatDate } = useLocalize()
|
const { t, lang, formatDate } = useLocalize()
|
||||||
const { author } = useSession()
|
const { author } = useSession()
|
||||||
const mainTopicSlug = props.article.main_topic || ''
|
const mainTopicSlug = props.article.main_topic || ''
|
||||||
const mainTopic = props.article.topics.find((tpc: Topic) => tpc.slug === mainTopicSlug)
|
const mainTopic = props.article.topics?.find((tpc: Topic) => tpc.slug === mainTopicSlug)
|
||||||
const mainTopicTitle =
|
const mainTopicTitle =
|
||||||
mainTopicSlug && lang() === 'en' ? mainTopicSlug.replace('-', ' ') : mainTopic.title
|
mainTopicSlug && lang() === 'en' ? mainTopicSlug.replace('-', ' ') : mainTopic?.title || ''
|
||||||
|
|
||||||
const formattedDate = createMemo<string>(() => {
|
const formattedDate = createMemo<string>(() => {
|
||||||
return formatDate(new Date(props.article.created_at * 1000))
|
let r = ''
|
||||||
|
if (props.article.created_at) r = formatDate(new Date(props.article.created_at * 1000))
|
||||||
|
return r
|
||||||
})
|
})
|
||||||
|
|
||||||
const { title, subtitle } = getTitleAndSubtitle(props.article)
|
const { title, subtitle } = getTitleAndSubtitle(props.article)
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { Sidebar } from '../../Feed/Sidebar'
|
||||||
import styles from './Feed.module.scss'
|
import styles from './Feed.module.scss'
|
||||||
import stylesBeside from '../../Feed/Beside.module.scss'
|
import stylesBeside from '../../Feed/Beside.module.scss'
|
||||||
import stylesTopic from '../../Feed/CardTopic.module.scss'
|
import stylesTopic from '../../Feed/CardTopic.module.scss'
|
||||||
|
import { useSession } from '../../../context/session'
|
||||||
|
|
||||||
export const FEED_PAGE_SIZE = 20
|
export const FEED_PAGE_SIZE = 20
|
||||||
const UNRATED_ARTICLES_COUNT = 5
|
const UNRATED_ARTICLES_COUNT = 5
|
||||||
|
@ -129,7 +130,14 @@ export const FeedView = (props: Props) => {
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
loadMore()
|
loadMore()
|
||||||
// eslint-disable-next-line promise/catch-or-return
|
// eslint-disable-next-line promise/catch-or-return
|
||||||
Promise.all([loadUnratedArticles(), loadTopComments()]).finally(() => setIsRightColumnLoaded(true))
|
Promise.all([loadTopComments()]).finally(() => setIsRightColumnLoaded(true))
|
||||||
|
})
|
||||||
|
|
||||||
|
const { session } = useSession()
|
||||||
|
createEffect(() => {
|
||||||
|
if (session()?.access_token && !unratedArticles()) {
|
||||||
|
loadUnratedArticles()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
createEffect(
|
createEffect(
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import type { SearchResult } from '../../graphql/schema/core.gen'
|
import type { SearchResult } from '../../graphql/schema/core.gen'
|
||||||
|
|
||||||
import { Show, For, createSignal } from 'solid-js'
|
import { Show, For, createSignal, createEffect, onMount } from 'solid-js'
|
||||||
|
|
||||||
import '../../styles/Search.scss'
|
import '../../styles/Search.scss'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
import { useRouter } from '../../stores/router'
|
import { useRouter } from '../../stores/router'
|
||||||
import { loadShouts, useArticlesStore } from '../../stores/zine/articles'
|
import { loadShoutsSearch, useArticlesStore } from '../../stores/zine/articles'
|
||||||
import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll'
|
import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll'
|
||||||
import { ArticleCard } from '../Feed/ArticleCard'
|
import { ArticleCard } from '../Feed/ArticleCard'
|
||||||
|
import { apiClient } from '../../graphql/client/core'
|
||||||
|
|
||||||
type SearchPageSearchParams = {
|
type SearchPageSearchParams = {
|
||||||
by: '' | 'relevance' | 'rating'
|
by: '' | 'relevance' | 'rating'
|
||||||
|
@ -35,16 +36,33 @@ export const SearchView = (props: Props) => {
|
||||||
|
|
||||||
const loadMore = async () => {
|
const loadMore = async () => {
|
||||||
saveScrollPosition()
|
saveScrollPosition()
|
||||||
const { hasMore } = await loadShouts({
|
if (query()) {
|
||||||
filters: {},
|
console.log(query())
|
||||||
offset: offset(),
|
const { hasMore } = await loadShoutsSearch({
|
||||||
limit: LOAD_MORE_PAGE_SIZE,
|
text: query(),
|
||||||
})
|
offset: offset(),
|
||||||
setIsLoadMoreButtonVisible(hasMore)
|
limit: LOAD_MORE_PAGE_SIZE,
|
||||||
setOffset(offset() + LOAD_MORE_PAGE_SIZE)
|
})
|
||||||
|
setIsLoadMoreButtonVisible(hasMore)
|
||||||
|
setOffset(offset() + LOAD_MORE_PAGE_SIZE)
|
||||||
|
} else {
|
||||||
|
console.warn('[SaerchView] no query found')
|
||||||
|
}
|
||||||
restoreScrollPosition()
|
restoreScrollPosition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
const q = window.location.pathname.replace('/search/', '') || props.query
|
||||||
|
setQuery(q)
|
||||||
|
if (sortedArticles() && !sortedArticles()[0].created_at) {
|
||||||
|
// TODO: fill up articles data structures in search results
|
||||||
|
console.info('[SearchView] poor articles data structure found')
|
||||||
|
await loadMore()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: use score from the search results to sort by relevance
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="search-page wide-container">
|
<div class="search-page wide-container">
|
||||||
<form action="/search" class="search-form row">
|
<form action="/search" class="search-form row">
|
||||||
|
@ -94,21 +112,15 @@ export const SearchView = (props: Props) => {
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<Show when={isLoadMoreButtonVisible()}>
|
||||||
<a href="#" class="search__show-more">
|
<div class="col-md-6">
|
||||||
<span class="search__show-more-inner">{t('Load more')}</span>
|
<a href={`/search/${query()}`} onClick={loadMore} class="search__show-more">
|
||||||
</a>
|
<span class="search__show-more-inner">{t('Load more')}</span>
|
||||||
</div>
|
</a>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Show when={isLoadMoreButtonVisible()}>
|
|
||||||
<p class="load-more-container">
|
|
||||||
<button class="button" onClick={loadMore}>
|
|
||||||
{t('Load more')}
|
|
||||||
</button>
|
|
||||||
</p>
|
|
||||||
</Show>
|
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -195,8 +195,8 @@ export const apiClient = {
|
||||||
return resp.data.load_shouts_by
|
return resp.data.load_shouts_by
|
||||||
},
|
},
|
||||||
|
|
||||||
getShoutsSearch: async (args: QueryLoad_Shouts_SearchArgs) => {
|
getShoutsSearch: async ({ text, limit, offset }: QueryLoad_Shouts_SearchArgs) => {
|
||||||
const resp = await publicGraphQLClient.query(shoutsLoadSearch, args).toPromise()
|
const resp = await publicGraphQLClient.query(shoutsLoadSearch, { text, limit, offset }).toPromise()
|
||||||
if (resp.error) console.error(resp)
|
if (resp.error) console.error(resp)
|
||||||
|
|
||||||
return resp.data.load_shouts_search
|
return resp.data.load_shouts_search
|
||||||
|
|
|
@ -6,6 +6,19 @@ export default gql`
|
||||||
score
|
score
|
||||||
title
|
title
|
||||||
slug
|
slug
|
||||||
|
created_at
|
||||||
|
cover
|
||||||
|
topics {
|
||||||
|
slug
|
||||||
|
title
|
||||||
|
}
|
||||||
|
authors {
|
||||||
|
slug
|
||||||
|
name
|
||||||
|
pic
|
||||||
|
created_at
|
||||||
|
last_seen
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -85,18 +85,20 @@ const addArticles = (...args: Shout[][]) => {
|
||||||
const authorsByTopic = allArticles.reduce(
|
const authorsByTopic = allArticles.reduce(
|
||||||
(acc, article) => {
|
(acc, article) => {
|
||||||
const { authors, topics } = article
|
const { authors, topics } = article
|
||||||
|
if (topics) {
|
||||||
topics.forEach((topic) => {
|
// TODO: check if data can be consistent without topics and authors in article
|
||||||
if (!acc[topic.slug]) {
|
topics.forEach((topic) => {
|
||||||
acc[topic.slug] = []
|
if (!acc[topic.slug]) {
|
||||||
}
|
acc[topic.slug] = []
|
||||||
|
|
||||||
authors.forEach((author) => {
|
|
||||||
if (!acc[topic.slug].some((a) => a.slug === author.slug)) {
|
|
||||||
acc[topic.slug].push(author)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authors.forEach((author) => {
|
||||||
|
if (!acc[topic.slug].some((a) => a.slug === author.slug)) {
|
||||||
|
acc[topic.slug].push(author)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
|
|
||||||
return acc
|
return acc
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user