This commit is contained in:
tonyrewin 2022-09-09 15:18:09 +03:00
parent 44e0d11832
commit 4c59293678
5 changed files with 78 additions and 64 deletions

View File

@ -1,5 +1,5 @@
import { createEffect, createMemo, For, Show } from 'solid-js' import { createMemo, For, Show } from 'solid-js'
import { Shout, Topic, Author, Reaction, ReactionKind } from '../../graphql/types.gen' import { Shout, Reaction, ReactionKind, Topic, Author } from '../../graphql/types.gen'
import '../../styles/Feed.scss' import '../../styles/Feed.scss'
import Icon from '../Nav/Icon' import Icon from '../Nav/Icon'
import { byCreated, sortBy } from '../../utils/sortby' import { byCreated, sortBy } from '../../utils/sortby'
@ -9,10 +9,13 @@ import { t } from '../../utils/intl'
import { useStore } from '@nanostores/solid' import { useStore } from '@nanostores/solid'
import { session } from '../../stores/auth' import { session } from '../../stores/auth'
import CommentCard from '../Article/Comment' import CommentCard from '../Article/Comment'
import { loadRecentArticles, useArticlesStore } from '../../stores/zine/articles' import { loadMoreAll, useArticlesStore } from '../../stores/zine/articles'
import { useReactionsStore } from '../../stores/zine/reactions' import { useReactionsStore } from '../../stores/zine/reactions'
import { useAuthorsStore } from '../../stores/zine/authors' import { useAuthorsStore } from '../../stores/zine/authors'
import { FeedSidebar } from '../Feed/Sidebar' import { FeedSidebar } from '../Feed/Sidebar'
import { useTopicsStore } from '../../stores/zine/topics'
import { unique } from '../../utils'
import { AuthorCard } from '../Author/Card'
interface FeedProps { interface FeedProps {
recentArticles: Shout[] recentArticles: Shout[]
@ -27,19 +30,23 @@ const AUTHORSHIP_REACTIONS = [
] ]
export const FeedPage = (props: FeedProps) => { export const FeedPage = (props: FeedProps) => {
const [getPage, setPage] = createSignal(1)
// state // state
const { getSortedArticles: articles } = useArticlesStore({ sortedArticles: props.articles }) const { getSortedArticles: articles } = useArticlesStore({ sortedArticles: props.recentArticles })
const reactions = useReactionsStore(props.reactions) const reactions = useReactionsStore(props.reactions)
const { const {
// getAuthorEntities: authorsBySlug, // getAuthorEntities: authorsBySlug,
getSortedAuthors: authors getSortedAuthors: authors
} = useAuthorsStore() // test if it catches preloaded authors } = useAuthorsStore() // test if it catches preloaded authors
const auth = useStore(session) const auth = useStore(session)
const topics = createMemo(() => {
const ttt = []
articles().forEach((s: Shout) => s.topics.forEach((tpc: Topic) => ttt.push(tpc)))
return unique(ttt)
})
const { getSortedTopics } = useTopicsStore({ topics: topics() })
// derived // derived
const topReactions = createMemo(() => sortBy(reactions(), byCreated)) const topReactions = createMemo(() => sortBy(reactions(), byCreated))
const topAuthors = createMemo(() => sortBy(authors(), 'shouts'))
// note this became synthetic // note this became synthetic
// methods // methods
@ -49,19 +56,11 @@ export const FeedPage = (props: FeedProps) => {
// TODO: list of articles where you are co-author // TODO: list of articles where you are co-author
// TODO: preload proposals // TODO: preload proposals
// TODO: (maybe?) and changes history // TODO: (maybe?) and changes history
console.debug(reactions().filter((r) => r.kind in AUTHORSHIP_REACTIONS)) console.debug(reactions().filter((r) => r.kind in AUTHORSHIP_REACTIONS)) // 2 community self-regulating mechanics
// TODO: query all new posts to be rated for publishing
const loadMore = () => { // TODO: query all reactions where user is in authors list
setPage(getPage() + 1) return []
//const size = props['size'] || 50
//const page = (props.page || 1) + 1
// TODO: loadFeed({ page, size })
}
createEffect(() => {
loadRecentArticles({ page: getPage() })
}) })
return ( return (
<> <>
<div class="container feed"> <div class="container feed">
@ -88,8 +87,8 @@ export const FeedPage = (props: FeedProps) => {
</li> </li>
</ul> </ul>
<Show when={getSortedArticles().length > 0}> <Show when={articles().length > 0}>
<For each={getSortedArticles().slice(0, 4)}> <For each={articles().slice(0, 4)}>
{(article) => <ArticleCard article={article} settings={{ isFeedMode: true }} />} {(article) => <ArticleCard article={article} settings={{ isFeedMode: true }} />}
</For> </For>
@ -101,18 +100,17 @@ export const FeedPage = (props: FeedProps) => {
</a> </a>
</div> </div>
{/*FIXME NOW*/} <ul class="beside-column">
{/*<ul class="beside-column">*/} <For each={topAuthors()}>
{/* <For each={topAuthors()}>*/} {(author: Author) => (
{/* {(author) => (*/} <li>
{/* <li>*/} <AuthorCard author={author} compact={true} hasLink={true} />
{/* <AuthorCard author={author} compact={true} hasLink={true} />*/} </li>
{/* </li>*/} )}
{/* )}*/} </For>
{/* </For>*/} </ul>
{/*</ul>*/}
<For each={getSortedArticles().slice(4)}> <For each={articles().slice(4)}>
{(article) => <ArticleCard article={article} settings={{ isFeedMode: true }} />} {(article) => <ArticleCard article={article} settings={{ isFeedMode: true }} />}
</For> </For>
</Show> </Show>
@ -129,10 +127,10 @@ export const FeedPage = (props: FeedProps) => {
{(c: Reaction) => <CommentCard comment={c} compact={true} />} {(c: Reaction) => <CommentCard comment={c} compact={true} />}
</For> </For>
</section> </section>
<Show when={getTopTopics().length > 0}> <Show when={getSortedTopics().length > 0}>
<section class="feed-topics"> <section class="feed-topics">
<h4>{t('Topics')}</h4> <h4>{t('Topics')}</h4>
<For each={getTopTopics()}> <For each={getSortedTopics().slice(0, 5)}>
{(topic) => <TopicCard topic={topic} subscribeButtonBottom={true} />} {(topic) => <TopicCard topic={topic} subscribeButtonBottom={true} />}
</For> </For>
</section> </section>
@ -140,7 +138,7 @@ export const FeedPage = (props: FeedProps) => {
</aside> </aside>
</div> </div>
<p class="load-more-container"> <p class="load-more-container">
<button class="button" onClick={loadMore}> <button class="button" onClick={loadMoreAll}>
{t('Load more')} {t('Load more')}
</button> </button>
</p> </p>

View File

@ -23,7 +23,7 @@ import {
topCommented topCommented
} from '../../stores/zine/top' } from '../../stores/zine/top'
import { useTopicsStore } from '../../stores/zine/topics' import { useTopicsStore } from '../../stores/zine/topics'
import { useArticlesStore } from '../../stores/zine/articles' import { loadMorePublished, useArticlesStore } from '../../stores/zine/articles'
type HomeProps = { type HomeProps = {
randomTopics: Topic[] randomTopics: Topic[]
@ -86,12 +86,6 @@ export const HomePage = (props: HomeProps) => {
console.info('[home] mounted') console.info('[home] mounted')
}) })
const loadMore = () => {
const size = props['size'] || 50
const page = (props.page || 1) + 1
console.log('[home] try to load ' + page + ' page with ' + size + ' items')
// FIXME: loadPublished({ page, size })
}
return ( return (
<Suspense fallback={t('Loading')}> <Suspense fallback={t('Loading')}>
<Show when={Boolean(articles())}> <Show when={Boolean(articles())}>
@ -145,7 +139,7 @@ export const HomePage = (props: HomeProps) => {
<Row3 articles={articles().slice(31, 34) as []} /> <Row3 articles={articles().slice(31, 34) as []} />
<p class="load-more-container"> <p class="load-more-container">
<button class="button" onClick={loadMore}> <button class="button" onClick={loadMorePublished}>
{t('Load more')} {t('Load more')}
</button> </button>
</p> </p>

View File

@ -44,8 +44,8 @@ router.listen((r) => setResource(r.path))
// signals // signals
const [pageState, setPage] = createSignal() const [getPage, setPage] = createSignal<number>(1)
const [sizeState, setSize] = createSignal() const [getSize, setSize] = createSignal<number>(10)
export type SortBy = export type SortBy =
| 'rating' | 'rating'
@ -109,8 +109,8 @@ const updateParams = () => {
// get request search query params // get request search query params
const paramsDict = { const paramsDict = {
by: by(), // sort name by: by(), // sort name
page: pageState(), // page number page: getPage(), // page number
size: sizeState() // entries per page size: getSize() // entries per page
// TODO: add q for /search // TODO: add q for /search
} }
console.log('[router] updated url with stored params') console.log('[router] updated url with stored params')
@ -138,4 +138,4 @@ if (!isServer) {
createEffect(() => router.open(window.location.pathname), [window.location]) createEffect(() => router.open(window.location.pathname), [window.location])
} }
export { slug, route, setPage, setSize, by, setBy, resource } export { slug, route, setPage, getPage, getSize, setSize, by, setBy, resource }

View File

@ -3,6 +3,7 @@ import type { Shout } from '../../graphql/types.gen'
import type { WritableAtom } from 'nanostores' import type { WritableAtom } from 'nanostores'
import { useStore } from '@nanostores/solid' import { useStore } from '@nanostores/solid'
import { apiClient } from '../../utils/apiClient' import { apiClient } from '../../utils/apiClient'
import { getPage, setPage } from '../router'
let articleEntitiesStore: WritableAtom<Record<string, Shout>> let articleEntitiesStore: WritableAtom<Record<string, Shout>>
let sortedArticlesStore: WritableAtom<Shout[]> let sortedArticlesStore: WritableAtom<Shout[]>
@ -69,8 +70,13 @@ const addArticles = (articles: Shout[]) => {
} }
} }
export const loadRecentArticles = async ({ page }: { page: number }): Promise<void> => { export const loadRecentAllArticles = async ({ page }: { page: number }): Promise<void> => {
const newArticles = await apiClient.getRecentArticles({ page }) const newArticles = await apiClient.getRecentAllArticles({ page, size: 50 })
addArticles(newArticles)
}
export const loadRecentPublishedArticles = async ({ page }: { page: number }): Promise<void> => {
const newArticles = await apiClient.getRecentPublishedArticles({ page, size: 50 })
addArticles(newArticles) addArticles(newArticles)
} }
@ -88,3 +94,13 @@ export const useArticlesStore = ({ sortedArticles }: InitialState) => {
return { getArticleEntities, getSortedArticles, getArticlesByTopics, getArticlesByAuthors } return { getArticleEntities, getSortedArticles, getArticlesByTopics, getArticlesByAuthors }
} }
export const loadMoreAll = () => {
setPage(getPage() + 1)
loadRecentAllArticles({ page: getPage() + 1 })
}
export const loadMorePublished = () => {
setPage(getPage() + 1)
loadRecentPublishedArticles({ page: getPage() + 1 })
}

View File

@ -45,11 +45,6 @@ export const apiClient = {
const response = await publicGraphQLClient.query(articlesTopMonth, { page: 1, size: 10 }).toPromise() const response = await publicGraphQLClient.query(articlesTopMonth, { page: 1, size: 10 }).toPromise()
return response.data.articlesTopMonth return response.data.articlesTopMonth
}, },
getRecentPublishedArticles: async () => {
const response = await publicGraphQLClient.query(articlesRecentPublished, {}).toPromise()
return response.data.recentPublished
},
getRandomTopics: async () => { getRandomTopics: async () => {
const response = await publicGraphQLClient.query(topicsRandomQuery, {}).toPromise() const response = await publicGraphQLClient.query(topicsRandomQuery, {}).toPromise()
@ -74,7 +69,7 @@ export const apiClient = {
return response.data.searchQuery return response.data.searchQuery
}, },
getRecentArticles: async ({ getRecentAllArticles: async ({
page = 1, page = 1,
size = FEED_PAGE_SIZE size = FEED_PAGE_SIZE
}: { }: {
@ -90,6 +85,22 @@ export const apiClient = {
return response.data.recentAll return response.data.recentAll
}, },
getRecentPublishedArticles: async ({
page = 1,
size = FEED_PAGE_SIZE
}: {
page?: number
size?: number
}): Promise<Shout[]> => {
const response = await publicGraphQLClient
.query(articlesRecentPublished, {
page,
size
})
.toPromise()
return response.data.recentAll
},
getArticlesForTopics: async ({ getArticlesForTopics: async ({
topicSlugs, topicSlugs,
page = 1, page = 1,
@ -181,12 +192,6 @@ export const apiClient = {
}, },
// feeds // feeds
getPublishedShouts: async ({ page, size }: { page: number; size: number }) => {
const response = await publicGraphQLClient.query(articlesRecentPublished, { page, size }).toPromise()
return response.data.recentPublished
},
getAllTopics: async () => { getAllTopics: async () => {
const response = await publicGraphQLClient.query(topicsAll, {}).toPromise() const response = await publicGraphQLClient.query(topicsAll, {}).toPromise()
return response.data.topicsAll return response.data.topicsAll
@ -203,6 +208,9 @@ export const apiClient = {
return response.data?.getShoutBySlug return response.data?.getShoutBySlug
}, },
// reactions
getReactionsForShouts: async ({ getReactionsForShouts: async ({
shoutSlugs, shoutSlugs,
page = 1, page = 1,
@ -242,8 +250,6 @@ export const apiClient = {
return response.data.reactionsByShout return response.data.reactionsByShout
}, },
// reactions
createReaction: async ({ reaction }) => { createReaction: async ({ reaction }) => {
const response = await privateGraphQLClient const response = await privateGraphQLClient
.mutation(reactionCreate, { reaction }) .mutation(reactionCreate, { reaction })