client data fetching
This commit is contained in:
parent
32bbedfa17
commit
e63b018efa
|
@ -71,7 +71,7 @@ export const Header = (props: Props) => {
|
|||
onMount(() => {
|
||||
let scrollTop = window.scrollY
|
||||
|
||||
window.console.log(props.title)
|
||||
// window.console.log(props.title)
|
||||
|
||||
const handleScroll = () => {
|
||||
setIsScrollingBottom(window.scrollY > scrollTop)
|
||||
|
|
|
@ -1,11 +1,27 @@
|
|||
import { MainLayout } from '../Layouts/MainLayout'
|
||||
import { AllAuthorsView } from '../Views/AllAuthors'
|
||||
import type { PageProps } from '../types'
|
||||
import { createSignal, onMount, Show } from 'solid-js'
|
||||
import { loadAllAuthors } from '../../stores/zine/authors'
|
||||
import { t } from '../../utils/intl'
|
||||
|
||||
export const AllAuthorsPage = (props: PageProps) => {
|
||||
const [isLoaded, setIsLoaded] = createSignal<boolean>(Boolean(props.allAuthors))
|
||||
|
||||
onMount(async () => {
|
||||
if (isLoaded()) {
|
||||
return
|
||||
}
|
||||
|
||||
await loadAllAuthors()
|
||||
setIsLoaded(true)
|
||||
})
|
||||
|
||||
return (
|
||||
<MainLayout>
|
||||
<AllAuthorsView authors={props.authors} />
|
||||
<Show when={isLoaded()} fallback={t('Loading')}>
|
||||
<AllAuthorsView authors={props.allAuthors} />
|
||||
</Show>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,27 @@
|
|||
import { MainLayout } from '../Layouts/MainLayout'
|
||||
import { AllTopicsView } from '../Views/AllTopics'
|
||||
import type { PageProps } from '../types'
|
||||
import { createSignal, onMount, Show } from 'solid-js'
|
||||
import { t } from '../../utils/intl'
|
||||
import { loadAllTopics } from '../../stores/zine/topics'
|
||||
|
||||
export const AllTopicsPage = (props: PageProps) => {
|
||||
const [isLoaded, setIsLoaded] = createSignal<boolean>(Boolean(props.allTopics))
|
||||
|
||||
onMount(async () => {
|
||||
if (isLoaded()) {
|
||||
return
|
||||
}
|
||||
|
||||
await loadAllTopics()
|
||||
setIsLoaded(true)
|
||||
})
|
||||
|
||||
return (
|
||||
<MainLayout>
|
||||
<AllTopicsView topics={props.topics} />
|
||||
<Show when={isLoaded()} fallback={t('Loading')}>
|
||||
<AllTopicsView topics={props.allTopics} />
|
||||
</Show>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,26 +10,29 @@ import { useRouter } from '../../stores/router'
|
|||
export const ArticlePage = (props: PageProps) => {
|
||||
const sortedArticles = props.article ? [props.article] : []
|
||||
|
||||
const { getPage } = useRouter()
|
||||
const slug = createMemo(() => {
|
||||
const { getPage } = useRouter()
|
||||
|
||||
const page = getPage()
|
||||
const page = getPage()
|
||||
|
||||
if (page.route !== 'article') {
|
||||
throw new Error('ts guard')
|
||||
}
|
||||
if (page.route !== 'article') {
|
||||
throw new Error('ts guard')
|
||||
}
|
||||
|
||||
return page.params.slug
|
||||
})
|
||||
|
||||
const { articleEntities } = useArticlesStore({
|
||||
sortedArticles
|
||||
})
|
||||
|
||||
const article = createMemo<Shout>(() => articleEntities()[page.params.slug])
|
||||
const article = createMemo<Shout>(() => articleEntities()[slug()])
|
||||
|
||||
onMount(() => {
|
||||
const slug = page.params.slug
|
||||
const articleValue = articleEntities()[slug]
|
||||
const articleValue = articleEntities()[slug()]
|
||||
|
||||
if (!articleValue || !articleValue.body) {
|
||||
loadArticle({ slug })
|
||||
loadArticle({ slug: slug() })
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -1,11 +1,45 @@
|
|||
import { MainLayout } from '../Layouts/MainLayout'
|
||||
import { AuthorView } from '../Views/Author'
|
||||
import type { PageProps } from '../types'
|
||||
import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
|
||||
import { loadArticlesForAuthors, resetSortedArticles } from '../../stores/zine/articles'
|
||||
import { useRouter } from '../../stores/router'
|
||||
import { t } from '../../utils/intl'
|
||||
import { loadAuthor } from '../../stores/zine/authors'
|
||||
|
||||
export const AuthorPage = (props: PageProps) => {
|
||||
const [isLoaded, setIsLoaded] = createSignal(Boolean(props.authorArticles) && Boolean(props.author))
|
||||
|
||||
const slug = createMemo(() => {
|
||||
const { getPage } = useRouter()
|
||||
|
||||
const page = getPage()
|
||||
|
||||
if (page.route !== 'author') {
|
||||
throw new Error('ts guard')
|
||||
}
|
||||
|
||||
return page.params.slug
|
||||
})
|
||||
|
||||
onMount(async () => {
|
||||
if (isLoaded()) {
|
||||
return
|
||||
}
|
||||
|
||||
await loadArticlesForAuthors({ authorSlugs: [slug()] })
|
||||
await loadAuthor({ slug: slug() })
|
||||
|
||||
setIsLoaded(true)
|
||||
})
|
||||
|
||||
onCleanup(() => resetSortedArticles())
|
||||
|
||||
return (
|
||||
<MainLayout>
|
||||
<AuthorView author={props.author} authorArticles={props.articles} />
|
||||
<Show when={isLoaded()} fallback={t('Loading')}>
|
||||
<AuthorView author={props.author} authorArticles={props.authorArticles} authorSlug={slug()} />
|
||||
</Show>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,30 @@
|
|||
import { MainLayout } from '../Layouts/MainLayout'
|
||||
import { FeedView } from '../Views/Feed'
|
||||
import type { PageProps } from '../types'
|
||||
import { createSignal, onCleanup, onMount, Show } from 'solid-js'
|
||||
import { loadRecentArticles, resetSortedArticles } from '../../stores/zine/articles'
|
||||
import { t } from '../../utils/intl'
|
||||
|
||||
export const FeedPage = (props: PageProps) => {
|
||||
const [isLoaded, setIsLoaded] = createSignal(Boolean(props.feedArticles))
|
||||
|
||||
onMount(async () => {
|
||||
if (isLoaded()) {
|
||||
return
|
||||
}
|
||||
|
||||
await loadRecentArticles({ limit: 50, offset: 0 })
|
||||
|
||||
setIsLoaded(true)
|
||||
})
|
||||
|
||||
onCleanup(() => resetSortedArticles())
|
||||
|
||||
return (
|
||||
<MainLayout>
|
||||
<FeedView articles={props.articles} />
|
||||
<Show when={isLoaded()} fallback={t('Loading')}>
|
||||
<FeedView articles={props.feedArticles} />
|
||||
</Show>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,32 @@
|
|||
import { HomeView } from '../Views/Home'
|
||||
import { MainLayout } from '../Layouts/MainLayout'
|
||||
import type { PageProps } from '../types'
|
||||
import { createSignal, onCleanup, onMount, Show } from 'solid-js'
|
||||
import { t } from '../../utils/intl'
|
||||
import { loadPublishedArticles, resetSortedArticles } from '../../stores/zine/articles'
|
||||
import { loadRandomTopics } from '../../stores/zine/topics'
|
||||
|
||||
export const HomePage = (props: PageProps) => {
|
||||
const [isLoaded, setIsLoaded] = createSignal(Boolean(props.homeArticles) && Boolean(props.randomTopics))
|
||||
|
||||
onMount(async () => {
|
||||
if (isLoaded()) {
|
||||
return
|
||||
}
|
||||
|
||||
await loadPublishedArticles({ limit: 5, offset: 0 })
|
||||
await loadRandomTopics()
|
||||
|
||||
setIsLoaded(true)
|
||||
})
|
||||
|
||||
onCleanup(() => resetSortedArticles())
|
||||
|
||||
return (
|
||||
<MainLayout>
|
||||
<HomeView randomTopics={props.randomTopics} recentPublishedArticles={props.articles || []} />
|
||||
<Show when={isLoaded()} fallback={t('Loading')}>
|
||||
<HomeView randomTopics={props.randomTopics} recentPublishedArticles={props.homeArticles || []} />
|
||||
</Show>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,42 @@
|
|||
import { MainLayout } from '../Layouts/MainLayout'
|
||||
import { SearchView } from '../Views/Search'
|
||||
import type { PageProps } from '../types'
|
||||
import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
|
||||
import { loadSearchResults, resetSortedArticles } from '../../stores/zine/articles'
|
||||
import { t } from '../../utils/intl'
|
||||
import { useRouter } from '../../stores/router'
|
||||
|
||||
export const SearchPage = (props: PageProps) => {
|
||||
const [isLoaded, setIsLoaded] = createSignal(Boolean(props.searchResults))
|
||||
|
||||
const q = createMemo(() => {
|
||||
const { getPage } = useRouter()
|
||||
|
||||
const page = getPage()
|
||||
|
||||
if (page.route !== 'search') {
|
||||
throw new Error('ts guard')
|
||||
}
|
||||
|
||||
return page.params.q
|
||||
})
|
||||
|
||||
onMount(async () => {
|
||||
if (isLoaded()) {
|
||||
return
|
||||
}
|
||||
|
||||
await loadSearchResults({ query: q(), limit: 50, offset: 0 })
|
||||
setIsLoaded(true)
|
||||
})
|
||||
|
||||
onCleanup(() => resetSortedArticles())
|
||||
|
||||
return (
|
||||
<MainLayout>
|
||||
<SearchView results={props.searchResults || []} query={props.searchQuery} />
|
||||
<Show when={isLoaded()} fallback={t('Loading')}>
|
||||
<SearchView results={props.searchResults || []} query={props.searchQuery} />
|
||||
</Show>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,45 @@
|
|||
import { MainLayout } from '../Layouts/MainLayout'
|
||||
import { TopicView } from '../Views/Topic'
|
||||
import type { PageProps } from '../types'
|
||||
import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
|
||||
import { loadArticlesForTopics, resetSortedArticles } from '../../stores/zine/articles'
|
||||
import { useRouter } from '../../stores/router'
|
||||
import { t } from '../../utils/intl'
|
||||
import { loadTopic } from '../../stores/zine/topics'
|
||||
|
||||
export const TopicPage = (props: PageProps) => {
|
||||
const [isLoaded, setIsLoaded] = createSignal(Boolean(props.authorArticles) && Boolean(props.author))
|
||||
|
||||
const slug = createMemo(() => {
|
||||
const { getPage } = useRouter()
|
||||
|
||||
const page = getPage()
|
||||
|
||||
if (page.route !== 'author') {
|
||||
throw new Error('ts guard')
|
||||
}
|
||||
|
||||
return page.params.slug
|
||||
})
|
||||
|
||||
onMount(async () => {
|
||||
if (isLoaded()) {
|
||||
return
|
||||
}
|
||||
|
||||
await loadArticlesForTopics({ topicSlugs: [slug()] })
|
||||
await loadTopic({ slug: slug() })
|
||||
|
||||
setIsLoaded(true)
|
||||
})
|
||||
|
||||
onCleanup(() => resetSortedArticles())
|
||||
|
||||
return (
|
||||
<MainLayout>
|
||||
<TopicView topic={props.topic} topicArticles={props.articles} />
|
||||
<Show when={isLoaded()} fallback={t('Loading')}>
|
||||
<TopicView topic={props.topic} topicArticles={props.topicArticles} topicSlug={slug()} />
|
||||
</Show>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import { useRouter } from '../../stores/router'
|
|||
type AuthorProps = {
|
||||
authorArticles: Shout[]
|
||||
author: Author
|
||||
authorSlug: string
|
||||
// FIXME author topics fro server
|
||||
// topics: Topic[]
|
||||
}
|
||||
|
@ -30,18 +31,9 @@ export const AuthorView = (props: AuthorProps) => {
|
|||
})
|
||||
const { authorEntities } = useAuthorsStore({ authors: [props.author] })
|
||||
|
||||
const author = createMemo(() => authorEntities()[props.author.slug])
|
||||
const author = createMemo(() => authorEntities()[props.authorSlug])
|
||||
const { getSearchParams, changeSearchParam } = useRouter<AuthorPageSearchParams>()
|
||||
|
||||
//const slug = createMemo(() => author().slug)
|
||||
/*
|
||||
const slug = createMemo<string>(() => {
|
||||
let slug = props?.slug
|
||||
if (props?.slug.startsWith('@')) slug = slug.replace('@', '')
|
||||
return slug
|
||||
})
|
||||
*/
|
||||
|
||||
const title = createMemo(() => {
|
||||
const m = getSearchParams().by
|
||||
if (m === 'viewed') return t('Top viewed')
|
||||
|
@ -101,8 +93,8 @@ export const AuthorView = (props: AuthorProps) => {
|
|||
{/*/>*/}
|
||||
<Row3 articles={sortedArticles().slice(1, 4)} />
|
||||
<Row2 articles={sortedArticles().slice(4, 6)} />
|
||||
<Row3 articles={sortedArticles().slice(10, 13)} />
|
||||
<Row3 articles={sortedArticles().slice(13, 16)} />
|
||||
<Row3 articles={sortedArticles().slice(6, 9)} />
|
||||
<Row3 articles={sortedArticles().slice(9, 12)} />
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createMemo, For, onMount, Show } from 'solid-js'
|
||||
import { createEffect, createMemo, For, onMount, Show } from 'solid-js'
|
||||
import Banner from '../Discours/Banner'
|
||||
import { NavTopics } from '../Nav/Topics'
|
||||
import { Row5 } from '../Feed/Row5'
|
||||
|
@ -103,7 +103,7 @@ export const HomeView = (props: HomeProps) => {
|
|||
})
|
||||
|
||||
return (
|
||||
<Show when={locale()}>
|
||||
<Show when={locale() && sortedArticles().length > 0}>
|
||||
<NavTopics topics={randomTopics()} />
|
||||
|
||||
<Row5 articles={sortedArticles().slice(0, 5)} />
|
||||
|
|
|
@ -19,6 +19,7 @@ type TopicsPageSearchParams = {
|
|||
interface TopicProps {
|
||||
topic: Topic
|
||||
topicArticles: Shout[]
|
||||
topicSlug: string
|
||||
}
|
||||
|
||||
export const TopicView = (props: TopicProps) => {
|
||||
|
@ -29,7 +30,7 @@ export const TopicView = (props: TopicProps) => {
|
|||
|
||||
const { authorsByTopic } = useAuthorsStore()
|
||||
|
||||
const topic = createMemo(() => topicEntities()[props.topic.slug])
|
||||
const topic = createMemo(() => topicEntities()[props.topicSlug])
|
||||
|
||||
/*
|
||||
const slug = createMemo<string>(() => {
|
||||
|
@ -40,11 +41,10 @@ export const TopicView = (props: TopicProps) => {
|
|||
*/
|
||||
|
||||
const title = createMemo(() => {
|
||||
// FIXME
|
||||
// const m = getSearchParams().by
|
||||
// if (m === 'viewed') return t('Top viewed')
|
||||
// if (m === 'rating') return t('Top rated')
|
||||
// if (m === 'commented') return t('Top discussed')
|
||||
const m = getSearchParams().by
|
||||
if (m === 'viewed') return t('Top viewed')
|
||||
if (m === 'rating') return t('Top rated')
|
||||
if (m === 'commented') return t('Top discussed')
|
||||
return t('Top recent')
|
||||
})
|
||||
|
||||
|
|
|
@ -5,11 +5,14 @@ import type { Author, Shout, Topic } from '../graphql/types.gen'
|
|||
export type PageProps = {
|
||||
randomTopics?: Topic[]
|
||||
article?: Shout
|
||||
articles?: Shout[]
|
||||
authorArticles?: Shout[]
|
||||
topicArticles?: Shout[]
|
||||
homeArticles?: Shout[]
|
||||
feedArticles?: Shout[]
|
||||
author?: Author
|
||||
authors?: Author[]
|
||||
allAuthors?: Author[]
|
||||
topic?: Topic
|
||||
topics?: Topic[]
|
||||
allTopics?: Topic[]
|
||||
searchQuery?: string
|
||||
// other types?
|
||||
searchResults?: Shout[]
|
||||
|
|
|
@ -15,5 +15,5 @@ Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate'
|
|||
---
|
||||
|
||||
<Zine>
|
||||
<Root articles={articles} author={author} client:load />
|
||||
<Root authorArticles={articles} author={author} client:load />
|
||||
</Zine>
|
||||
|
|
|
@ -11,5 +11,5 @@ initRouter(pathname, search)
|
|||
---
|
||||
|
||||
<Zine>
|
||||
<Root authors={authors} client:load />
|
||||
<Root allAuthors={authors} client:load />
|
||||
</Zine>
|
||||
|
|
|
@ -12,5 +12,5 @@ const articles = await apiClient.getRecentArticles({ limit: 50 })
|
|||
---
|
||||
|
||||
<Zine>
|
||||
<Root articles={articles} client:load />
|
||||
<Root feedArticles={articles} client:load />
|
||||
</Zine>
|
||||
|
|
|
@ -15,6 +15,6 @@ Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate'
|
|||
---
|
||||
|
||||
<Zine>
|
||||
<Root randomTopics={randomTopics} articles={articles} client:load />
|
||||
<Root randomTopics={randomTopics} homeArticles={articles} client:load />
|
||||
</Zine>
|
||||
|
||||
|
|
|
@ -16,5 +16,5 @@ Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate'
|
|||
---
|
||||
|
||||
<Zine>
|
||||
<Root articles={articles} topic={topic} client:load />
|
||||
<Root topicArticles={articles} topic={topic} client:load />
|
||||
</Zine>
|
||||
|
|
|
@ -11,6 +11,6 @@ initRouter(pathname, search)
|
|||
---
|
||||
|
||||
<Zine>
|
||||
<Root topics={topics} client:load />
|
||||
<Root allTopics={topics} client:load />
|
||||
</Zine>
|
||||
|
||||
|
|
|
@ -151,6 +151,22 @@ export const loadPublishedArticles = async ({
|
|||
addSortedArticles(newArticles)
|
||||
}
|
||||
|
||||
export const loadArticlesForAuthors = async ({ authorSlugs }: { authorSlugs: string[] }): Promise<void> => {
|
||||
const articles = await apiClient.getArticlesForAuthors({ authorSlugs, limit: 50 })
|
||||
addArticles(articles)
|
||||
setSortedArticles(articles)
|
||||
}
|
||||
|
||||
export const loadArticlesForTopics = async ({ topicSlugs }: { topicSlugs: string[] }): Promise<void> => {
|
||||
const articles = await apiClient.getArticlesForTopics({ topicSlugs, limit: 50 })
|
||||
addArticles(articles)
|
||||
setSortedArticles(articles)
|
||||
}
|
||||
|
||||
export const resetSortedArticles = () => {
|
||||
setSortedArticles([])
|
||||
}
|
||||
|
||||
export const loadTopMonthArticles = async (): Promise<void> => {
|
||||
const articles = await apiClient.getTopMonthArticles()
|
||||
addArticles(articles)
|
||||
|
|
|
@ -46,6 +46,13 @@ const addAuthors = (authors: Author[]) => {
|
|||
})
|
||||
}
|
||||
|
||||
export const loadAuthor = async ({ slug }: { slug: string }): Promise<void> => {
|
||||
// TODO:
|
||||
const articles = await apiClient.getArticlesForAuthors({ authorSlugs: [slug], limit: 1 })
|
||||
const author = articles[0].authors.find((a) => a.slug === slug)
|
||||
addAuthors([author])
|
||||
}
|
||||
|
||||
export const addAuthorsByTopic = (newAuthorsByTopic: { [topicSlug: string]: Author[] }) => {
|
||||
const allAuthors = Object.values(newAuthorsByTopic).flat()
|
||||
addAuthors(allAuthors)
|
||||
|
|
|
@ -92,6 +92,18 @@ export const loadAllTopics = async (): Promise<void> => {
|
|||
addTopics(topics)
|
||||
}
|
||||
|
||||
export const loadRandomTopics = async (): Promise<void> => {
|
||||
const topics = await apiClient.getRandomTopics({ amount: 12 })
|
||||
setRandomTopics(topics)
|
||||
}
|
||||
|
||||
export const loadTopic = async ({ slug }: { slug: string }): Promise<void> => {
|
||||
// TODO:
|
||||
const articles = await apiClient.getArticlesForTopics({ topicSlugs: [slug], limit: 1 })
|
||||
const topic = articles[0].topics.find(({ slug: topicSlug }) => topicSlug === slug)
|
||||
addTopics([topic])
|
||||
}
|
||||
|
||||
type InitialState = {
|
||||
topics?: Topic[]
|
||||
randomTopics?: Topic[]
|
||||
|
|
|
@ -225,6 +225,10 @@ export const apiClient = {
|
|||
getPublishedArticles: async ({ limit = FEED_SIZE, offset }: { limit?: number; offset?: number }) => {
|
||||
const response = await publicGraphQLClient.query(articlesRecentPublished, { limit, offset }).toPromise()
|
||||
|
||||
if (response.error) {
|
||||
log.error('getPublishedArticles', response.error)
|
||||
}
|
||||
|
||||
return response.data.recentPublished
|
||||
},
|
||||
getAllTopics: async () => {
|
||||
|
|
Loading…
Reference in New Issue
Block a user