This commit is contained in:
Untone 2024-07-06 03:59:01 +03:00
parent 6104079f09
commit 2d89f62864
9 changed files with 103 additions and 128 deletions

View File

@ -1,4 +1,4 @@
import { A, redirect, useLocation, useNavigate, useSearchParams } from '@solidjs/router' import { A, redirect, useSearchParams } from '@solidjs/router'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { For, Show, createEffect, createSignal, onCleanup, onMount } from 'solid-js' import { For, Show, createEffect, createSignal, onCleanup, onMount } from 'solid-js'
import { useLocalize } from '~/context/localize' import { useLocalize } from '~/context/localize'
@ -54,8 +54,6 @@ export const Header = (props: Props) => {
const [isZineVisible, setIsZineVisible] = createSignal(false) const [isZineVisible, setIsZineVisible] = createSignal(false)
const [isFeedVisible, setIsFeedVisible] = createSignal(false) const [isFeedVisible, setIsFeedVisible] = createSignal(false)
const { session } = useSession() const { session } = useSession()
const loc = useLocation()
const navigate = useNavigate()
const toggleFixed = () => setFixed(!fixed()) const toggleFixed = () => setFixed(!fixed())
const tag = (topic: Topic) => const tag = (topic: Topic) =>
@ -148,11 +146,6 @@ export const Header = (props: Props) => {
}, time) }, time)
} }
const handleToggleMenuByLink = (event: MouseEvent, route: string) => {
event.preventDefault()
if (fixed()) toggleFixed()
if (loc.pathname !== route) navigate(route)
}
return ( return (
<header <header
class={styles.mainHeader} class={styles.mainHeader}
@ -198,14 +191,13 @@ export const Header = (props: Props) => {
<div class={styles.articleHeader}>{props.title}</div> <div class={styles.articleHeader}>{props.title}</div>
</Show> </Show>
<div class={clsx(styles.mainNavigation, { [styles.fixed]: fixed() })}> <div class={clsx(styles.mainNavigation, { [styles.fixed]: fixed() })}>
<ul class="view-switcher"> <ul class="view-switcher" onClick={() => !fixed() && toggleFixed()}>
<Link <Link
onMouseOver={() => toggleSubnavigation(true, setIsZineVisible)} onMouseOver={() => toggleSubnavigation(true, setIsZineVisible)}
onMouseOut={hideSubnavigation} onMouseOut={hideSubnavigation}
href="/" href="/"
active={isZineVisible()} active={isZineVisible()}
body={t('Journal')} body={t('Journal')}
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, '')}
/> />
<Link <Link
onMouseOver={() => toggleSubnavigation(true, setIsFeedVisible)} onMouseOver={() => toggleSubnavigation(true, setIsFeedVisible)}
@ -213,7 +205,6 @@ export const Header = (props: Props) => {
href="/feed" href="/feed"
active={isFeedVisible()} active={isFeedVisible()}
body={t('Feed')} body={t('Feed')}
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, 'feed')}
/> />
<Link <Link
onMouseOver={() => toggleSubnavigation(true, setIsTopicsVisible)} onMouseOver={() => toggleSubnavigation(true, setIsTopicsVisible)}
@ -221,14 +212,12 @@ export const Header = (props: Props) => {
href="/topic" href="/topic"
active={isTopicsVisible()} active={isTopicsVisible()}
body={t('Topics')} body={t('Topics')}
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, 'topic')}
/> />
<Link <Link
onMouseOver={(event?: MouseEvent) => hideSubnavigation(event, 0)} onMouseOver={(event?: MouseEvent) => hideSubnavigation(event, 0)}
onMouseOut={(event?: MouseEvent) => hideSubnavigation(event, 0)} onMouseOut={(event?: MouseEvent) => hideSubnavigation(event, 0)}
href="/author" href="/author"
body={t('Authors')} body={t('Authors')}
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, 'author')}
/> />
<Link <Link
onMouseOver={() => toggleSubnavigation(true, setIsKnowledgeBaseVisible)} onMouseOver={() => toggleSubnavigation(true, setIsKnowledgeBaseVisible)}
@ -236,7 +225,6 @@ export const Header = (props: Props) => {
href="/guide" href="/guide"
body={t('Knowledge base')} body={t('Knowledge base')}
active={isKnowledgeBaseVisible()} active={isKnowledgeBaseVisible()}
onClick={(event: MouseEvent) => handleToggleMenuByLink(event, 'guide')}
/> />
</ul> </ul>

View File

@ -20,7 +20,7 @@ export const Link = (props: Props) => {
classList={{ 'view-switcher__item--selected': props.href === `/${loc.pathname}` }} classList={{ 'view-switcher__item--selected': props.href === `/${loc.pathname}` }}
> >
<ConditionalWrapper <ConditionalWrapper
condition={props.href === `/${loc.pathname}`} condition={props.href !== `/${loc.pathname}`}
wrapper={(children) => <A href={props.href || '/'}>{children}</A>} wrapper={(children) => <A href={props.href || '/'}>{children}</A>}
> >
<span <span

View File

@ -1,7 +1,7 @@
import { Meta } from '@solidjs/meta' import { Meta } from '@solidjs/meta'
import { useSearchParams } from '@solidjs/router' import { useSearchParams } from '@solidjs/router'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { For, Show, createEffect, createMemo, createSignal, on } from 'solid-js' import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
import { Loading } from '~/components/_shared/Loading' import { Loading } from '~/components/_shared/Loading'
import { SearchField } from '~/components/_shared/SearchField' import { SearchField } from '~/components/_shared/SearchField'
import { useAuthors } from '~/context/authors' import { useAuthors } from '~/context/authors'
@ -31,10 +31,12 @@ export const AllAuthors = (props: Props) => {
const { t, lang } = useLocalize() const { t, lang } = useLocalize()
const [searchQuery, setSearchQuery] = createSignal('') const [searchQuery, setSearchQuery] = createSignal('')
const alphabet = createMemo(() => ABC[lang()] || ABC['ru']) const alphabet = createMemo(() => ABC[lang()] || ABC['ru'])
const [searchParams] = useSearchParams<{ by?: string }>() const [searchParams, changeSearchParams] = useSearchParams<{ by?: string }>()
const { authorsSorted, addAuthors, setAuthorsSort } = useAuthors() const { authorsSorted, addAuthors, setAuthorsSort } = useAuthors()
createEffect(on(() => searchParams?.by || 'name', setAuthorsSort, {}))
createEffect(on(() => props.authors || [], addAuthors, {})) onMount(() => !searchParams?.by && changeSearchParams({ by: 'name' }))
createEffect(on(() => searchParams?.by || 'name', setAuthorsSort || ((_) => null), {}))
createEffect(on(() => props.authors || [], addAuthors || ((_) => null), {}))
const filteredAuthors = createMemo(() => { const filteredAuthors = createMemo(() => {
const query = searchQuery().toLowerCase() const query = searchQuery().toLowerCase()
@ -165,7 +167,7 @@ export const AllAuthors = (props: Props) => {
</Show> </Show>
<Show when={searchParams?.by !== 'name' && props.isLoaded}> <Show when={searchParams?.by !== 'name' && props.isLoaded}>
<AuthorsList <AuthorsList
allAuthorsLength={authorsSorted()?.length || 0} allAuthorsLength={authorsSorted?.()?.length || 0}
searchQuery={searchQuery()} searchQuery={searchQuery()}
query={searchParams?.by === 'followers' ? 'followers' : 'shouts'} query={searchParams?.by === 'followers' ? 'followers' : 'shouts'}
/> />

View File

@ -1,19 +1,17 @@
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { For, Show, createEffect, createSignal, on } from 'solid-js' import { For, Show, createEffect, createSignal, on } from 'solid-js'
import { Loading } from '~/components/_shared/Loading' import { Loading } from '~/components/_shared/Loading'
import { SearchField } from '~/components/_shared/SearchField' import { SearchField } from '~/components/_shared/SearchField'
import { FollowsFilter, useFollowing } from '~/context/following' import { FollowsFilter, useFollowing } from '~/context/following'
import { useLocalize } from '~/context/localize' import { useLocalize } from '~/context/localize'
import { Author, Topic } from '~/graphql/schema/core.gen' import { Author, Topic } from '~/graphql/schema/core.gen'
import { dummyFilter } from '~/lib/dummyFilter' import { dummyFilter } from '~/lib/dummyFilter'
import stylesSettings from '../../../styles/FeedSettings.module.scss'
import { AuthorBadge } from '../../Author/AuthorBadge' import { AuthorBadge } from '../../Author/AuthorBadge'
import { ProfileSettingsNavigation } from '../../Nav/ProfileSettingsNavigation' import { ProfileSettingsNavigation } from '../../Nav/ProfileSettingsNavigation'
import styles from '../../ProfileSettings/Seetings.module.scss'
import { TopicBadge } from '../../Topic/TopicBadge' import { TopicBadge } from '../../Topic/TopicBadge'
import styles from '../../../pages/profile/Settings.module.scss'
import stylesSettings from '../../../styles/FeedSettings.module.scss'
export const ProfileSubscriptions = () => { export const ProfileSubscriptions = () => {
const { t, lang } = useLocalize() const { t, lang } = useLocalize()
const { follows } = useFollowing() const { follows } = useFollowing()

View File

@ -8,13 +8,17 @@ import {
on, on,
useContext useContext
} from 'solid-js' } from 'solid-js'
import loadAuthorByQuery from '~/graphql/query/core/author-by' import { getAuthor, loadAuthors, loadAuthorsAll } from '~/graphql/api/public'
import loadAuthorsAllQuery from '~/graphql/query/core/authors-all' import {
import loadAuthorsByQuery from '~/graphql/query/core/authors-load-by' Author,
import { Author, Maybe, QueryLoad_Authors_ByArgs, Shout, Topic } from '~/graphql/schema/core.gen' Maybe,
QueryGet_AuthorArgs,
QueryLoad_Authors_ByArgs,
Shout,
Topic
} from '~/graphql/schema/core.gen'
import { byStat } from '~/lib/sortby' import { byStat } from '~/lib/sortby'
import { useFeed } from './feed' import { useFeed } from './feed'
import { useGraphQL } from './graphql'
const TOP_AUTHORS_COUNT = 5 const TOP_AUTHORS_COUNT = 5
@ -35,7 +39,7 @@ type AuthorsContextType = {
authorsSorted: Accessor<Author[]> authorsSorted: Accessor<Author[]>
addAuthors: (authors: Author[]) => void addAuthors: (authors: Author[]) => void
addAuthor: (author: Author) => void addAuthor: (author: Author) => void
loadAuthor: (slug: string) => Promise<void> loadAuthor: (args: QueryGet_AuthorArgs) => Promise<void>
loadAuthors: (args: QueryLoad_Authors_ByArgs) => Promise<void> loadAuthors: (args: QueryLoad_Authors_ByArgs) => Promise<void>
topAuthors: Accessor<Author[]> topAuthors: Accessor<Author[]>
authorsByTopic: Accessor<{ [topicSlug: string]: Author[] }> authorsByTopic: Accessor<{ [topicSlug: string]: Author[] }>
@ -52,7 +56,6 @@ export const AuthorsProvider = (props: { children: JSX.Element }) => {
const [authorsSorted, setAuthorsSorted] = createSignal<Author[]>([]) const [authorsSorted, setAuthorsSorted] = createSignal<Author[]>([])
const [sortBy, setSortBy] = createSignal<SortFunction<Author>>() const [sortBy, setSortBy] = createSignal<SortFunction<Author>>()
const { feedByAuthor } = useFeed() const { feedByAuthor } = useFeed()
const { query } = useGraphQL()
const setAuthorsSort = (stat: string) => setSortBy((_) => byStat(stat) as SortFunction<Author>) const setAuthorsSort = (stat: string) => setSortBy((_) => byStat(stat) as SortFunction<Author>)
// Эффект для отслеживания изменений сигнала sortBy и обновления authorsSorted // Эффект для отслеживания изменений сигнала sortBy и обновления authorsSorted
@ -69,6 +72,7 @@ export const AuthorsProvider = (props: { children: JSX.Element }) => {
) )
const addAuthors = (newAuthors: Author[]) => { const addAuthors = (newAuthors: Author[]) => {
console.debug('[context.authors] storing new authors:', newAuthors)
setAuthors((prevAuthors) => { setAuthors((prevAuthors) => {
const updatedAuthors = { ...prevAuthors } const updatedAuthors = { ...prevAuthors }
newAuthors.forEach((author) => { newAuthors.forEach((author) => {
@ -86,13 +90,11 @@ export const AuthorsProvider = (props: { children: JSX.Element }) => {
}) })
} }
const loadAuthor = async (slug: string): Promise<void> => { const loadAuthor = async (opts: QueryGet_AuthorArgs): Promise<void> => {
try { try {
const resp = await query(loadAuthorByQuery, { slug }).toPromise() const fetcher = await getAuthor(opts)
if (resp) { const author = await fetcher()
const author = resp.data.get_author if (author) addAuthor(author as Author)
if (author?.id) addAuthor(author)
}
} catch (error) { } catch (error) {
console.error('Error loading author:', error) console.error('Error loading author:', error)
throw error throw error
@ -123,15 +125,13 @@ export const AuthorsProvider = (props: { children: JSX.Element }) => {
return sortedTopAuthors return sortedTopAuthors
}) })
const loadAuthors = async (args: QueryLoad_Authors_ByArgs): Promise<void> => { const loadAuthorsPage = async (args: QueryLoad_Authors_ByArgs): Promise<void> => {
try { try {
const resp = await query(loadAuthorsByQuery, { ...args }).toPromise() const fetcher = await loadAuthors(args)
if (resp) { const data = await fetcher()
const author = resp.data.get_author if (data) addAuthors(data as Author[])
if (author?.id) addAuthor(author)
}
} catch (error) { } catch (error) {
console.error('Error loading author:', error) console.error('Error loading authors:', error)
throw error throw error
} }
} }
@ -165,9 +165,11 @@ export const AuthorsProvider = (props: { children: JSX.Element }) => {
return result return result
}) })
const loadAllAuthors = async (): Promise<Author[]> => { const loadAllAuthors = async () => {
const resp = await query(loadAuthorsAllQuery, {}).toPromise() const fetcher = loadAuthorsAll()
return resp?.data?.get_authors_all || [] const data = await fetcher()
addAuthors(data || [])
return data || []
} }
const contextValue: AuthorsContextType = { const contextValue: AuthorsContextType = {
@ -177,7 +179,7 @@ export const AuthorsProvider = (props: { children: JSX.Element }) => {
addAuthors, addAuthors,
addAuthor, addAuthor,
loadAuthor, loadAuthor,
loadAuthors, loadAuthors: loadAuthorsPage,
topAuthors, topAuthors,
authorsByTopic, authorsByTopic,
setAuthorsSort setAuthorsSort

View File

@ -1,10 +1,8 @@
import { createLazyMemo } from '@solid-primitives/memo' import { createLazyMemo } from '@solid-primitives/memo'
import { makePersisted } from '@solid-primitives/storage' import { makePersisted } from '@solid-primitives/storage'
import { Accessor, JSX, createContext, createSignal, useContext } from 'solid-js' import { Accessor, JSX, createContext, createSignal, useContext } from 'solid-js'
import getShoutBySlug from '~/graphql/query/core/article-load' import { loadFollowedShouts } from '~/graphql/api/private'
import loadShoutsByQuery from '~/graphql/query/core/articles-load-by' import { loadShoutsSearch as fetchShoutsSearch, getShout, loadShouts } from '~/graphql/api/public'
import loadShoutsFeed from '~/graphql/query/core/articles-load-feed'
import loadShoutsSearchQuery from '~/graphql/query/core/articles-load-search'
import { import {
Author, Author,
LoadShoutsOptions, LoadShoutsOptions,
@ -51,7 +49,6 @@ export const FeedProvider = (props: { children: JSX.Element }) => {
const [topFeed, setTopFeed] = createSignal<Shout[]>([]) const [topFeed, setTopFeed] = createSignal<Shout[]>([])
const [topMonthFeed, setTopMonthFeed] = createSignal<Shout[]>([]) const [topMonthFeed, setTopMonthFeed] = createSignal<Shout[]>([])
const [feedByLayout, _setFeedByLayout] = createSignal<{ [layout: string]: Shout[] }>({}) const [feedByLayout, _setFeedByLayout] = createSignal<{ [layout: string]: Shout[] }>({})
const { query } = useGraphQL()
const [seen, setSeen] = makePersisted(createSignal<{ [slug: string]: number }>({}), { const [seen, setSeen] = makePersisted(createSignal<{ [slug: string]: number }>({}), {
name: 'discoursio-seen' name: 'discoursio-seen'
}) })
@ -133,9 +130,8 @@ export const FeedProvider = (props: { children: JSX.Element }) => {
// Load a single shout by slug and update the articleEntities and sortedFeed state // Load a single shout by slug and update the articleEntities and sortedFeed state
const loadShout = async (slug: string): Promise<void> => { const loadShout = async (slug: string): Promise<void> => {
const resp = await query(getShoutBySlug, { slug }).toPromise() const fetcher = await getShout({ slug })
if (!resp) return const newArticle = (await fetcher()) as Shout
const newArticle = resp?.data?.get_shout as Shout
addFeed([newArticle]) addFeed([newArticle])
const newArticleIndex = sortedFeed().findIndex((s) => s.id === newArticle.id) const newArticleIndex = sortedFeed().findIndex((s) => s.id === newArticle.id)
if (newArticleIndex >= 0) { if (newArticleIndex >= 0) {
@ -149,36 +145,26 @@ export const FeedProvider = (props: { children: JSX.Element }) => {
const loadShoutsBy = async ( const loadShoutsBy = async (
options: LoadShoutsOptions options: LoadShoutsOptions
): Promise<{ hasMore: boolean; newShouts: Shout[] }> => { ): Promise<{ hasMore: boolean; newShouts: Shout[] }> => {
const resp = await query(loadShoutsByQuery, { options }).toPromise() const fetcher = await loadShouts(options)
const result = resp?.data?.load_shouts_by || [] const result = (await fetcher()) || []
const hasMore = result.length !== options.limit + 1 && result.length !== 0 const hasMore = result.length !== options.limit + 1 && result.length !== 0
if (hasMore) result.splice(-1)
if (hasMore) {
result.splice(-1)
}
addFeed(result) addFeed(result)
return { hasMore, newShouts: result } return { hasMore, newShouts: result }
} }
const client = useGraphQL()
// Load the user's feed based on the provided options and update the articleEntities and sortedFeed state // Load the user's feed based on the provided options and update the articleEntities and sortedFeed state
const loadMyFeed = async ( const loadMyFeed = async (
options: LoadShoutsOptions options: LoadShoutsOptions
): Promise<{ hasMore: boolean; newShouts: Shout[] }> => { ): Promise<{ hasMore: boolean; newShouts: Shout[] }> => {
if (!options.limit) options.limit = 0 if (!options.limit) options.limit = 0
options.limit += 1 options.limit += 1
const resp = await query(loadShoutsFeed, options).toPromise() const fetcher = await loadFollowedShouts(client, options)
const result = resp?.data?.load_shouts_feed const result = (await fetcher()) || []
const hasMore = result.length === options.limit + 1 const hasMore = result.length === options.limit + 1
if (hasMore) result.splice(-1)
if (hasMore) { addFeed(result || [])
resp.data.splice(-1) return { hasMore, newShouts: result }
}
addFeed(resp.data || [])
return { hasMore, newShouts: resp.data.load_shouts_by }
} }
// Load shouts based on the search query and update the articleEntities and sortedFeed state // Load shouts based on the search query and update the articleEntities and sortedFeed state
@ -186,16 +172,11 @@ export const FeedProvider = (props: { children: JSX.Element }) => {
options: QueryLoad_Shouts_SearchArgs options: QueryLoad_Shouts_SearchArgs
): Promise<{ hasMore: boolean; newShouts: Shout[] }> => { ): Promise<{ hasMore: boolean; newShouts: Shout[] }> => {
options.limit = options?.limit || 0 + 1 options.limit = options?.limit || 0 + 1
const resp = await query(loadShoutsSearchQuery, options).toPromise() const fetcher = await fetchShoutsSearch(options)
const result = resp?.data?.load_shouts_search || [] const result = (await fetcher()) || []
const hasMore = result.length === (options?.limit || 0) + 1 const hasMore = result.length === (options?.limit || 0) + 1
if (hasMore) result.splice(-1)
if (hasMore) {
result.splice(-1)
}
addFeed(result) addFeed(result)
return { hasMore, newShouts: result } return { hasMore, newShouts: result }
} }
@ -216,8 +197,8 @@ export const FeedProvider = (props: { children: JSX.Element }) => {
order_by: 'likes_stat', order_by: 'likes_stat',
limit: 10 limit: 10
} }
const resp = await query(loadShoutsByQuery, options).toPromise() const fetcher = await loadShouts(options)
const result = resp?.data?.load_shouts_by || [] const result = (await fetcher()) || []
addFeed(result) addFeed(result)
setTopMonthFeed(result) setTopMonthFeed(result)
} }
@ -228,8 +209,8 @@ export const FeedProvider = (props: { children: JSX.Element }) => {
order_by: 'likes_stat', order_by: 'likes_stat',
limit: 10 limit: 10
} }
const resp = await query(loadShoutsByQuery, options).toPromise() const fetcher = await loadShouts(options)
const result = resp?.data?.load_shouts_by || [] const result = (await fetcher()) || []
addFeed(result) addFeed(result)
setTopFeed(result) setTopFeed(result)
} }

View File

@ -2,12 +2,15 @@ import { cache } from '@solidjs/router'
import { defaultClient } from '~/context/graphql' import { defaultClient } from '~/context/graphql'
import loadShoutsByQuery from '~/graphql/query/core/articles-load-by' import loadShoutsByQuery from '~/graphql/query/core/articles-load-by'
import loadShoutsSearchQuery from '~/graphql/query/core/articles-load-search' import loadShoutsSearchQuery from '~/graphql/query/core/articles-load-search'
import getAuthorQuery from '~/graphql/query/core/author-by'
import loadAuthorsAllQuery from '~/graphql/query/core/authors-all'
import loadAuthorsByQuery from '~/graphql/query/core/authors-load-by' import loadAuthorsByQuery from '~/graphql/query/core/authors-load-by'
import loadReactionsByQuery from '~/graphql/query/core/reactions-load-by' import loadReactionsByQuery from '~/graphql/query/core/reactions-load-by'
import loadTopicsQuery from '~/graphql/query/core/topics-all' import loadTopicsQuery from '~/graphql/query/core/topics-all'
import { import {
Author, Author,
LoadShoutsOptions, LoadShoutsOptions,
QueryGet_AuthorArgs,
QueryGet_ShoutArgs, QueryGet_ShoutArgs,
QueryLoad_Authors_ByArgs, QueryLoad_Authors_ByArgs,
QueryLoad_Reactions_ByArgs, QueryLoad_Reactions_ByArgs,
@ -29,11 +32,19 @@ export const loadAuthors = (options: QueryLoad_Authors_ByArgs) => {
const filter = new URLSearchParams(options.by as Record<string, string>) const filter = new URLSearchParams(options.by as Record<string, string>)
return cache(async () => { return cache(async () => {
const resp = await defaultClient.query(loadAuthorsByQuery, { ...options }).toPromise() const resp = await defaultClient.query(loadAuthorsByQuery, { ...options }).toPromise()
const result = resp?.data?.load_shouts_by const result = resp?.data?.load_authors_by
if (result) return result as Author[] if (result) return result as Author[]
}, `authors-${filter}-${page}`) }, `authors-${filter}-${page}`)
} }
export const loadAuthorsAll = () => {
return cache(async () => {
const resp = await defaultClient.query(loadAuthorsAllQuery, {}).toPromise()
const result = resp?.data?.get_authors_all
if (result) return result as Author[]
}, 'authors-all')
}
export const loadShouts = (options: LoadShoutsOptions) => { export const loadShouts = (options: LoadShoutsOptions) => {
const page = `${options.offset || 0}-${options.limit + (options.offset || 0)}` const page = `${options.offset || 0}-${options.limit + (options.offset || 0)}`
const filter = new URLSearchParams(options.filters as Record<string, string>) const filter = new URLSearchParams(options.filters as Record<string, string>)
@ -65,6 +76,17 @@ export const getShout = (options: QueryGet_ShoutArgs) => {
) )
} }
export const getAuthor = (options: QueryGet_AuthorArgs) => {
return cache(
async () => {
const resp = await defaultClient.query(getAuthorQuery, { ...options }).toPromise()
const result = resp?.data?.get_author
if (result) return result as Author
},
`author-${options?.slug || options?.author_id}`
)
}
export const loadShoutsSearch = (options: QueryLoad_Shouts_SearchArgs) => { export const loadShoutsSearch = (options: QueryLoad_Shouts_SearchArgs) => {
const page = `${options.offset || 0}-${(options?.limit || 0) + (options.offset || 0)}` const page = `${options.offset || 0}-${(options?.limit || 0) + (options.offset || 0)}`
return cache(async () => { return cache(async () => {

View File

@ -2,7 +2,7 @@ import { gql } from '@urql/core'
export default gql` export default gql`
query AuthorsAllQuery($by: AuthorsBy!, $limit: Int, $offset: Int) { query AuthorsAllQuery($by: AuthorsBy!, $limit: Int, $offset: Int) {
get_authors_nostat(by: $by, limit: $limit, offset: $offset) { get_authors(by: $by, limit: $limit, offset: $offset) {
id id
slug slug
name name

View File

@ -1,56 +1,38 @@
import { RouteDefinition, RouteLoadFuncArgs, type RouteSectionProps, createAsync } from '@solidjs/router' import { RouteDefinition, RouteLoadFuncArgs, type RouteSectionProps, createAsync } from '@solidjs/router'
import { Suspense, createEffect } from 'solid-js' import { Suspense, createReaction } from 'solid-js'
import { AllAuthors } from '~/components/Views/AllAuthors' import { AllAuthors } from '~/components/Views/AllAuthors'
import { AUTHORS_PER_PAGE } from '~/components/Views/AllAuthors/AllAuthors'
import { Loading } from '~/components/_shared/Loading' import { Loading } from '~/components/_shared/Loading'
import { PageLayout } from '~/components/_shared/PageLayout' import { PageLayout } from '~/components/_shared/PageLayout'
import { useAuthors } from '~/context/authors' import { useAuthors } from '~/context/authors'
import { useLocalize } from '~/context/localize' import { useLocalize } from '~/context/localize'
import { ReactionsProvider } from '~/context/reactions' import { ReactionsProvider } from '~/context/reactions'
import { loadAuthors } from '~/graphql/api/public' import { loadAuthors, loadAuthorsAll } from '~/graphql/api/public'
import { Author, QueryLoad_Authors_ByArgs } from '~/graphql/schema/core.gen' import { Author, AuthorsBy } from '~/graphql/schema/core.gen'
const fetchData = async () => { const fetchAuthorsWithStat = async (offset = 0, order?: string) => {
const opts: QueryLoad_Authors_ByArgs = { const by: AuthorsBy = { order }
by: { const authorsFetcher = loadAuthors({ by, offset, limit: AUTHORS_PER_PAGE })
after: undefined, return await authorsFetcher()
created_at: undefined,
last_seen: undefined,
name: undefined,
order: undefined,
slug: undefined,
stat: undefined,
topic: undefined
}
}
const topicsFetcher = loadAuthors(opts)
return await topicsFetcher()
} }
const AUTHORS_PER_PAGE = 20
const fetchAllAuthors = async () => {
const authorsAllFetcher = loadAuthorsAll()
return await authorsAllFetcher()
}
export const route = { export const route = {
load: (_args: RouteLoadFuncArgs) => { load: ({ location: { query } }: RouteLoadFuncArgs) =>
const opts: QueryLoad_Authors_ByArgs = { fetchAuthorsWithStat(Number.parseInt(query.offset), query.by || 'name')
by: {
after: undefined,
created_at: undefined,
last_seen: undefined,
name: undefined,
order: undefined,
slug: undefined,
stat: undefined,
topic: undefined
},
limit: AUTHORS_PER_PAGE,
offset: 0
}
return loadAuthors(opts)
}
} satisfies RouteDefinition } satisfies RouteDefinition
export default function AllAuthorsPage(props: RouteSectionProps<{ authors: Author[] }>) { export default function AllAuthorsPage(props: RouteSectionProps<{ authors: Author[] }>) {
const { t } = useLocalize() const { t } = useLocalize()
const { addAuthors } = useAuthors() const { authorsSorted, addAuthors } = useAuthors()
const authors = createAsync<Author[]>(async () => props.data.authors || (await fetchData())) const authors = createAsync<Author[]>(
createEffect(() => addAuthors(authors() || [])) async () => authorsSorted?.() || props.data.authors || (await fetchAllAuthors())
)
createReaction(() => typeof addAuthors === 'function' && addAuthors?.(authors() || []))
return ( return (
<PageLayout withPadding={true} title={`${t('Discours')} :: ${t('All authors')}`}> <PageLayout withPadding={true} title={`${t('Discours')} :: ${t('All authors')}`}>
<ReactionsProvider> <ReactionsProvider>