showup
This commit is contained in:
parent
6104079f09
commit
2d89f62864
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 () => {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user